/*! Render the legend into a given rectangle. \param plot Plot widget \param painter Painter \param rect Bounding rectangle */ void QwtPlotRenderer::renderLegend( const QwtPlot *plot, QPainter *painter, const QRectF &rect ) const { if ( !plot->legend() || plot->legend()->isEmpty() ) return; if ( !( d_data->discardFlags & DiscardBackground ) ) { if ( plot->legend()->autoFillBackground() || plot->legend()->testAttribute( Qt::WA_StyledBackground ) ) { qwtRenderBackground( painter, rect, plot->legend() ); } } const QwtDynGridLayout *legendLayout = qobject_cast<QwtDynGridLayout *>( plot->legend()->contentsWidget()->layout() ); if ( legendLayout == NULL ) return; int left, right, top, bottom; plot->legend()->getContentsMargins( &left, &top, &right, &bottom ); QRect layoutRect; layoutRect.setLeft( qCeil( rect.left() ) + left ); layoutRect.setTop( qCeil( rect.top() ) + top ); layoutRect.setRight( qFloor( rect.right() ) - right ); layoutRect.setBottom( qFloor( rect.bottom() ) - bottom ); uint numCols = legendLayout->columnsForWidth( layoutRect.width() ); QList<QRect> itemRects = legendLayout->layoutItems( layoutRect, numCols ); int index = 0; for ( int i = 0; i < legendLayout->count(); i++ ) { QLayoutItem *item = legendLayout->itemAt( i ); QWidget *w = item->widget(); if ( w ) { painter->save(); painter->setClipRect( itemRects[index] ); renderLegendItem( plot, painter, w, itemRects[index] ); index++; painter->restore(); } } }
/*! Render the legend into a given rectangle. \param plot Plot widget \param painter Painter \param rect Bounding rectangle */ void QwtPlotRenderer::renderLegend( const QwtPlot *plot, QPainter *painter, const QRectF &rect ) const { if ( !plot->legend() || plot->legend()->isEmpty() ) return; if ( !( d_data->discardFlags & DiscardBackground ) ) { if ( plot->legend()->autoFillBackground() || plot->legend()->testAttribute( Qt::WA_StyledBackground ) ) { qwtRenderBackground( painter, rect, plot->legend() ); } } const QwtDynGridLayout *legendLayout = qobject_cast<QwtDynGridLayout *>( plot->legend()->contentsWidget()->layout() ); if ( legendLayout == NULL ) return; uint numCols = legendLayout->columnsForWidth( rect.width() ); QList<QRect> itemRects = legendLayout->layoutItems( rect.toRect(), numCols ); int index = 0; for ( int i = 0; i < legendLayout->count(); i++ ) { QLayoutItem *item = legendLayout->itemAt( i ); QWidget *w = item->widget(); if ( w ) { painter->save(); painter->setClipRect( itemRects[index] ); renderLegendItem( plot, painter, w, itemRects[index] ); index++; painter->restore(); } } }
/*! Render the legend item into a given rectangle. \param plot Plot widget \param painter Painter \param widget Widget representing a legend item \param rect Bounding rectangle \note When widget is not derived from QwtLegendItem renderLegendItem does nothing and needs to be overloaded */ void QwtPlotRenderer::renderLegendItem( const QwtPlot *plot, QPainter *painter, const QWidget *widget, const QRectF &rect ) const { if ( !( d_data->discardFlags & DiscardBackground ) ) { if ( widget->autoFillBackground() || widget->testAttribute( Qt::WA_StyledBackground ) ) { qwtRenderBackground( painter, rect, widget ); } } const QwtLegendItem *item = qobject_cast<const QwtLegendItem *>( widget ); if ( item ) { const QSize sz = item->identifierSize(); const QRectF identifierRect( rect.x() + item->margin(), rect.center().y() - 0.5 * sz.height(), sz.width(), sz.height() ); QwtLegendItemManager *itemManger = plot->legend()->find( item ); if ( itemManger ) { painter->save(); painter->setClipRect( identifierRect, Qt::IntersectClip ); itemManger->drawLegendIdentifier( painter, identifierRect ); painter->restore(); } // Label QRectF titleRect = rect; titleRect.setX( identifierRect.right() + 2 * item->spacing() ); painter->setFont( item->font() ); item->text().draw( painter, titleRect ); } }
/*! Render the canvas into a given rectangle. \param plot Plot widget \param painter Painter \param map Maps mapping between plot and paint device coordinates \param canvasRect Canvas rectangle */ void QwtPlotRenderer::renderCanvas( const QwtPlot *plot, QPainter *painter, const QRectF &canvasRect, const QwtScaleMap *map ) const { painter->save(); QPainterPath clipPath; QRectF r = canvasRect.adjusted( 0.0, 0.0, -1.0, -1.0 ); if ( d_data->layoutFlags & FrameWithScales ) { r.adjust( -1.0, -1.0, 1.0, 1.0 ); painter->setPen( QPen( Qt::black ) ); if ( !( d_data->discardFlags & DiscardCanvasBackground ) ) { const QBrush bgBrush = plot->canvas()->palette().brush( plot->backgroundRole() ); painter->setBrush( bgBrush ); } QwtPainter::drawRect( painter, r ); } else { if ( !( d_data->discardFlags & DiscardCanvasBackground ) ) { qwtRenderBackground( painter, r, plot->canvas() ); if ( plot->canvas()->testAttribute( Qt::WA_StyledBackground ) ) { // The clip region is calculated in integers // To avoid too much rounding errors better // calculate it in target device resolution // TODO ... int x1 = qCeil( canvasRect.left() ); int x2 = qFloor( canvasRect.right() ); int y1 = qCeil( canvasRect.top() ); int y2 = qFloor( canvasRect.bottom() ); clipPath = plot->canvas()->borderPath( QRect( x1, y1, x2 - x1 - 1, y2 - y1 - 1 ) ); } } } painter->restore(); painter->save(); if ( clipPath.isEmpty() ) painter->setClipRect( canvasRect ); else painter->setClipPath( clipPath ); plot->drawItems( painter, canvasRect, map ); painter->restore(); }
/*! Paint the contents of a QwtPlot instance into a given rectangle. \param plot Plot to be rendered \param painter Painter \param plotRect Bounding rectangle \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment() */ void QwtPlotRenderer::render( QwtPlot *plot, QPainter *painter, const QRectF &plotRect ) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || plot->size().isNull() ) return; if ( !( d_data->discardFlags & DiscardBackground ) ) qwtRenderBackground( painter, plotRect, plot ); /* The layout engine uses the same methods as they are used by the Qt layout system. Therefore we need to calculate the layout in screen coordinates and paint with a scaled painter. */ QTransform transform; transform.scale( double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(), double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() ); QRectF layoutRect = transform.inverted().mapRect( plotRect ); if ( !( d_data->discardFlags & DiscardBackground ) ) { // subtract the contents margins int left, top, right, bottom; plot->getContentsMargins( &left, &top, &right, &bottom ); layoutRect.adjust( left, top, -right, -bottom ); } int baseLineDists[QwtPlot::axisCnt]; if ( d_data->layoutFlags & FrameWithScales ) { for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->margin(); scaleWidget->setMargin( 0 ); } if ( !plot->axisEnabled( axisId ) ) { int left = 0; int right = 0; int top = 0; int bottom = 0; // When we have a scale the frame is painted on // the position of the backbone - otherwise we // need to introduce a margin around the canvas switch( axisId ) { case QwtPlot::yLeft: layoutRect.adjust( 1, 0, 0, 0 ); break; case QwtPlot::yRight: layoutRect.adjust( 0, 0, -1, 0 ); break; case QwtPlot::xTop: layoutRect.adjust( 0, 1, 0, 0 ); break; case QwtPlot::xBottom: layoutRect.adjust( 0, 0, 0, -1 ); break; default: break; } layoutRect.adjust( left, top, right, bottom ); } } } // Calculate the layout for the document. QwtPlotLayout::Options layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( d_data->discardFlags & DiscardLegend ) layoutOptions |= QwtPlotLayout::IgnoreLegend; plot->plotLayout()->activate( plot, layoutRect, layoutOptions ); // now start painting painter->save(); painter->setWorldTransform( transform, true ); // canvas QwtScaleMap maps[QwtPlot::axisCnt]; buildCanvasMaps( plot, plot->plotLayout()->canvasRect(), maps ); renderCanvas( plot, painter, plot->plotLayout()->canvasRect(), maps ); if ( !( d_data->discardFlags & DiscardTitle ) && ( !plot->titleLabel()->text().isEmpty() ) ) { renderTitle( plot, painter, plot->plotLayout()->titleRect() ); } if ( !( d_data->discardFlags & DiscardLegend ) && plot->legend() && !plot->legend()->isEmpty() ) { renderLegend( plot, painter, plot->plotLayout()->legendRect() ); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) { int baseDist = scaleWidget->margin(); int startDist, endDist; scaleWidget->getBorderDistHint( startDist, endDist ); renderScale( plot, painter, axisId, startDist, endDist, baseDist, plot->plotLayout()->scaleRect( axisId ) ); } } plot->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( d_data->layoutFlags & FrameWithScales ) { // restore the previous base line dists for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) scaleWidget->setMargin( baseLineDists[axisId] ); } } painter->restore(); }
/*! Paint the contents of a QwtPlot instance into a given rectangle. \param plot Plot to be rendered \param painter Painter \param plotRect Bounding rectangle \sa renderDocument(), renderTo(), QwtPainter::setRoundingAlignment() */ void QwtPlotRenderer::render( QwtPlot *plot, QPainter *painter, const QRectF &plotRect ) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || plot->size().isNull() ) return; if ( !( d_data->discardFlags & DiscardBackground ) ) qwtRenderBackground( painter, plotRect, plot ); /* The layout engine uses the same methods as they are used by the Qt layout system. Therefore we need to calculate the layout in screen coordinates and paint with a scaled painter. */ QTransform transform; transform.scale( double( painter->device()->logicalDpiX() ) / plot->logicalDpiX(), double( painter->device()->logicalDpiY() ) / plot->logicalDpiY() ); painter->save(); int baseLineDists[QwtPlot::axisCnt]; if ( d_data->layoutFlags & FrameWithScales ) { for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->margin(); scaleWidget->setMargin( 0 ); } } } // Calculate the layout for the print. QwtPlotLayout::Options layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( d_data->discardFlags & DiscardLegend ) layoutOptions |= QwtPlotLayout::IgnoreLegend; const QRectF layoutRect = transform.inverted().mapRect( plotRect ); plot->plotLayout()->activate( plot, layoutRect, layoutOptions ); painter->setWorldTransform( transform, true ); // canvas QwtScaleMap maps[QwtPlot::axisCnt]; buildCanvasMaps( plot, plot->plotLayout()->canvasRect(), maps ); renderCanvas( plot, painter, plot->plotLayout()->canvasRect(), maps ); if ( !( d_data->discardFlags & DiscardTitle ) && ( !plot->titleLabel()->text().isEmpty() ) ) { renderTitle( plot, painter, plot->plotLayout()->titleRect() ); } if ( !( d_data->discardFlags & DiscardLegend ) && plot->legend() && !plot->legend()->isEmpty() ) { renderLegend( plot, painter, plot->plotLayout()->legendRect() ); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) { int baseDist = scaleWidget->margin(); int startDist, endDist; scaleWidget->getBorderDistHint( startDist, endDist ); renderScale( plot, painter, axisId, startDist, endDist, baseDist, plot->plotLayout()->scaleRect( axisId ) ); } } plot->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( d_data->layoutFlags & FrameWithScales ) { // restore the previous base line dists for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = plot->axisWidget( axisId ); if ( scaleWidget ) scaleWidget->setMargin( baseLineDists[axisId] ); } } painter->restore(); }