Qwt User's Guide 6.2.0

qwt_plot_rasteritem.cpp
1 /******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10 #include "qwt_plot_rasteritem.h"
11 #include "qwt_scale_map.h"
12 #include "qwt_painter.h"
13 #include "qwt_text.h"
14 #include "qwt_interval.h"
15 #include "qwt_math.h"
16
17 #include <qpainter.h>
18 #include <qpaintengine.h>
19 #include <qthread.h>
20 #include <qfuture.h>
21 #include <qtconcurrentrun.h>
22
23 #include <limits>
24
25 class QwtPlotRasterItem::PrivateData
26 {
27 public:
28 PrivateData()
29 : alpha( -1 )
30 , paintAttributes( QwtPlotRasterItem::PaintInDeviceResolution )
31 {
32 cache.policy = QwtPlotRasterItem::NoCache;
33 }
34
35 int alpha;
36
37 QwtPlotRasterItem::PaintAttributes paintAttributes;
38
39 struct ImageCache
40 {
41 QwtPlotRasterItem::CachePolicy policy;
42 QRectF area;
43 QSizeF size;
44 QImage image;
45 } cache;
46 };
47
48
49 static QRectF qwtAlignRect(const QRectF& rect)
50 {
51 QRectF r;
52 r.setLeft( qRound( rect.left() ) );
53 r.setRight( qRound( rect.right() ) );
54 r.setTop( qRound( rect.top() ) );
55 r.setBottom( qRound( rect.bottom() ) );
56
57 return r;
58 }
59
60 static QRectF qwtStripRect(const QRectF& rect, const QRectF& area,
61 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
62 const QwtInterval& xInterval, const QwtInterval& yInterval)
63 {
64 QRectF r = rect;
65 if ( xInterval.borderFlags() & QwtInterval::ExcludeMinimum )
66 {
67 if ( area.left() <= xInterval.minValue() )
68 {
69 if ( xMap.isInverting() )
70 r.adjust(0, 0, -1, 0);
71 else
72 r.adjust(1, 0, 0, 0);
73 }
74 }
75
76 if ( xInterval.borderFlags() & QwtInterval::ExcludeMaximum )
77 {
78 if ( area.right() >= xInterval.maxValue() )
79 {
80 if ( xMap.isInverting() )
81 r.adjust(1, 0, 0, 0);
82 else
83 r.adjust(0, 0, -1, 0);
84 }
85 }
86
87 if ( yInterval.borderFlags() & QwtInterval::ExcludeMinimum )
88 {
89 if ( area.top() <= yInterval.minValue() )
90 {
91 if ( yMap.isInverting() )
92 r.adjust(0, 0, 0, -1);
93 else
94 r.adjust(0, 1, 0, 0);
95 }
96 }
97
98 if ( yInterval.borderFlags() & QwtInterval::ExcludeMaximum )
99 {
100 if ( area.bottom() >= yInterval.maxValue() )
101 {
102 if ( yMap.isInverting() )
103 r.adjust(0, 1, 0, 0);
104 else
105 r.adjust(0, 0, 0, -1);
106 }
107 }
108
109 return r;
110 }
111
112 static QImage qwtExpandImage(const QImage& image,
113 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
114 const QRectF& area, const QRectF& area2, const QRectF& paintRect,
115 const QwtInterval& xInterval, const QwtInterval& yInterval )
116 {
117 const QRectF strippedRect = qwtStripRect(paintRect, area2,
118 xMap, yMap, xInterval, yInterval);
119 const QSize sz = strippedRect.toRect().size();
120
121 const int w = image.width();
122 const int h = image.height();
123
124 const QRectF r = QwtScaleMap::transform(xMap, yMap, area).normalized();
125 const double pw = ( r.width() - 1 ) / w;
126 const double ph = ( r.height() - 1 ) / h;
127
128 double px0, py0;
129 if ( !xMap.isInverting() )
130 {
131 px0 = xMap.transform( area2.left() );
132 px0 = qRound( px0 );
133 px0 = px0 - xMap.transform( area.left() );
134 }
135 else
136 {
137 px0 = xMap.transform( area2.right() );
138 px0 = qRound( px0 );
139 px0 -= xMap.transform( area.right() );
140
141 px0 -= 1.0;
142 }
143 px0 += strippedRect.left() - paintRect.left();
144
145 if ( !yMap.isInverting() )
146 {
147 py0 = yMap.transform( area2.top() );
148 py0 = qRound( py0 );
149 py0 -= yMap.transform( area.top() );
150 }
151 else
152 {
153 py0 = yMap.transform( area2.bottom() );
154 py0 = qRound( py0 );
155 py0 -= yMap.transform( area.bottom() );
156
157 py0 -= 1.0;
158 }
159 py0 += strippedRect.top() - paintRect.top();
160
161 QImage expanded( sz, image.format() );
162 if ( image.format() == QImage::Format_Indexed8 )
163 expanded.setColorTable( image.colorTable() );
164
165 switch( image.depth() )
166 {
167 case 32:
168 {
169 for ( int y1 = 0; y1 < h; y1++ )
170 {
171 int yy1;
172 if ( y1 == 0 )
173 {
174 yy1 = 0;
175 }
176 else
177 {
178 yy1 = qRound( y1 * ph - py0 );
179 if ( yy1 < 0 )
180 yy1 = 0;
181 }
182
183 int yy2;
184 if ( y1 == h - 1 )
185 {
186 yy2 = sz.height();
187 }
188 else
189 {
190 yy2 = qRound( ( y1 + 1 ) * ph - py0 );
191 if ( yy2 > sz.height() )
192 yy2 = sz.height();
193 }
194
195 const quint32* line1 =
196 reinterpret_cast< const quint32* >( image.scanLine( y1 ) );
197
198 for ( int x1 = 0; x1 < w; x1++ )
199 {
200 int xx1;
201 if ( x1 == 0 )
202 {
203 xx1 = 0;
204 }
205 else
206 {
207 xx1 = qRound( x1 * pw - px0 );
208 if ( xx1 < 0 )
209 xx1 = 0;
210 }
211
212 int xx2;
213 if ( x1 == w - 1 )
214 {
215 xx2 = sz.width();
216 }
217 else
218 {
219 xx2 = qRound( ( x1 + 1 ) * pw - px0 );
220 if ( xx2 > sz.width() )
221 xx2 = sz.width();
222 }
223
224 const quint32 rgb( line1[x1] );
225 for ( int y2 = yy1; y2 < yy2; y2++ )
226 {
227 quint32* line2 = reinterpret_cast< quint32* >(
228 expanded.scanLine( y2 ) );
229
230 for ( int x2 = xx1; x2 < xx2; x2++ )
231 line2[x2] = rgb;
232 }
233 }
234 }
235 break;
236 }
237 case 8:
238 {
239 for ( int y1 = 0; y1 < h; y1++ )
240 {
241 int yy1;
242 if ( y1 == 0 )
243 {
244 yy1 = 0;
245 }
246 else
247 {
248 yy1 = qRound( y1 * ph - py0 );
249 if ( yy1 < 0 )
250 yy1 = 0;
251 }
252
253 int yy2;
254 if ( y1 == h - 1 )
255 {
256 yy2 = sz.height();
257 }
258 else
259 {
260 yy2 = qRound( ( y1 + 1 ) * ph - py0 );
261 if ( yy2 > sz.height() )
262 yy2 = sz.height();
263 }
264
265 const uchar* line1 = image.scanLine( y1 );
266
267 for ( int x1 = 0; x1 < w; x1++ )
268 {
269 int xx1;
270 if ( x1 == 0 )
271 {
272 xx1 = 0;
273 }
274 else
275 {
276 xx1 = qRound( x1 * pw - px0 );
277 if ( xx1 < 0 )
278 xx1 = 0;
279 }
280
281 int xx2;
282 if ( x1 == w - 1 )
283 {
284 xx2 = sz.width();
285 }
286 else
287 {
288 xx2 = qRound( ( x1 + 1 ) * pw - px0 );
289 if ( xx2 > sz.width() )
290 xx2 = sz.width();
291 }
292
293 for ( int y2 = yy1; y2 < yy2; y2++ )
294 {
295 uchar* line2 = expanded.scanLine( y2 );
296 memset( line2 + xx1, line1[x1], xx2 - xx1 );
297 }
298 }
299 }
300 break;
301 }
302 default:
303 expanded = image;
304 }
305
306 return expanded;
307 }
308
309 static QRectF qwtExpandToPixels(const QRectF& rect, const QRectF& pixelRect)
310 {
311 const double pw = pixelRect.width();
312 const double ph = pixelRect.height();
313
314 const double dx1 = pixelRect.left() - rect.left();
315 const double dx2 = pixelRect.right() - rect.right();
316 const double dy1 = pixelRect.top() - rect.top();
317 const double dy2 = pixelRect.bottom() - rect.bottom();
318
319 QRectF r;
320 r.setLeft( pixelRect.left() - qwtCeil( dx1 / pw ) * pw );
321 r.setTop( pixelRect.top() - qwtCeil( dy1 / ph ) * ph );
322 r.setRight( pixelRect.right() - qwtFloor( dx2 / pw ) * pw );
323 r.setBottom( pixelRect.bottom() - qwtFloor( dy2 / ph ) * ph );
324
325 return r;
326 }
327
328 static void qwtTransformMaps( const QTransform& tr,
329 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
330 QwtScaleMap& xxMap, QwtScaleMap& yyMap )
331 {
332 const QPointF p1 = tr.map( QPointF( xMap.p1(), yMap.p1() ) );
333 const QPointF p2 = tr.map( QPointF( xMap.p2(), yMap.p2() ) );
334
335 xxMap = xMap;
336 xxMap.setPaintInterval( p1.x(), p2.x() );
337
338 yyMap = yMap;
339 yyMap.setPaintInterval( p1.y(), p2.y() );
340 }
341
342 static void qwtAdjustMaps( QwtScaleMap& xMap, QwtScaleMap& yMap,
343 const QRectF& area, const QRectF& paintRect)
344 {
345 double sx1 = area.left();
346 double sx2 = area.right();
347 if ( xMap.isInverting() )
348 qSwap(sx1, sx2);
349
350 double sy1 = area.top();
351 double sy2 = area.bottom();
352
353 if ( yMap.isInverting() )
354 qSwap(sy1, sy2);
355
356 xMap.setPaintInterval(paintRect.left(), paintRect.right() );
357 xMap.setScaleInterval(sx1, sx2);
358
359 yMap.setPaintInterval(paintRect.top(), paintRect.bottom() );
360 yMap.setScaleInterval(sy1, sy2);
361 }
362
363 static bool qwtUseCache( QwtPlotRasterItem::CachePolicy policy,
364 const QPainter* painter )
365 {
366 bool doCache = false;
367
368 if ( policy == QwtPlotRasterItem::PaintCache )
369 {
370 // Caching doesn't make sense, when the item is
371 // not painted to screen
372
373 switch ( painter->paintEngine()->type() )
374 {
375 case QPaintEngine::SVG:
376 case QPaintEngine::Pdf:
377 #if QT_VERSION < 0x060000
378 case QPaintEngine::PostScript:
379 #endif
380 case QPaintEngine::MacPrinter:
381 case QPaintEngine::Picture:
382 break;
383 default:;
384 doCache = true;
385 }
386 }
387
388 return doCache;
389 }
390
391 static void qwtToRgba( const QImage* from, QImage* to,
392 const QRect& tile, int alpha )
393 {
394 const QRgb mask1 = qRgba( 0, 0, 0, alpha );
395 const QRgb mask2 = qRgba( 255, 255, 255, 0 );
396 const QRgb mask3 = qRgba( 0, 0, 0, 255 );
397
398 const int y0 = tile.top();
399 const int y1 = tile.bottom();
400 const int x0 = tile.left();
401 const int x1 = tile.right();
402
403 if ( from->depth() == 8 )
404 {
405 for ( int y = y0; y <= y1; y++ )
406 {
407 QRgb* alphaLine = reinterpret_cast< QRgb* >( to->scanLine( y ) );
408 const unsigned char* line = from->scanLine( y );
409
410 for ( int x = x0; x <= x1; x++ )
411 *alphaLine++ = ( from->color( *line++ ) & mask2 ) | mask1;
412 }
413 }
414 else if ( from->depth() == 32 )
415 {
416 for ( int y = y0; y <= y1; y++ )
417 {
418 QRgb* alphaLine = reinterpret_cast< QRgb* >( to->scanLine( y ) );
419 const QRgb* line = reinterpret_cast< const QRgb* >( from->scanLine( y ) );
420
421 for ( int x = x0; x <= x1; x++ )
422 {
423 const QRgb rgb = *line++;
424 if ( rgb & mask3 ) // alpha != 0
425 *alphaLine++ = ( rgb & mask2 ) | mask1;
426 else
427 *alphaLine++ = rgb;
428 }
429 }
430 }
431 }
432
434 QwtPlotRasterItem::QwtPlotRasterItem( const QString& title )
435 : QwtPlotItem( QwtText( title ) )
436 {
437 init();
438 }
439
441 QwtPlotRasterItem::QwtPlotRasterItem( const QwtText& title )
442 : QwtPlotItem( title )
443 {
444 init();
445 }
446
448 QwtPlotRasterItem::~QwtPlotRasterItem()
449 {
450 delete m_data;
451 }
452
453 void QwtPlotRasterItem::init()
454 {
455 m_data = new PrivateData();
456
457 setItemAttribute( QwtPlotItem::AutoScale, true );
458 setItemAttribute( QwtPlotItem::Legend, false );
459
460 setZ( 8.0 );
461 }
462
470 void QwtPlotRasterItem::setPaintAttribute( PaintAttribute attribute, bool on )
471 {
472 if ( on )
473 m_data->paintAttributes |= attribute;
474 else
475 m_data->paintAttributes &= ~attribute;
476 }
477
482 bool QwtPlotRasterItem::testPaintAttribute( PaintAttribute attribute ) const
483 {
484 return ( m_data->paintAttributes & attribute );
485 }
486
510 void QwtPlotRasterItem::setAlpha( int alpha )
511 {
512 if ( alpha < 0 )
513 alpha = -1;
514
515 if ( alpha > 255 )
516 alpha = 255;
517
518 if ( alpha != m_data->alpha )
519 {
520 m_data->alpha = alpha;
521
522 itemChanged();
523 }
524 }
525
530 int QwtPlotRasterItem::alpha() const
531 {
532 return m_data->alpha;
533 }
534
543 void QwtPlotRasterItem::setCachePolicy(
544 QwtPlotRasterItem::CachePolicy policy )
545 {
546 if ( m_data->cache.policy != policy )
547 {
548 m_data->cache.policy = policy;
549
550 invalidateCache();
551 itemChanged();
552 }
553 }
554
559 QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const
560 {
561 return m_data->cache.policy;
562 }
563
568 void QwtPlotRasterItem::invalidateCache()
569 {
570 m_data->cache.image = QImage();
571 m_data->cache.area = QRect();
572 m_data->cache.size = QSize();
573 }
574
601 QRectF QwtPlotRasterItem::pixelHint( const QRectF& area ) const
602 {
603 Q_UNUSED( area );
604 return QRectF();
605 }
606
614 void QwtPlotRasterItem::draw( QPainter* painter,
615 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
616 const QRectF& canvasRect ) const
617 {
618 if ( canvasRect.isEmpty() || m_data->alpha == 0 )
619 return;
620
621 const bool doCache = qwtUseCache( m_data->cache.policy, painter );
622
623 const QwtInterval xInterval = interval( Qt::XAxis );
624 const QwtInterval yInterval = interval( Qt::YAxis );
625
626 /*
627 Scaling an image always results in a loss of
628 precision/quality. So we always render the image in
629 paint device resolution.
630 */
631
632 QwtScaleMap xxMap, yyMap;
633 qwtTransformMaps( painter->transform(), xMap, yMap, xxMap, yyMap );
634
635 QRectF paintRect = painter->transform().mapRect( canvasRect );
636 QRectF area = QwtScaleMap::invTransform( xxMap, yyMap, paintRect );
637
638 const QRectF br = boundingRect();
639 if ( br.isValid() && !br.contains( area ) )
640 {
641 area &= br;
642 if ( !area.isValid() )
643 return;
644
645 paintRect = QwtScaleMap::transform( xxMap, yyMap, area );
646 }
647
648 QRectF imageRect;
649 QImage image;
650
651 QRectF pixelRect = pixelHint(area);
652 if ( !pixelRect.isEmpty() )
653 {
654 // one pixel of the target device in plot coordinates
655 const double dx = qAbs( xxMap.invTransform( 1 ) - xxMap.invTransform( 0 ) );
656 const double dy = qAbs( yyMap.invTransform( 1 ) - yyMap.invTransform( 0 ) );
657
658 if ( dx > pixelRect.width() && dy > pixelRect.height() )
659 {
660 /*
661 When the resolution of the data pixels is higher than
662 the resolution of the target device we render in
663 target device resolution.
664 */
665 pixelRect = QRectF();
666 }
667 else
668 {
669 /*
670 If only one dimension is of the data pixel is higher
671 we expand the pixel rect to the resolution of the target device.
672 */
673
674 if ( dx > pixelRect.width() )
675 pixelRect.setWidth( dx );
676
677 if ( dy > pixelRect.height() )
678 pixelRect.setHeight( dy );
679 }
680 }
681
682 if ( pixelRect.isEmpty() )
683 {
684 if ( QwtPainter::roundingAlignment( painter ) )
685 {
686 // we want to have maps, where the boundaries of
687 // the aligned paint rectangle exactly match the area
688
689 paintRect = qwtAlignRect(paintRect);
690 qwtAdjustMaps(xxMap, yyMap, area, paintRect);
691 }
692
693 // When we have no information about position and size of
694 // data pixels we render in resolution of the paint device.
695
696 image = compose(xxMap, yyMap,
697 area, paintRect, paintRect.size().toSize(), doCache);
698 if ( image.isNull() )
699 return;
700
701 // Remove pixels at the boundaries, when explicitly
702 // excluded in the intervals
703
704 imageRect = qwtStripRect(paintRect, area,
705 xxMap, yyMap, xInterval, yInterval);
706
707 if ( imageRect != paintRect )
708 {
709 const QRect r(
710 qRound( imageRect.x() - paintRect.x() ),
711 qRound( imageRect.y() - paintRect.y() ),
712 qRound( imageRect.width() ),
713 qRound( imageRect.height() ) );
714
715 image = image.copy(r);
716 }
717 }
718 else
719 {
720 if ( QwtPainter::roundingAlignment( painter ) )
721 paintRect = qwtAlignRect(paintRect);
722
723 // align the area to the data pixels
724 QRectF imageArea = qwtExpandToPixels(area, pixelRect);
725
726 if ( imageArea.right() == xInterval.maxValue() &&
727 !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
728 {
729 imageArea.adjust(0, 0, pixelRect.width(), 0);
730 }
731 if ( imageArea.bottom() == yInterval.maxValue() &&
732 !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
733 {
734 imageArea.adjust(0, 0, 0, pixelRect.height() );
735 }
736
737 QSize imageSize;
738 imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) );
739 imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) );
740
741 image = compose(xxMap, yyMap,
742 imageArea, paintRect, imageSize, doCache );
743
744 if ( image.isNull() )
745 return;
746
747 imageRect = qwtStripRect(paintRect, area,
748 xxMap, yyMap, xInterval, yInterval);
749
750 if ( ( image.width() > 1 || image.height() > 1 ) &&
751 testPaintAttribute( PaintInDeviceResolution ) )
752 {
753 // Because of rounding errors the pixels
754 // need to be expanded manually to rectangles of
755 // different sizes
756
757 image = qwtExpandImage(image, xxMap, yyMap,
758 imageArea, area, paintRect, xInterval, yInterval );
759 }
760 }
761
762 painter->save();
763 painter->setWorldTransform( QTransform() );
764
765 QwtPainter::drawImage( painter, imageRect, image );
766
767 painter->restore();
768 }
769
778 QwtInterval QwtPlotRasterItem::interval(Qt::Axis axis) const
779 {
780 Q_UNUSED( axis );
781 return QwtInterval();
782 }
783
788 QRectF QwtPlotRasterItem::boundingRect() const
789 {
790 const QwtInterval intervalX = interval( Qt::XAxis );
791 const QwtInterval intervalY = interval( Qt::YAxis );
792
793 if ( !intervalX.isValid() && !intervalY.isValid() )
794 return QRectF(); // no bounding rect
795
796 QRectF r;
797
798 if ( intervalX.isValid() )
799 {
800 r.setLeft( intervalX.minValue() );
801 r.setRight( intervalX.maxValue() );
802 }
803 else
804 {
805 const qreal max = std::numeric_limits< float >::max();
806
807 r.setLeft( -0.5 * max );
808 r.setWidth( max );
809 }
810
811 if ( intervalY.isValid() )
812 {
813 r.setTop( intervalY.minValue() );
814 r.setBottom( intervalY.maxValue() );
815 }
816 else
817 {
818 const qreal max = std::numeric_limits< float >::max();
819
820 r.setTop( -0.5 * max );
821 r.setHeight( max );
822 }
823
824 return r.normalized();
825 }
826
827 QImage QwtPlotRasterItem::compose(
828 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
829 const QRectF& imageArea, const QRectF& paintRect,
830 const QSize& imageSize, bool doCache) const
831 {
832 QImage image;
833 if ( imageArea.isEmpty() || paintRect.isEmpty() || imageSize.isEmpty() )
834 return image;
835
836 if ( doCache )
837 {
838 if ( !m_data->cache.image.isNull()
839 && m_data->cache.area == imageArea
840 && m_data->cache.size == paintRect.size() )
841 {
842 image = m_data->cache.image;
843 }
844 }
845
846 if ( image.isNull() )
847 {
848 double dx = 0.0;
849 if ( paintRect.toRect().width() > imageSize.width() )
850 dx = imageArea.width() / imageSize.width();
851
852 const QwtScaleMap xxMap =
853 imageMap(Qt::Horizontal, xMap, imageArea, imageSize, dx);
854
855 double dy = 0.0;
856 if ( paintRect.toRect().height() > imageSize.height() )
857 dy = imageArea.height() / imageSize.height();
858
859 const QwtScaleMap yyMap =
860 imageMap(Qt::Vertical, yMap, imageArea, imageSize, dy);
861
862 image = renderImage( xxMap, yyMap, imageArea, imageSize );
863
864 if ( doCache )
865 {
866 m_data->cache.area = imageArea;
867 m_data->cache.size = paintRect.size();
868 m_data->cache.image = image;
869 }
870 }
871
872 if ( m_data->alpha >= 0 && m_data->alpha < 255 )
873 {
874 QImage alphaImage( image.size(), QImage::Format_ARGB32 );
875
876 #if !defined( QT_NO_QFUTURE )
877 uint numThreads = renderThreadCount();
878
879 if ( numThreads <= 0 )
880 numThreads = QThread::idealThreadCount();
881
882 if ( numThreads <= 0 )
883 numThreads = 1;
884
885 const int numRows = image.height() / numThreads;
886
887 QVector< QFuture< void > > futures;
888 futures.reserve( numThreads - 1 );
889
890 for ( uint i = 0; i < numThreads; i++ )
891 {
892 QRect tile( 0, i * numRows, image.width(), numRows );
893 if ( i == numThreads - 1 )
894 {
895 tile.setHeight( image.height() - i * numRows );
896 qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
897 }
898 else
899 {
900 futures += QtConcurrent::run(
901 &qwtToRgba, &image, &alphaImage, tile, m_data->alpha );
902 }
903 }
904 for ( int i = 0; i < futures.size(); i++ )
905 futures[i].waitForFinished();
906 #else
907 const QRect tile( 0, 0, image.width(), image.height() );
908 qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
909 #endif
910 image = alphaImage;
911 }
912
913 return image;
914 }
915
927 QwtScaleMap QwtPlotRasterItem::imageMap(
928 Qt::Orientation orientation,
929 const QwtScaleMap& map, const QRectF& area,
930 const QSize& imageSize, double pixelSize) const
931 {
932 double p1, p2, s1, s2;
933
934 if ( orientation == Qt::Horizontal )
935 {
936 p1 = 0.0;
937 p2 = imageSize.width();
938 s1 = area.left();
939 s2 = area.right();
940 }
941 else
942 {
943 p1 = 0.0;
944 p2 = imageSize.height();
945 s1 = area.top();
946 s2 = area.bottom();
947 }
948
949 if ( pixelSize > 0.0 || p2 == 1.0 )
950 {
951 double off = 0.5 * pixelSize;
952 if ( map.isInverting() )
953 off = -off;
954
955 s1 += off;
956 s2 += off;
957 }
958 else
959 {
960 p2--;
961 }
962
963 if ( map.isInverting() && ( s1 < s2 ) )
964 qSwap( s1, s2 );
965
966 QwtScaleMap newMap = map;
967 newMap.setPaintInterval( p1, p2 );
968 newMap.setScaleInterval( s1, s2 );
969
970 return newMap;
971 }
QVector
Definition: qwt_clipper.h:23
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:23
QwtInterval::minValue
double minValue() const
Definition: qwt_interval.h:192
QwtInterval::ExcludeMaximum
@ ExcludeMaximum
Max value is not included in the interval.
Definition: qwt_interval.h:38
QwtInterval::ExcludeMinimum
@ ExcludeMinimum
Min value is not included in the interval.
Definition: qwt_interval.h:35
QwtInterval::maxValue
double maxValue() const
Definition: qwt_interval.h:198
QwtInterval::borderFlags
BorderFlags borderFlags() const
Definition: qwt_interval.h:166
QwtInterval::isValid
bool isValid() const
Definition: qwt_interval.h:210
QwtPainter::drawImage
static void drawImage(QPainter *, const QRectF &, const QImage &)
Wrapper for QPainter::drawImage()
Definition: qwt_painter.cpp:773
QwtPainter::roundingAlignment
static bool roundingAlignment()
Definition: qwt_painter.h:183
QwtPlotItem
Base class for items on the plot canvas.
Definition: qwt_plot_item.h:67
QwtPlotItem::paintRect
QRectF paintRect(const QwtScaleMap &, const QwtScaleMap &) const
Calculate the bounding paint rectangle of 2 maps.
Definition: qwt_plot_item.cpp:720
QwtPlotItem::setZ
void setZ(double z)
Set the z value.
Definition: qwt_plot_item.cpp:165
QwtPlotItem::setItemAttribute
void setItemAttribute(ItemAttribute, bool on=true)
Definition: qwt_plot_item.cpp:228
QwtPlotItem::itemChanged
virtual void itemChanged()
Definition: qwt_plot_item.cpp:481
QwtPlotItem::Legend
@ Legend
The item is represented on the legend.
Definition: qwt_plot_item.h:150
QwtPlotItem::AutoScale
@ AutoScale
Definition: qwt_plot_item.h:157
QwtPlotItem::renderThreadCount
uint renderThreadCount() const
Definition: qwt_plot_item.cpp:360
QwtPlotRasterItem
A class, which displays raster data.
Definition: qwt_plot_rasteritem.h:38
QwtPlotRasterItem::testPaintAttribute
bool testPaintAttribute(PaintAttribute) const
Definition: qwt_plot_rasteritem.cpp:482
QwtPlotRasterItem::draw
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const override
Draw the raster data.
Definition: qwt_plot_rasteritem.cpp:614
QwtPlotRasterItem::boundingRect
virtual QRectF boundingRect() const override
Definition: qwt_plot_rasteritem.cpp:788
QwtPlotRasterItem::setAlpha
void setAlpha(int alpha)
Set an alpha value for the raster data.
Definition: qwt_plot_rasteritem.cpp:510
QwtPlotRasterItem::renderImage
virtual QImage renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &area, const QSize &imageSize) const =0
Render an image.
QwtPlotRasterItem::~QwtPlotRasterItem
virtual ~QwtPlotRasterItem()
Destructor.
Definition: qwt_plot_rasteritem.cpp:448
QwtPlotRasterItem::setCachePolicy
void setCachePolicy(CachePolicy)
Definition: qwt_plot_rasteritem.cpp:543
QwtPlotRasterItem::invalidateCache
void invalidateCache()
Definition: qwt_plot_rasteritem.cpp:568
QwtPlotRasterItem::alpha
int alpha() const
Definition: qwt_plot_rasteritem.cpp:530
QwtPlotRasterItem::setPaintAttribute
void setPaintAttribute(PaintAttribute, bool on=true)
Definition: qwt_plot_rasteritem.cpp:470
QwtPlotRasterItem::PaintAttributes
QFlags< PaintAttribute > PaintAttributes
Definition: qwt_plot_rasteritem.h:83
QwtPlotRasterItem::PaintAttribute
PaintAttribute
Definition: qwt_plot_rasteritem.h:67
QwtPlotRasterItem::PaintInDeviceResolution
@ PaintInDeviceResolution
Definition: qwt_plot_rasteritem.h:80
QwtPlotRasterItem::pixelHint
virtual QRectF pixelHint(const QRectF &) const
Pixel hint.
Definition: qwt_plot_rasteritem.cpp:601
QwtPlotRasterItem::CachePolicy
CachePolicy
Cache policy The default policy is NoCache.
Definition: qwt_plot_rasteritem.h:45
QwtPlotRasterItem::PaintCache
@ PaintCache
Definition: qwt_plot_rasteritem.h:59
QwtPlotRasterItem::NoCache
@ NoCache
Definition: qwt_plot_rasteritem.h:49
QwtPlotRasterItem::QwtPlotRasterItem
QwtPlotRasterItem(const QString &title=QString())
Constructor.
Definition: qwt_plot_rasteritem.cpp:434
QwtPlotRasterItem::imageMap
virtual QwtScaleMap imageMap(Qt::Orientation, const QwtScaleMap &map, const QRectF &area, const QSize &imageSize, double pixelSize) const
Calculate a scale map for painting to an image.
Definition: qwt_plot_rasteritem.cpp:927
QwtPlotRasterItem::interval
virtual QwtInterval interval(Qt::Axis) const
Definition: qwt_plot_rasteritem.cpp:778
QwtPlotRasterItem::cachePolicy
CachePolicy cachePolicy() const
Definition: qwt_plot_rasteritem.cpp:559
QwtScaleMap
A scale map.
Definition: qwt_scale_map.h:27
QwtScaleMap::isInverting
bool isInverting() const
Definition: qwt_scale_map.h:164
QwtScaleMap::p1
double p1() const
Definition: qwt_scale_map.h:99
QwtScaleMap::transform
double transform(double s) const
Definition: qwt_scale_map.h:137
QwtScaleMap::setPaintInterval
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
Definition: qwt_scale_map.cpp:119
QwtScaleMap::setScaleInterval
void setScaleInterval(double s1, double s2)
Specify the borders of the scale interval.
Definition: qwt_scale_map.cpp:100
QwtScaleMap::invTransform
double invTransform(double p) const
Definition: qwt_scale_map.h:154
QwtScaleMap::p2
double p2() const
Definition: qwt_scale_map.h:107
QwtText
A class representing a text.
Definition: qwt_text.h:52