00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_plot_rasteritem.h"
00011 #include "qwt_scale_map.h"
00012 #include "qwt_painter.h"
00013 #include <qapplication.h>
00014 #include <qdesktopwidget.h>
00015 #include <qpainter.h>
00016 #include <qpaintengine.h>
00017 #include <qmath.h>
00018 #include <qthread.h>
00019 #include <qfuture.h>
00020 #include <qtconcurrentrun.h>
00021 #include <float.h>
00022
00023 class QwtPlotRasterItem::PrivateData
00024 {
00025 public:
00026 PrivateData():
00027 alpha( -1 ),
00028 paintAttributes( QwtPlotRasterItem::PaintInDeviceResolution )
00029 {
00030 cache.policy = QwtPlotRasterItem::NoCache;
00031 }
00032
00033 int alpha;
00034
00035 QwtPlotRasterItem::PaintAttributes paintAttributes;
00036
00037 struct ImageCache
00038 {
00039 QwtPlotRasterItem::CachePolicy policy;
00040 QRectF area;
00041 QSizeF size;
00042 QImage image;
00043 } cache;
00044 };
00045
00046
00047 static QRectF qwtAlignRect(const QRectF &rect)
00048 {
00049 QRectF r;
00050 r.setLeft( qRound( rect.left() ) );
00051 r.setRight( qRound( rect.right() ) );
00052 r.setTop( qRound( rect.top() ) );
00053 r.setBottom( qRound( rect.bottom() ) );
00054
00055 return r;
00056 }
00057
00058 static QRectF qwtStripRect(const QRectF &rect, const QRectF &area,
00059 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00060 const QwtInterval &xInterval, const QwtInterval &yInterval)
00061 {
00062 QRectF r = rect;
00063 if ( xInterval.borderFlags() & QwtInterval::ExcludeMinimum )
00064 {
00065 if ( area.left() <= xInterval.minValue() )
00066 {
00067 if ( xMap.isInverting() )
00068 r.adjust(0, 0, -1, 0);
00069 else
00070 r.adjust(1, 0, 0, 0);
00071 }
00072 }
00073
00074 if ( xInterval.borderFlags() & QwtInterval::ExcludeMaximum )
00075 {
00076 if ( area.right() >= xInterval.maxValue() )
00077 {
00078 if ( xMap.isInverting() )
00079 r.adjust(1, 0, 0, 0);
00080 else
00081 r.adjust(0, 0, -1, 0);
00082 }
00083 }
00084
00085 if ( yInterval.borderFlags() & QwtInterval::ExcludeMinimum )
00086 {
00087 if ( area.top() <= yInterval.minValue() )
00088 {
00089 if ( yMap.isInverting() )
00090 r.adjust(0, 0, 0, -1);
00091 else
00092 r.adjust(0, 1, 0, 0);
00093 }
00094 }
00095
00096 if ( yInterval.borderFlags() & QwtInterval::ExcludeMaximum )
00097 {
00098 if ( area.bottom() >= yInterval.maxValue() )
00099 {
00100 if ( yMap.isInverting() )
00101 r.adjust(0, 1, 0, 0);
00102 else
00103 r.adjust(0, 0, 0, -1);
00104 }
00105 }
00106
00107 return r;
00108 }
00109
00110 static QImage qwtExpandImage(const QImage &image,
00111 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00112 const QRectF &area, const QRectF &area2, const QRectF &paintRect,
00113 const QwtInterval &xInterval, const QwtInterval &yInterval )
00114 {
00115 const QRectF strippedRect = qwtStripRect(paintRect, area2,
00116 xMap, yMap, xInterval, yInterval);
00117 const QSize sz = strippedRect.toRect().size();
00118
00119 const int w = image.width();
00120 const int h = image.height();
00121
00122 const QRectF r = QwtScaleMap::transform(xMap, yMap, area).normalized();
00123 const double pw = ( r.width() - 1) / w;
00124 const double ph = ( r.height() - 1) / h;
00125
00126 double px0, py0;
00127 if ( !xMap.isInverting() )
00128 {
00129 px0 = xMap.transform( area2.left() );
00130 px0 = qRound( px0 );
00131 px0 = px0 - xMap.transform( area.left() );
00132 }
00133 else
00134 {
00135 px0 = xMap.transform( area2.right() );
00136 px0 = qRound( px0 );
00137 px0 -= xMap.transform( area.right() );
00138
00139 px0 -= 1.0;
00140 }
00141 px0 += strippedRect.left() - paintRect.left();
00142
00143 if ( !yMap.isInverting() )
00144 {
00145 py0 = yMap.transform( area2.top() );
00146 py0 = qRound( py0 );
00147 py0 -= yMap.transform( area.top() );
00148 }
00149 else
00150 {
00151 py0 = yMap.transform( area2.bottom() );
00152 py0 = qRound( py0 );
00153 py0 -= yMap.transform( area.bottom() );
00154
00155 py0 -= 1.0;
00156 }
00157 py0 += strippedRect.top() - paintRect.top();
00158
00159 QImage expanded(sz, image.format());
00160
00161 switch( image.depth() )
00162 {
00163 case 32:
00164 {
00165 for ( int y1 = 0; y1 < h; y1++ )
00166 {
00167 int yy1;
00168 if ( y1 == 0 )
00169 {
00170 yy1 = 0;
00171 }
00172 else
00173 {
00174 yy1 = qRound( y1 * ph - py0 );
00175 if ( yy1 < 0 )
00176 yy1 = 0;
00177 }
00178
00179 int yy2;
00180 if ( y1 == h - 1 )
00181 {
00182 yy2 = sz.height();
00183 }
00184 else
00185 {
00186 yy2 = qRound( ( y1 + 1 ) * ph - py0 );
00187 if ( yy2 > sz.height() )
00188 yy2 = sz.height();
00189 }
00190
00191 const quint32 *line1 =
00192 reinterpret_cast<const quint32 *>( image.scanLine( y1 ) );
00193
00194 for ( int x1 = 0; x1 < w; x1++ )
00195 {
00196 int xx1;
00197 if ( x1 == 0 )
00198 {
00199 xx1 = 0;
00200 }
00201 else
00202 {
00203 xx1 = qRound( x1 * pw - px0 );
00204 if ( xx1 < 0 )
00205 xx1 = 0;
00206 }
00207
00208 int xx2;
00209 if ( x1 == w - 1 )
00210 {
00211 xx2 = sz.width();
00212 }
00213 else
00214 {
00215 xx2 = qRound( ( x1 + 1 ) * pw - px0 );
00216 if ( xx2 > sz.width() )
00217 xx2 = sz.width();
00218 }
00219
00220 const quint32 rgb( line1[x1] );
00221 for ( int y2 = yy1; y2 < yy2; y2++ )
00222 {
00223 quint32 *line2 = reinterpret_cast<quint32 *>(
00224 expanded.scanLine( y2 ) );
00225
00226 for ( int x2 = xx1; x2 < xx2; x2++ )
00227 line2[x2] = rgb;
00228 }
00229 }
00230 }
00231 break;
00232 }
00233 case 8:
00234 {
00235 for ( int y1 = 0; y1 < h; y1++ )
00236 {
00237 int yy1;
00238 if ( y1 == 0 )
00239 {
00240 yy1 = 0;
00241 }
00242 else
00243 {
00244 yy1 = qRound( y1 * ph - py0 );
00245 if ( yy1 < 0 )
00246 yy1 = 0;
00247 }
00248
00249 int yy2;
00250 if ( y1 == h - 1 )
00251 {
00252 yy2 = sz.height();
00253 }
00254 else
00255 {
00256 yy2 = qRound( ( y1 + 1 ) * ph - py0 );
00257 if ( yy2 > sz.height() )
00258 yy2 = sz.height();
00259 }
00260
00261 const uchar *line1 = image.scanLine( y1 );
00262
00263 for ( int x1 = 0; x1 < w; x1++ )
00264 {
00265 int xx1;
00266 if ( x1 == 0 )
00267 {
00268 xx1 = 0;
00269 }
00270 else
00271 {
00272 xx1 = qRound( x1 * pw - px0 );
00273 if ( xx1 < 0 )
00274 xx1 = 0;
00275 }
00276
00277 int xx2;
00278 if ( x1 == w - 1 )
00279 {
00280 xx2 = sz.width();
00281 }
00282 else
00283 {
00284 xx2 = qRound( ( x1 + 1 ) * pw - px0 );
00285 if ( xx2 > sz.width() )
00286 xx2 = sz.width();
00287 }
00288
00289 for ( int y2 = yy1; y2 < yy2; y2++ )
00290 {
00291 uchar *line2 = expanded.scanLine( y2 );
00292 memset( line2 + xx1, line1[x1], xx2 - xx1 );
00293 }
00294 }
00295 }
00296 break;
00297 }
00298 default:
00299 expanded = image;
00300 }
00301
00302 return expanded;
00303 }
00304
00305 static QRectF qwtExpandToPixels(const QRectF &rect, const QRectF &pixelRect)
00306 {
00307 const double pw = pixelRect.width();
00308 const double ph = pixelRect.height();
00309
00310 const double dx1 = pixelRect.left() - rect.left();
00311 const double dx2 = pixelRect.right() - rect.right();
00312 const double dy1 = pixelRect.top() - rect.top();
00313 const double dy2 = pixelRect.bottom() - rect.bottom();
00314
00315 QRectF r;
00316 r.setLeft( pixelRect.left() - qCeil( dx1 / pw ) * pw );
00317 r.setTop( pixelRect.top() - qCeil( dy1 / ph ) * ph );
00318 r.setRight( pixelRect.right() - qFloor( dx2 / pw ) * pw );
00319 r.setBottom( pixelRect.bottom() - qFloor( dy2 / ph ) * ph );
00320
00321 return r;
00322 }
00323
00324 static void qwtTransformMaps( const QTransform &tr,
00325 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00326 QwtScaleMap &xxMap, QwtScaleMap &yyMap )
00327 {
00328 const QPointF p1 = tr.map( QPointF( xMap.p1(), yMap.p1() ) );
00329 const QPointF p2 = tr.map( QPointF( xMap.p2(), yMap.p2() ) );
00330
00331 xxMap = xMap;
00332 xxMap.setPaintInterval( p1.x(), p2.x() );
00333
00334 yyMap = yMap;
00335 yyMap.setPaintInterval( p1.y(), p2.y() );
00336 }
00337
00338 static void qwtAdjustMaps( QwtScaleMap &xMap, QwtScaleMap &yMap,
00339 const QRectF &area, const QRectF &paintRect)
00340 {
00341 double sx1 = area.left();
00342 double sx2 = area.right();
00343 if ( xMap.isInverting() )
00344 qSwap(sx1, sx2);
00345
00346 double sy1 = area.top();
00347 double sy2 = area.bottom();
00348
00349 if ( yMap.isInverting() )
00350 qSwap(sy1, sy2);
00351
00352 xMap.setPaintInterval(paintRect.left(), paintRect.right());
00353 xMap.setScaleInterval(sx1, sx2);
00354
00355 yMap.setPaintInterval(paintRect.top(), paintRect.bottom());
00356 yMap.setScaleInterval(sy1, sy2);
00357 }
00358
00359 static bool qwtUseCache( QwtPlotRasterItem::CachePolicy policy,
00360 const QPainter *painter )
00361 {
00362 bool doCache = false;
00363
00364 if ( policy == QwtPlotRasterItem::PaintCache )
00365 {
00366
00367
00368
00369 switch ( painter->paintEngine()->type() )
00370 {
00371 case QPaintEngine::SVG:
00372 case QPaintEngine::Pdf:
00373 case QPaintEngine::PostScript:
00374 case QPaintEngine::MacPrinter:
00375 case QPaintEngine::Picture:
00376 break;
00377 default:;
00378 doCache = true;
00379 }
00380 }
00381
00382 return doCache;
00383 }
00384
00385 static void qwtToRgba( const QImage* from, QImage* to,
00386 const QRect& tile, int alpha )
00387 {
00388 const QRgb mask1 = qRgba( 0, 0, 0, alpha );
00389 const QRgb mask2 = qRgba( 255, 255, 255, 0 );
00390 const QRgb mask3 = qRgba( 0, 0, 0, 255 );
00391
00392 const int y0 = tile.top();
00393 const int y1 = tile.bottom();
00394 const int x0 = tile.left();
00395 const int x1 = tile.right();
00396
00397 if ( from->depth() == 8 )
00398 {
00399 for ( int y = y0; y <= y1; y++ )
00400 {
00401 QRgb *alphaLine = reinterpret_cast<QRgb *>( to->scanLine( y ) );
00402 const unsigned char *line = from->scanLine( y );
00403
00404 for ( int x = x0; x <= x1; x++ )
00405 *alphaLine++ = ( from->color( *line++ ) & mask2 ) | mask1;
00406 }
00407 }
00408 else if ( from->depth() == 32 )
00409 {
00410 for ( int y = y0; y <= y1; y++ )
00411 {
00412 QRgb *alphaLine = reinterpret_cast<QRgb *>( to->scanLine( y ) );
00413 const QRgb *line = reinterpret_cast<const QRgb *>( from->scanLine( y ) );
00414
00415 for ( int x = x0; x <= x1; x++ )
00416 {
00417 const QRgb rgb = *line++;
00418 if ( rgb & mask3 )
00419 *alphaLine++ = ( rgb & mask2 ) | mask1;
00420 else
00421 *alphaLine++ = rgb;
00422 }
00423 }
00424 }
00425 }
00426
00428 QwtPlotRasterItem::QwtPlotRasterItem( const QString& title ):
00429 QwtPlotItem( QwtText( title ) )
00430 {
00431 init();
00432 }
00433
00435 QwtPlotRasterItem::QwtPlotRasterItem( const QwtText& title ):
00436 QwtPlotItem( title )
00437 {
00438 init();
00439 }
00440
00442 QwtPlotRasterItem::~QwtPlotRasterItem()
00443 {
00444 delete d_data;
00445 }
00446
00447 void QwtPlotRasterItem::init()
00448 {
00449 d_data = new PrivateData();
00450
00451 setItemAttribute( QwtPlotItem::AutoScale, true );
00452 setItemAttribute( QwtPlotItem::Legend, false );
00453
00454 setZ( 8.0 );
00455 }
00456
00464 void QwtPlotRasterItem::setPaintAttribute( PaintAttribute attribute, bool on )
00465 {
00466 if ( on )
00467 d_data->paintAttributes |= attribute;
00468 else
00469 d_data->paintAttributes &= ~attribute;
00470 }
00471
00476 bool QwtPlotRasterItem::testPaintAttribute( PaintAttribute attribute ) const
00477 {
00478 return ( d_data->paintAttributes & attribute );
00479 }
00480
00504 void QwtPlotRasterItem::setAlpha( int alpha )
00505 {
00506 if ( alpha < 0 )
00507 alpha = -1;
00508
00509 if ( alpha > 255 )
00510 alpha = 255;
00511
00512 if ( alpha != d_data->alpha )
00513 {
00514 d_data->alpha = alpha;
00515
00516 itemChanged();
00517 }
00518 }
00519
00524 int QwtPlotRasterItem::alpha() const
00525 {
00526 return d_data->alpha;
00527 }
00528
00537 void QwtPlotRasterItem::setCachePolicy(
00538 QwtPlotRasterItem::CachePolicy policy )
00539 {
00540 if ( d_data->cache.policy != policy )
00541 {
00542 d_data->cache.policy = policy;
00543
00544 invalidateCache();
00545 itemChanged();
00546 }
00547 }
00548
00553 QwtPlotRasterItem::CachePolicy QwtPlotRasterItem::cachePolicy() const
00554 {
00555 return d_data->cache.policy;
00556 }
00557
00562 void QwtPlotRasterItem::invalidateCache()
00563 {
00564 d_data->cache.image = QImage();
00565 d_data->cache.area = QRect();
00566 d_data->cache.size = QSize();
00567 }
00568
00595 QRectF QwtPlotRasterItem::pixelHint( const QRectF &area ) const
00596 {
00597 Q_UNUSED( area );
00598 return QRectF();
00599 }
00600
00608 void QwtPlotRasterItem::draw( QPainter *painter,
00609 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00610 const QRectF &canvasRect ) const
00611 {
00612 if ( canvasRect.isEmpty() || d_data->alpha == 0 )
00613 return;
00614
00615 const bool doCache = qwtUseCache( d_data->cache.policy, painter );
00616
00617 const QwtInterval xInterval = interval( Qt::XAxis );
00618 const QwtInterval yInterval = interval( Qt::YAxis );
00619
00620
00621
00622
00623
00624
00625
00626 QwtScaleMap xxMap, yyMap;
00627 qwtTransformMaps( painter->transform(), xMap, yMap, xxMap, yyMap );
00628
00629 QRectF paintRect = painter->transform().mapRect( canvasRect );
00630 QRectF area = QwtScaleMap::invTransform( xxMap, yyMap, paintRect );
00631
00632 const QRectF br = boundingRect();
00633 if ( br.isValid() && !br.contains( area ) )
00634 {
00635 area &= br;
00636 if ( !area.isValid() )
00637 return;
00638
00639 paintRect = QwtScaleMap::transform( xxMap, yyMap, area );
00640 }
00641
00642 QRectF imageRect;
00643 QImage image;
00644
00645 QRectF pixelRect = pixelHint(area);
00646 if ( !pixelRect.isEmpty() )
00647 {
00648
00649 const double dx = qAbs( xxMap.invTransform( 1 ) - xxMap.invTransform( 0 ) );
00650 const double dy = qAbs( yyMap.invTransform( 1 ) - yyMap.invTransform( 0 ) );
00651
00652 if ( dx > pixelRect.width() && dy > pixelRect.height() )
00653 {
00654
00655
00656
00657
00658
00659 pixelRect = QRectF();
00660 }
00661 else
00662 {
00663
00664
00665
00666
00667
00668 if ( dx > pixelRect.width() )
00669 pixelRect.setWidth( dx );
00670
00671 if ( dy > pixelRect.height() )
00672 pixelRect.setHeight( dy );
00673 }
00674 }
00675
00676 if ( pixelRect.isEmpty() )
00677 {
00678 if ( QwtPainter::roundingAlignment( painter ) )
00679 {
00680
00681
00682
00683 paintRect = qwtAlignRect(paintRect);
00684 qwtAdjustMaps(xxMap, yyMap, area, paintRect);
00685 }
00686
00687
00688
00689
00690 image = compose(xxMap, yyMap,
00691 area, paintRect, paintRect.size().toSize(), doCache);
00692 if ( image.isNull() )
00693 return;
00694
00695
00696
00697
00698 imageRect = qwtStripRect(paintRect, area,
00699 xxMap, yyMap, xInterval, yInterval);
00700
00701 if ( imageRect != paintRect )
00702 {
00703 const QRect r(
00704 qRound( imageRect.x() - paintRect.x()),
00705 qRound( imageRect.y() - paintRect.y() ),
00706 qRound( imageRect.width() ),
00707 qRound( imageRect.height() ) );
00708
00709 image = image.copy(r);
00710 }
00711 }
00712 else
00713 {
00714 if ( QwtPainter::roundingAlignment( painter ) )
00715 paintRect = qwtAlignRect(paintRect);
00716
00717
00718 QRectF imageArea = qwtExpandToPixels(area, pixelRect);
00719
00720 if ( imageArea.right() == xInterval.maxValue() &&
00721 !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
00722 {
00723 imageArea.adjust(0, 0, pixelRect.width(), 0);
00724 }
00725 if ( imageArea.bottom() == yInterval.maxValue() &&
00726 !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) )
00727 {
00728 imageArea.adjust(0, 0, 0, pixelRect.height() );
00729 }
00730
00731 QSize imageSize;
00732 imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) );
00733 imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) );
00734
00735 image = compose(xxMap, yyMap,
00736 imageArea, paintRect, imageSize, doCache );
00737
00738 if ( image.isNull() )
00739 return;
00740
00741 imageRect = qwtStripRect(paintRect, area,
00742 xxMap, yyMap, xInterval, yInterval);
00743
00744 if ( ( image.width() > 1 || image.height() > 1 ) &&
00745 testPaintAttribute( PaintInDeviceResolution ) )
00746 {
00747
00748
00749
00750
00751 image = qwtExpandImage(image, xxMap, yyMap,
00752 imageArea, area, paintRect, xInterval, yInterval );
00753 }
00754 }
00755
00756 painter->save();
00757 painter->setWorldTransform( QTransform() );
00758
00759 QwtPainter::drawImage( painter, imageRect, image );
00760
00761 painter->restore();
00762 }
00763
00772 QwtInterval QwtPlotRasterItem::interval(Qt::Axis axis) const
00773 {
00774 Q_UNUSED( axis );
00775 return QwtInterval();
00776 }
00777
00782 QRectF QwtPlotRasterItem::boundingRect() const
00783 {
00784 const QwtInterval intervalX = interval( Qt::XAxis );
00785 const QwtInterval intervalY = interval( Qt::YAxis );
00786
00787 if ( !intervalX.isValid() && !intervalY.isValid() )
00788 return QRectF();
00789
00790 QRectF r;
00791
00792 if ( intervalX.isValid() )
00793 {
00794 r.setLeft( intervalX.minValue() );
00795 r.setRight( intervalX.maxValue() );
00796 }
00797 else
00798 {
00799 r.setLeft(-0.5 * FLT_MAX);
00800 r.setWidth(FLT_MAX);
00801 }
00802
00803 if ( intervalY.isValid() )
00804 {
00805 r.setTop( intervalY.minValue() );
00806 r.setBottom( intervalY.maxValue() );
00807 }
00808 else
00809 {
00810 r.setTop(-0.5 * FLT_MAX);
00811 r.setHeight(FLT_MAX);
00812 }
00813
00814 return r.normalized();
00815 }
00816
00817 QImage QwtPlotRasterItem::compose(
00818 const QwtScaleMap &xMap, const QwtScaleMap &yMap,
00819 const QRectF &imageArea, const QRectF &paintRect,
00820 const QSize &imageSize, bool doCache) const
00821 {
00822 QImage image;
00823 if ( imageArea.isEmpty() || paintRect.isEmpty() || imageSize.isEmpty() )
00824 return image;
00825
00826 if ( doCache )
00827 {
00828 if ( !d_data->cache.image.isNull()
00829 && d_data->cache.area == imageArea
00830 && d_data->cache.size == paintRect.size() )
00831 {
00832 image = d_data->cache.image;
00833 }
00834 }
00835
00836 if ( image.isNull() )
00837 {
00838 double dx = 0.0;
00839 if ( paintRect.toRect().width() > imageSize.width() )
00840 dx = imageArea.width() / imageSize.width();
00841
00842 const QwtScaleMap xxMap =
00843 imageMap(Qt::Horizontal, xMap, imageArea, imageSize, dx);
00844
00845 double dy = 0.0;
00846 if ( paintRect.toRect().height() > imageSize.height() )
00847 dy = imageArea.height() / imageSize.height();
00848
00849 const QwtScaleMap yyMap =
00850 imageMap(Qt::Vertical, yMap, imageArea, imageSize, dy);
00851
00852 image = renderImage( xxMap, yyMap, imageArea, imageSize );
00853
00854 if ( doCache )
00855 {
00856 d_data->cache.area = imageArea;
00857 d_data->cache.size = paintRect.size();
00858 d_data->cache.image = image;
00859 }
00860 }
00861
00862 if ( d_data->alpha >= 0 && d_data->alpha < 255 )
00863 {
00864 QImage alphaImage( image.size(), QImage::Format_ARGB32 );
00865
00866 #if !defined(QT_NO_QFUTURE)
00867 uint numThreads = renderThreadCount();
00868
00869 if ( numThreads <= 0 )
00870 numThreads = QThread::idealThreadCount();
00871
00872 if ( numThreads <= 0 )
00873 numThreads = 1;
00874
00875 const int numRows = image.height() / numThreads;
00876
00877 QList< QFuture<void> > futures;
00878 for ( uint i = 0; i < numThreads; i++ )
00879 {
00880 QRect tile( 0, i * numRows, image.width(), numRows );
00881 if ( i == numThreads - 1 )
00882 {
00883 tile.setHeight( image.height() - i * numRows );
00884 qwtToRgba( &image, &alphaImage, tile, d_data->alpha );
00885 }
00886 else
00887 {
00888 futures += QtConcurrent::run(
00889 &qwtToRgba, &image, &alphaImage, tile, d_data->alpha );
00890 }
00891 }
00892 for ( int i = 0; i < futures.size(); i++ )
00893 futures[i].waitForFinished();
00894 #else
00895 const QRect tile( 0, 0, image.width(), image.height() );
00896 qwtToRgba( &image, &alphaImage, tile, d_data->alpha );
00897 #endif
00898 image = alphaImage;
00899 }
00900
00901 return image;
00902 }
00903
00915 QwtScaleMap QwtPlotRasterItem::imageMap(
00916 Qt::Orientation orientation,
00917 const QwtScaleMap &map, const QRectF &area,
00918 const QSize &imageSize, double pixelSize) const
00919 {
00920 double p1, p2, s1, s2;
00921
00922 if ( orientation == Qt::Horizontal )
00923 {
00924 p1 = 0.0;
00925 p2 = imageSize.width();
00926 s1 = area.left();
00927 s2 = area.right();
00928 }
00929 else
00930 {
00931 p1 = 0.0;
00932 p2 = imageSize.height();
00933 s1 = area.top();
00934 s2 = area.bottom();
00935 }
00936
00937 if ( pixelSize > 0.0 )
00938 {
00939 double off = 0.5 * pixelSize;
00940 if ( map.isInverting() )
00941 off = -off;
00942
00943 s1 += off;
00944 s2 += off;
00945 }
00946 else
00947 {
00948 p2--;
00949 }
00950
00951 if ( map.isInverting() && ( s1 < s2 ) )
00952 qSwap( s1, s2 );
00953
00954 QwtScaleMap newMap = map;
00955 newMap.setPaintInterval( p1, p2 );
00956 newMap.setScaleInterval( s1, s2 );
00957
00958 return newMap;
00959 }