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  {
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 
435  : QwtPlotItem( QwtText( title ) )
436 {
437  init();
438 }
439 
442  : QwtPlotItem( title )
443 {
444  init();
445 }
446 
449 {
450  delete m_data;
451 }
452 
453 void QwtPlotRasterItem::init()
454 {
455  m_data = new PrivateData();
456 
459 
460  setZ( 8.0 );
461 }
462 
471 {
472  if ( on )
473  m_data->paintAttributes |= attribute;
474  else
475  m_data->paintAttributes &= ~attribute;
476 }
477 
483 {
484  return ( m_data->paintAttributes & attribute );
485 }
486 
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 
531 {
532  return m_data->alpha;
533 }
534 
545 {
546  if ( m_data->cache.policy != policy )
547  {
548  m_data->cache.policy = policy;
549 
550  invalidateCache();
551  itemChanged();
552  }
553 }
554 
560 {
561  return m_data->cache.policy;
562 }
563 
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 ) &&
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 
779 {
780  Q_UNUSED( axis );
781  return QwtInterval();
782 }
783 
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 
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 }
A class representing an interval.
Definition: qwt_interval.h:23
double minValue() const
Definition: qwt_interval.h:192
@ ExcludeMaximum
Max value is not included in the interval.
Definition: qwt_interval.h:38
@ ExcludeMinimum
Min value is not included in the interval.
Definition: qwt_interval.h:35
double maxValue() const
Definition: qwt_interval.h:198
BorderFlags borderFlags() const
Definition: qwt_interval.h:166
bool isValid() const
Definition: qwt_interval.h:210
static void drawImage(QPainter *, const QRectF &, const QImage &)
Wrapper for QPainter::drawImage()
static bool roundingAlignment()
Definition: qwt_painter.h:183
Base class for items on the plot canvas.
Definition: qwt_plot_item.h:67
QRectF paintRect(const QwtScaleMap &, const QwtScaleMap &) const
Calculate the bounding paint rectangle of 2 maps.
void setZ(double z)
Set the z value.
void setItemAttribute(ItemAttribute, bool on=true)
virtual void itemChanged()
@ Legend
The item is represented on the legend.
uint renderThreadCount() const
A class, which displays raster data.
bool testPaintAttribute(PaintAttribute) const
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const override
Draw the raster data.
virtual QRectF boundingRect() const override
void setAlpha(int alpha)
Set an alpha value for the raster data.
virtual QImage renderImage(const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &area, const QSize &imageSize) const =0
Render an image.
virtual ~QwtPlotRasterItem()
Destructor.
void setCachePolicy(CachePolicy)
void setPaintAttribute(PaintAttribute, bool on=true)
QFlags< PaintAttribute > PaintAttributes
virtual QRectF pixelHint(const QRectF &) const
Pixel hint.
CachePolicy
Cache policy The default policy is NoCache.
QwtPlotRasterItem(const QString &title=QString())
Constructor.
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.
virtual QwtInterval interval(Qt::Axis) const
CachePolicy cachePolicy() const
A scale map.
Definition: qwt_scale_map.h:27
bool isInverting() const
double p1() const
Definition: qwt_scale_map.h:99
double transform(double s) const
void setPaintInterval(double p1, double p2)
Specify the borders of the paint device interval.
void setScaleInterval(double s1, double s2)
Specify the borders of the scale interval.
double invTransform(double p) const
double p2() const
A class representing a text.
Definition: qwt_text.h:52