/*! \brief Paint the plot into a given rectangle. Paint the contents of a QwtPlot instance into a given rectangle. \param painter Painter \param plotRect Bounding rectangle \param pfilter Print filter \sa QwtPlotPrintFilter */ void QwtPlot::print(QPainter *painter, const QRect &plotRect, const QwtPlotPrintFilter &pfilter) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || size().isNull() ) return; painter->save(); // All paint operations need to be scaled according to // the paint device metrics. QwtPainter::setMetricsMap(this, painter->device()); const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); // It is almost impossible to integrate into the Qt layout // framework, when using different fonts for printing // and screen. To avoid writing different and Qt unconform // layout engines we change the widget attributes, print and // reset the widget attributes again. This way we produce a lot of // useless layout events ... pfilter.apply((QwtPlot *)this); int baseLineDists[QwtPlot::axisCnt]; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // In case of no background we set the backbone of // the scale on the frame of the canvas. for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->baseLineDist(); scaleWidget->setBaselineDist(0); } } } // Calculate the layout for the print. int layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) ) layoutOptions |= QwtPlotLayout::IgnoreMargin; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) ) layoutOptions |= QwtPlotLayout::IgnoreLegend; ((QwtPlot *)this)->plotLayout()->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), layoutOptions); if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle) && (!titleLabel()->text().isEmpty())) { printTitle(painter, plotLayout()->titleRect()); } if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend) && legend() && !legend()->isEmpty() ) { printLegend(painter, plotLayout()->legendRect()); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if (scaleWidget) { int baseDist = scaleWidget->baseLineDist(); int startDist, endDist; scaleWidget->getBorderDistHint(startDist, endDist); printScale(painter, axisId, startDist, endDist, baseDist, plotLayout()->scaleRect(axisId)); } } const QRect canvasRect = metricsMap.layoutToDevice(plotLayout()->canvasRect()); // When using QwtPainter all sizes where computed in pixel // coordinates and scaled by QwtPainter later. This limits // the precision to screen resolution. A much better solution // is to scale the maps and print in unlimited resolution. QwtArray<QwtScaleMap> map(axisCnt); for (axisId = 0; axisId < axisCnt; axisId++) { map[axisId].setTransformation(axisScaleEngine(axisId)->transformation()); const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId); map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound()); double from, to; if ( axisEnabled(axisId) ) { const int sDist = axisWidget(axisId)->startBorderDist(); const int eDist = axisWidget(axisId)->endBorderDist(); const QRect &scaleRect = plotLayout()->scaleRect(axisId); if ( axisId == xTop || axisId == xBottom ) { from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist); to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist); } else { from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist); to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist); } } else { const int margin = plotLayout()->canvasMargin(axisId); const QRect &canvasRect = plotLayout()->canvasRect(); if ( axisId == yLeft || axisId == yRight ) { from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin); to = metricsMap.layoutToDeviceX(canvasRect.top() + margin); } else { from = metricsMap.layoutToDeviceY(canvasRect.left() + margin); to = metricsMap.layoutToDeviceY(canvasRect.right() - margin); } } map[axisId].setPaintXInterval(from, to); } // The canvas maps are already scaled. QwtPainter::setMetricsMap(painter->device(), painter->device()); printCanvas(painter, canvasRect, map, pfilter); QwtPainter::resetMetricsMap(); ((QwtPlot *)this)->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // restore the previous base line dists for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) scaleWidget->setBaselineDist(baseLineDists[axisId]); } } pfilter.reset((QwtPlot *)this); painter->restore(); }
/*! \brief Paint the plot into a given rectangle. Paint the contents of a QwtPlot instance into a given rectangle. \param painter Painter \param plotRect Bounding rectangle \param pfilter Print filter \sa QwtPlotPrintFilter */ void QwtPlot::print(QPainter *painter, const QRect &plotRect, const QwtPlotPrintFilter &pfilter) const { int axisId; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || size().isNull() ) return; painter->save(); #if 1 /* PDF: In Qt4 ( <= 4.3.2 ) the scales are painted in gray instead of black. See http://trolltech.com/developer/task-tracker/index_html?id=184671&method=entry The dummy lines below work around the problem. */ const QPen pen = painter->pen(); painter->setPen(QPen(Qt::black, 1)); painter->setPen(pen); #endif // All paint operations need to be scaled according to // the paint device metrics. QwtPainter::setMetricsMap(this, painter->device()); const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); // It is almost impossible to integrate into the Qt layout // framework, when using different fonts for printing // and screen. To avoid writing different and Qt unconform // layout engines we change the widget attributes, print and // reset the widget attributes again. This way we produce a lot of // useless layout events ... pfilter.apply((QwtPlot *)this); int baseLineDists[QwtPlot::axisCnt]; if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales ) { for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) { baseLineDists[axisId] = scaleWidget->margin(); scaleWidget->setMargin(0); } } } // Calculate the layout for the print. int layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) ) layoutOptions |= QwtPlotLayout::IgnoreMargin; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) ) layoutOptions |= QwtPlotLayout::IgnoreLegend; ((QwtPlot *)this)->plotLayout()->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), layoutOptions); if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle) && (!titleLabel()->text().isEmpty())) { printTitle(painter, plotLayout()->titleRect()); } if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend) && legend() && !legend()->isEmpty() ) { printLegend(painter, plotLayout()->legendRect()); } for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if (scaleWidget) { int baseDist = scaleWidget->margin(); int startDist, endDist; scaleWidget->getBorderDistHint(startDist, endDist); printScale(painter, axisId, startDist, endDist, baseDist, plotLayout()->scaleRect(axisId)); } } QRect canvasRect = plotLayout()->canvasRect(); /* The border of the bounding rect needs to ba scaled to layout coordinates, so that it is aligned to the axes */ QRect boundingRect( canvasRect.left() - 1, canvasRect.top() - 1, canvasRect.width() + 2, canvasRect.height() + 2); boundingRect = metricsMap.layoutToDevice(boundingRect); boundingRect.setWidth(boundingRect.width() - 1); boundingRect.setHeight(boundingRect.height() - 1); canvasRect = metricsMap.layoutToDevice(canvasRect); // When using QwtPainter all sizes where computed in pixel // coordinates and scaled by QwtPainter later. This limits // the precision to screen resolution. A better solution // is to scale the maps and print in unlimited resolution. QwtScaleMap map[axisCnt]; for (axisId = 0; axisId < axisCnt; axisId++) { map[axisId].setTransformation(axisScaleEngine(axisId)->transformation()); const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId); map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound()); double from, to; if ( axisEnabled(axisId) ) { const int sDist = axisWidget(axisId)->startBorderDist(); const int eDist = axisWidget(axisId)->endBorderDist(); const QRect &scaleRect = plotLayout()->scaleRect(axisId); if ( axisId == xTop || axisId == xBottom ) { from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist); to = metricsMap.layoutToDeviceX(scaleRect.right() + 1 - eDist); } else { from = metricsMap.layoutToDeviceY(scaleRect.bottom() + 1 - eDist ); to = metricsMap.layoutToDeviceY(scaleRect.top() + sDist); } } else { int margin = plotLayout()->canvasMargin(axisId); if ( axisId == yLeft || axisId == yRight ) { margin = metricsMap.layoutToDeviceY(margin); from = canvasRect.bottom() - margin; to = canvasRect.top() + margin; } else { margin = metricsMap.layoutToDeviceX(margin); from = canvasRect.left() + margin; to = canvasRect.right() - margin; } } map[axisId].setPaintXInterval(from, to); } // The canvas maps are already scaled. QwtPainter::setMetricsMap(painter->device(), painter->device()); printCanvas(painter, boundingRect, canvasRect, map, pfilter); QwtPainter::resetMetricsMap(); ((QwtPlot *)this)->plotLayout()->invalidate(); // reset all widgets with their original attributes. if ( pfilter.options() & QwtPlotPrintFilter::PrintFrameWithScales ) { // restore the previous base line dists for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ ) { QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId); if ( scaleWidget ) scaleWidget->setMargin(baseLineDists[axisId]); } } pfilter.reset((QwtPlot *)this); painter->restore(); }
/*! \brief Paint the plot into a given rectangle. Paint the contents of a QwtPlot instance into a given rectangle. \param painter Painter \param plotRect Bounding rectangle \param pfilter Print filter \sa QwtPlotPrintFilter */ void QwtPlot::print(QPainter *painter, const QRect &plotRect, const QwtPlotPrintFilter &pfilter) const { int axis; if ( painter == 0 || !painter->isActive() || !plotRect.isValid() || size().isNull() ) return; painter->save(); // All paint operations need to be scaled according to // the paint device metrics. QwtPainter::setMetricsMap(this, painter->device()); #if QT_VERSION < 300 if ( painter->device()->isExtDev() ) { QPaintDeviceMetrics metrics(painter->device()); if ( metrics.logicalDpiX() == 72 && metrics.logicalDpiY() == 72 ) { // In Qt 2.x QPrinter returns hardcoded wrong metrics. // So scaling won´t work: we reset to screen resolution QwtPainter::setMetricsMap(this, this); } } #endif const QwtMetricsMap &metricsMap = QwtPainter::metricsMap(); // It is almost impossible to integrate into the Qt layout // framework, when using different fonts for printing // and screen. To avoid writing different and Qt unconform // layout engines we change the widget attributes, print and // reset the widget attributes again. This way we produce a lot of // useless layout events ... pfilter.apply((QwtPlot *)this); int baseLineDists[QwtPlot::axisCnt]; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // In case of no background we set the backbone of // the scale on the frame of the canvas. for (axis = 0; axis < QwtPlot::axisCnt; axis++ ) { if ( d_scale[axis] ) { baseLineDists[axis] = d_scale[axis]->baseLineDist(); d_scale[axis]->setBaselineDist(0); } } } // Calculate the layout for the print. int layoutOptions = QwtPlotLayout::IgnoreScrollbars | QwtPlotLayout::IgnoreFrames; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) ) layoutOptions |= QwtPlotLayout::IgnoreMargin; if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) ) layoutOptions |= QwtPlotLayout::IgnoreLegend; d_layout->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), layoutOptions); if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle) && (!d_lblTitle->text().isEmpty())) { printTitle(painter, d_layout->titleRect()); } if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend) && !d_legend->isEmpty() ) { printLegend(painter, d_layout->legendRect()); } for ( axis = 0; axis < QwtPlot::axisCnt; axis++ ) { if (d_scale[axis]) { int baseDist = d_scale[axis]->baseLineDist(); int startDist, endDist; d_scale[axis]->minBorderDist(startDist, endDist); printScale(painter, axis, startDist, endDist, baseDist, d_layout->scaleRect(axis)); } } const QRect canvasRect = metricsMap.layoutToDevice(d_layout->canvasRect()); // When using QwtPainter all sizes where computed in pixel // coordinates and scaled by QwtPainter later. This limits // the precision to screen resolution. A much better solution // is to scale the maps and print in unlimited resolution. QwtArray<QwtDiMap> map(axisCnt); for (axis = 0; axis < axisCnt; axis++) { const QwtScaleDiv &scaleDiv = d_as[axis].scaleDiv(); map[axis].setDblRange(scaleDiv.lBound(), scaleDiv.hBound(), scaleDiv.logScale()); double from, to; if ( axisEnabled(axis) ) { const int sDist = d_scale[axis]->startBorderDist(); const int eDist = d_scale[axis]->endBorderDist(); const QRect &scaleRect = d_layout->scaleRect(axis); if ( axis == xTop || axis == xBottom ) { from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist); to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist); } else { from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist); to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist); } } else { const int margin = plotLayout()->canvasMargin(axis); const QRect &canvasRect = plotLayout()->canvasRect(); if ( axis == yLeft || axis == yRight ) { from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin); to = metricsMap.layoutToDeviceX(canvasRect.top() + margin); } else { from = metricsMap.layoutToDeviceY(canvasRect.left() + margin); to = metricsMap.layoutToDeviceY(canvasRect.right() - margin); } } map[axis].setIntRange( qwtInt(from), qwtInt(to)); } // The maps are already scaled. QwtPainter::setMetricsMap(painter->device(), painter->device()); printCanvas(painter, canvasRect, map, pfilter); QwtPainter::resetMetricsMap(); d_layout->invalidate(); // reset all widgets with their original attributes. if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) ) { // restore the previous base line dists for (axis = 0; axis < QwtPlot::axisCnt; axis++ ) { if ( d_scale[axis] ) d_scale[axis]->setBaselineDist(baseLineDists[axis]); } } pfilter.reset((QwtPlot *)this); painter->restore(); }