Qwt User's Guide 6.3.0

Loading...
Searching...
No Matches
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
601QRectF 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 auto imageSize = paintRect.size();
697
698#if QT_VERSION >= 0x050000
699 const auto pixelRatio = QwtPainter::devicePixelRatio( painter->device() );
700 imageSize *= pixelRatio;
701#endif
702
703 image = compose(xxMap, yyMap,
704 area, paintRect, imageSize.toSize(), doCache);
705
706 if ( image.isNull() )
707 return;
708
709#if QT_VERSION >= 0x050000
710 image.setDevicePixelRatio( pixelRatio );
711#endif
712
713 // Remove pixels at the boundaries, when explicitly
714 // excluded in the intervals
715
716 imageRect = qwtStripRect(paintRect, area,
717 xxMap, yyMap, xInterval, yInterval);
718
719 if ( imageRect != paintRect )
720 {
721 const QRect r(
722 qRound( imageRect.x() - paintRect.x() ),
723 qRound( imageRect.y() - paintRect.y() ),
724 qRound( imageRect.width() ),
725 qRound( imageRect.height() ) );
726
727 image = image.copy(r);
728 }
729 }
730 else
731 {
732 if ( QwtPainter::roundingAlignment( painter ) )
733 paintRect = qwtAlignRect(paintRect);
734
735 // align the area to the data pixels
736 QRectF imageArea = qwtExpandToPixels(area, pixelRect);
737
738 if ( imageArea.right() == xInterval.maxValue() &&
739 !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
740 {
741 imageArea.adjust(0, 0, pixelRect.width(), 0);
742 }
743 if ( imageArea.bottom() == yInterval.maxValue() &&
744 !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
745 {
746 imageArea.adjust(0, 0, 0, pixelRect.height() );
747 }
748
749 QSize imageSize;
750 imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) );
751 imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) );
752
753 image = compose(xxMap, yyMap,
754 imageArea, paintRect, imageSize, doCache );
755
756 if ( image.isNull() )
757 return;
758
759 imageRect = qwtStripRect(paintRect, area,
760 xxMap, yyMap, xInterval, yInterval);
761
762 if ( ( image.width() > 1 || image.height() > 1 ) &&
763 testPaintAttribute( PaintInDeviceResolution ) )
764 {
765 // Because of rounding errors the pixels
766 // need to be expanded manually to rectangles of
767 // different sizes
768
769 image = qwtExpandImage(image, xxMap, yyMap,
770 imageArea, area, paintRect, xInterval, yInterval );
771 }
772 }
773
774 painter->save();
775 painter->setWorldTransform( QTransform() );
776
777 QwtPainter::drawImage( painter, imageRect, image );
778
779 painter->restore();
780}
781
790 QwtInterval QwtPlotRasterItem::interval(Qt::Axis axis) const
791{
792 Q_UNUSED( axis );
793 return QwtInterval();
794}
795
800QRectF QwtPlotRasterItem::boundingRect() const
801{
802 const QwtInterval intervalX = interval( Qt::XAxis );
803 const QwtInterval intervalY = interval( Qt::YAxis );
804
805 if ( !intervalX.isValid() && !intervalY.isValid() )
806 return QRectF(); // no bounding rect
807
808 QRectF r;
809
810 if ( intervalX.isValid() )
811 {
812 r.setLeft( intervalX.minValue() );
813 r.setRight( intervalX.maxValue() );
814 }
815 else
816 {
817 const qreal max = std::numeric_limits< float >::max();
818
819 r.setLeft( -0.5 * max );
820 r.setWidth( max );
821 }
822
823 if ( intervalY.isValid() )
824 {
825 r.setTop( intervalY.minValue() );
826 r.setBottom( intervalY.maxValue() );
827 }
828 else
829 {
830 const qreal max = std::numeric_limits< float >::max();
831
832 r.setTop( -0.5 * max );
833 r.setHeight( max );
834 }
835
836 return r.normalized();
837}
838
839QImage QwtPlotRasterItem::compose(
840 const QwtScaleMap& xMap, const QwtScaleMap& yMap,
841 const QRectF& imageArea, const QRectF& paintRect,
842 const QSize& imageSize, bool doCache) const
843{
844 QImage image;
845 if ( imageArea.isEmpty() || paintRect.isEmpty() || imageSize.isEmpty() )
846 return image;
847
848 if ( doCache )
849 {
850 if ( !m_data->cache.image.isNull()
851 && m_data->cache.area == imageArea
852 && m_data->cache.size == paintRect.size() )
853 {
854 image = m_data->cache.image;
855 }
856 }
857
858 if ( image.isNull() )
859 {
860 double dx = 0.0;
861 if ( paintRect.toRect().width() > imageSize.width() )
862 dx = imageArea.width() / imageSize.width();
863
864 const QwtScaleMap xxMap =
865 imageMap(Qt::Horizontal, xMap, imageArea, imageSize, dx);
866
867 double dy = 0.0;
868 if ( paintRect.toRect().height() > imageSize.height() )
869 dy = imageArea.height() / imageSize.height();
870
871 const QwtScaleMap yyMap =
872 imageMap(Qt::Vertical, yMap, imageArea, imageSize, dy);
873
874 image = renderImage( xxMap, yyMap, imageArea, imageSize );
875
876 if ( doCache )
877 {
878 m_data->cache.area = imageArea;
879 m_data->cache.size = paintRect.size();
880 m_data->cache.image = image;
881 }
882 }
883
884 if ( m_data->alpha >= 0 && m_data->alpha < 255 )
885 {
886 QImage alphaImage( image.size(), QImage::Format_ARGB32 );
887
888#if !defined( QT_NO_QFUTURE )
889 uint numThreads = renderThreadCount();
890
891 if ( numThreads <= 0 )
892 numThreads = QThread::idealThreadCount();
893
894 if ( numThreads <= 0 )
895 numThreads = 1;
896
897 const int numRows = image.height() / numThreads;
898
899 QVector< QFuture< void > > futures;
900 futures.reserve( numThreads - 1 );
901
902 for ( uint i = 0; i < numThreads; i++ )
903 {
904 QRect tile( 0, i * numRows, image.width(), numRows );
905 if ( i == numThreads - 1 )
906 {
907 tile.setHeight( image.height() - i * numRows );
908 qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
909 }
910 else
911 {
912 futures += QtConcurrent::run(
913 &qwtToRgba, &image, &alphaImage, tile, m_data->alpha );
914 }
915 }
916 for ( int i = 0; i < futures.size(); i++ )
917 futures[i].waitForFinished();
918#else
919 const QRect tile( 0, 0, image.width(), image.height() );
920 qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
921#endif
922 image = alphaImage;
923 }
924
925 return image;
926}
927
939 QwtScaleMap QwtPlotRasterItem::imageMap(
940 Qt::Orientation orientation,
941 const QwtScaleMap& map, const QRectF& area,
942 const QSize& imageSize, double pixelSize) const
943{
944 double p1, p2, s1, s2;
945
946 if ( orientation == Qt::Horizontal )
947 {
948 p1 = 0.0;
949 p2 = imageSize.width();
950 s1 = area.left();
951 s2 = area.right();
952 }
953 else
954 {
955 p1 = 0.0;
956 p2 = imageSize.height();
957 s1 = area.top();
958 s2 = area.bottom();
959 }
960
961 if ( pixelSize > 0.0 || p2 == 1.0 )
962 {
963 double off = 0.5 * pixelSize;
964 if ( map.isInverting() )
965 off = -off;
966
967 s1 += off;
968 s2 += off;
969 }
970 else
971 {
972 p2--;
973 }
974
975 if ( map.isInverting() && ( s1 < s2 ) )
976 qSwap( s1, s2 );
977
978 QwtScaleMap newMap = map;
979 newMap.setPaintInterval( p1, p2 );
980 newMap.setScaleInterval( s1, s2 );
981
982 return newMap;
983}
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:763
QwtPainter::devicePixelRatio
static qreal devicePixelRatio(const QPaintDevice *)
Definition qwt_painter.cpp:1481
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:800
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:939
QwtPlotRasterItem::interval
virtual QwtInterval interval(Qt::Axis) const
Definition qwt_plot_rasteritem.cpp:790
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