static QRectF qwtStripRect(const QRectF &rect, const QRectF &area, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QwtInterval &xInterval, const QwtInterval &yInterval) { QRectF r = rect; if ( xInterval.borderFlags() & QwtInterval::ExcludeMinimum ) { if ( area.left() <= xInterval.minValue() ) { if ( xMap.isInverting() ) r.adjust(0, 0, -1, 0); else r.adjust(1, 0, 0, 0); } } if ( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) { if ( area.right() >= xInterval.maxValue() ) { if ( xMap.isInverting() ) r.adjust(1, 0, 0, 0); else r.adjust(0, 0, -1, 0); } } if ( yInterval.borderFlags() & QwtInterval::ExcludeMinimum ) { if ( area.top() <= yInterval.minValue() ) { if ( yMap.isInverting() ) r.adjust(0, 0, 0, -1); else r.adjust(0, 1, 0, 0); } } if ( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) { if ( area.bottom() >= yInterval.maxValue() ) { if ( yMap.isInverting() ) r.adjust(0, 1, 0, 0); else r.adjust(0, 0, 0, -1); } } return r; }
static inline bool isCombinable( const QwtInterval &d1, const QwtInterval &d2 ) { if ( d1.isValid() && d2.isValid() ) { if ( d1.maxValue() == d2.minValue() ) { if ( !( d1.borderFlags() & QwtInterval::ExcludeMaximum && d2.borderFlags() & QwtInterval::ExcludeMinimum ) ) { return true; } } } return false; }
/*! \brief Draw the raster data \param painter Painter \param xMap X-Scale Map \param yMap Y-Scale Map \param canvasRect Contents rectangle of the plot canvas */ void QwtPlotRasterItem::draw( QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect ) const { if ( canvasRect.isEmpty() || d_data->alpha == 0 ) return; const bool doCache = qwtUseCache( d_data->cache.policy, painter ); const QwtInterval xInterval = interval( Qt::XAxis ); const QwtInterval yInterval = interval( Qt::YAxis ); /* Scaling an image always results in a loss of precision/quality. So we always render the image in paint device resolution. */ QwtScaleMap xxMap, yyMap; qwtTransformMaps( painter->transform(), xMap, yMap, xxMap, yyMap ); QRectF paintRect = painter->transform().mapRect( canvasRect ); QRectF area = QwtScaleMap::invTransform( xxMap, yyMap, paintRect ); const QRectF br = boundingRect(); if ( br.isValid() && !br.contains( area ) ) { area &= br; if ( !area.isValid() ) return; paintRect = QwtScaleMap::transform( xxMap, yyMap, area ); } QRectF imageRect; QImage image; QRectF pixelRect = pixelHint(area); if ( !pixelRect.isEmpty() ) { // pixel in target device resolution const double dx = qAbs( xxMap.invTransform( 1 ) - xxMap.invTransform( 0 ) ); const double dy = qAbs( yyMap.invTransform( 1 ) - yyMap.invTransform( 0 ) ); if ( dx > pixelRect.width() && dy > pixelRect.height() ) { /* When the resolution of the data pixels is higher than the resolution of the target device we render in target device resolution. */ pixelRect = QRectF(); } } if ( pixelRect.isEmpty() ) { if ( QwtPainter::roundingAlignment( painter ) ) { // we want to have maps, where the boundaries of // the aligned paint rectangle exactly match the area paintRect = qwtAlignRect(paintRect); qwtAdjustMaps(xxMap, yyMap, area, paintRect); } // When we have no information about position and size of // data pixels we render in resolution of the paint device. image = compose(xxMap, yyMap, area, paintRect, paintRect.size().toSize(), doCache); if ( image.isNull() ) return; // Remove pixels at the boundaries, when explicitly // excluded in the intervals imageRect = qwtStripRect(paintRect, area, xxMap, yyMap, xInterval, yInterval); if ( imageRect != paintRect ) { const QRect r( qRound( imageRect.x() - paintRect.x()), qRound( imageRect.y() - paintRect.y() ), qRound( imageRect.width() ), qRound( imageRect.height() ) ); image = image.copy(r); } } else { if ( QwtPainter::roundingAlignment( painter ) ) paintRect = qwtAlignRect(paintRect); // align the area to the data pixels QRectF imageArea = qwtExpandToPixels(area, pixelRect); if ( imageArea.right() == xInterval.maxValue() && !( xInterval.borderFlags() & QwtInterval::ExcludeMaximum ) ) { imageArea.adjust(0, 0, pixelRect.width(), 0); } if ( imageArea.bottom() == yInterval.maxValue() && !( yInterval.borderFlags() & QwtInterval::ExcludeMaximum ) ) { imageArea.adjust(0, 0, 0, pixelRect.height() ); } QSize imageSize; imageSize.setWidth( qRound( imageArea.width() / pixelRect.width() ) ); imageSize.setHeight( qRound( imageArea.height() / pixelRect.height() ) ); image = compose(xxMap, yyMap, imageArea, paintRect, imageSize, doCache ); if ( image.isNull() ) return; imageRect = qwtStripRect(paintRect, area, xxMap, yyMap, xInterval, yInterval); if ( ( image.width() > 1 || image.height() > 1 ) && testPaintAttribute( PaintInDeviceResolution ) ) { // Because of rounding errors the pixels // need to be expanded manually to rectangles of // different sizes image = qwtExpandImage(image, xxMap, yyMap, imageArea, area, paintRect, xInterval, yInterval ); } } painter->save(); painter->setWorldTransform( QTransform() ); QwtPainter::drawImage( painter, imageRect, image ); painter->restore(); }