Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

qwt_plot_print.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 // vim: expandtab
00011 
00012 #include <qlabel.h>
00013 #include <qpainter.h>
00014 #include <qpaintdevicemetrics.h>
00015 #include "qwt_painter.h"
00016 #include "qwt_legend.h"
00017 #include "qwt_plot.h"
00018 #include "qwt_plot_layout.h"
00019 #include "qwt_plot_dict.h"
00020 #include "qwt_rect.h"
00021 #include "qwt_dyngrid_layout.h"
00022 #include "qwt_scale.h"
00023 #include "qwt_text.h"
00024 #include "qwt_math.h"
00025 
00072 void QwtPlot::print(QPaintDevice &paintDev,
00073    const QwtPlotPrintFilter &pfilter) const
00074 {
00075     QPaintDeviceMetrics mpr(&paintDev);
00076 
00077     QRect rect(0, 0, mpr.width(), mpr.height());
00078     double aspect = double(rect.width())/double(rect.height());
00079     if ((aspect < 1.0))
00080         rect.setHeight(int(aspect*rect.width()));
00081 
00082     QPainter p(&paintDev);
00083     print(&p, rect, pfilter);
00084 }
00085 
00095 void QwtPlot::print(QPainter *painter, const QRect &plotRect,
00096         const QwtPlotPrintFilter &pfilter) const
00097 {
00098     int axis;
00099 
00100     if ( painter == 0 || !painter->isActive() ||
00101             !plotRect.isValid() || size().isNull() )
00102        return;
00103 
00104     painter->save();
00105 
00106     // All paint operations need to be scaled according to
00107     // the paint device metrics. 
00108 
00109     QwtPainter::setMetricsMap(this, painter->device());
00110 
00111 #if QT_VERSION < 300 
00112     if ( painter->device()->isExtDev() )
00113     {
00114         QPaintDeviceMetrics metrics(painter->device());
00115         if ( metrics.logicalDpiX() == 72 && metrics.logicalDpiY() == 72 )
00116         {
00117             // In Qt 2.x QPrinter returns hardcoded wrong metrics.
00118             // So scaling won´t work: we reset to screen resolution
00119 
00120             QwtPainter::setMetricsMap(this, this);
00121         }
00122     }
00123 #endif
00124 
00125     const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
00126 
00127     // It is almost impossible to integrate into the Qt layout
00128     // framework, when using different fonts for printing
00129     // and screen. To avoid writing different and Qt unconform
00130     // layout engines we change the widget attributes, print and 
00131     // reset the widget attributes again. This way we produce a lot of
00132     // useless layout events ...
00133 
00134     pfilter.apply((QwtPlot *)this);
00135 
00136     int baseLineDists[QwtPlot::axisCnt];
00137     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00138     {
00139         // In case of no background we set the backbone of
00140         // the scale on the frame of the canvas.
00141 
00142         for (axis = 0; axis < QwtPlot::axisCnt; axis++ )
00143         {
00144             if ( d_scale[axis] )
00145             {
00146                 baseLineDists[axis] = d_scale[axis]->baseLineDist();
00147                 d_scale[axis]->setBaselineDist(0);
00148             }
00149         }
00150     }
00151     // Calculate the layout for the print.
00152 
00153     int layoutOptions = QwtPlotLayout::IgnoreScrollbars 
00154         | QwtPlotLayout::IgnoreFrames | QwtPlotLayout::AlignScales;
00155     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) )
00156         layoutOptions |= QwtPlotLayout::IgnoreMargin;
00157     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) )
00158         layoutOptions |= QwtPlotLayout::IgnoreLegend;
00159 
00160     d_layout->activate(this, QwtPainter::metricsMap().deviceToLayout(plotRect), 
00161         layoutOptions);
00162 
00163     if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle)
00164         && (!d_lblTitle->text().isEmpty()))
00165     {
00166         printTitle(painter, d_layout->titleRect());
00167     }
00168 
00169     if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend)
00170         && !d_legend->isEmpty() )
00171     {
00172         printLegend(painter, d_layout->legendRect());
00173     }
00174 
00175     for ( axis = 0; axis < QwtPlot::axisCnt; axis++ )
00176     {
00177         if (d_scale[axis])
00178         {
00179             int baseDist = d_scale[axis]->baseLineDist();
00180 
00181             int startDist, endDist;
00182             d_scale[axis]->minBorderDist(startDist, endDist);
00183 
00184             printScale(painter, axis, startDist, endDist,
00185                 baseDist, d_layout->scaleRect(axis));
00186         }
00187     }
00188 
00189     const QRect canvasRect = metricsMap.layoutToDevice(d_layout->canvasRect());
00190 
00191     // When using QwtPainter all sizes where computed in pixel
00192     // coordinates and scaled by QwtPainter later. This limits
00193     // the precision to screen resolution. A much better solution
00194     // is to scale the maps and print in unlimited resolution.
00195 
00196     QwtArray<QwtDiMap> map(axisCnt);
00197     for (axis = 0; axis < axisCnt; axis++)
00198     {
00199         const QwtScaleDiv &scaleDiv = d_as[axis].scaleDiv();
00200         map[axis].setDblRange(scaleDiv.lBound(),
00201             scaleDiv.hBound(), scaleDiv.logScale());
00202 
00203         double from, to;
00204         if ( axisEnabled(axis) )
00205         {
00206             const int sDist = d_scale[axis]->startBorderDist();
00207             const int eDist = d_scale[axis]->endBorderDist();
00208             const QRect &scaleRect = d_layout->scaleRect(axis);
00209 
00210             if ( axis == xTop || axis == xBottom )
00211             {
00212                 from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist);
00213                 to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist);
00214             }
00215             else
00216             {
00217                 from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist);
00218                 to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist);
00219             }
00220         }
00221         else
00222         {
00223             const int margin = plotLayout()->canvasMargin(axis);
00224 
00225             const QRect &canvasRect = plotLayout()->canvasRect();
00226             if ( axis == yLeft || axis == yRight )
00227             {
00228                 from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin);
00229                 to = metricsMap.layoutToDeviceX(canvasRect.top() + margin);
00230             }
00231             else
00232             {
00233                 from = metricsMap.layoutToDeviceY(canvasRect.left() + margin);
00234                 to = metricsMap.layoutToDeviceY(canvasRect.right() - margin);
00235             }
00236         }
00237         map[axis].setIntRange( qwtInt(from), qwtInt(to));
00238     }
00239 
00240 
00241     // The maps are already scaled. 
00242     QwtPainter::setMetricsMap(painter->device(), painter->device());
00243 
00244     printCanvas(painter, canvasRect, map, pfilter);
00245 
00246     QwtPainter::resetMetricsMap();
00247 
00248     d_layout->invalidate();
00249 
00250     // reset all widgets with their original attributes.
00251     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00252     {
00253         // restore the previous base line dists
00254 
00255         for (axis = 0; axis < QwtPlot::axisCnt; axis++ )
00256         {
00257             if ( d_scale[axis] )
00258                 d_scale[axis]->setBaselineDist(baseLineDists[axis]);
00259         }
00260     }
00261 
00262     pfilter.reset((QwtPlot *)this);
00263 
00264     painter->restore();
00265 }
00266 
00274 void QwtPlot::printTitle(QPainter *painter, const QRect &rect) const
00275 {
00276     QwtText *text = QwtText::makeText(
00277         d_lblTitle->text(), d_lblTitle->textFormat(),
00278         d_lblTitle->alignment(), d_lblTitle->font(),
00279         d_lblTitle->palette().color(
00280             QPalette::Active, QColorGroup::Foreground)); 
00281 
00282     text->draw(painter, rect);
00283     delete text;
00284 }
00285 
00293 void QwtPlot::printLegend(QPainter *painter, const QRect &rect) const
00294 {
00295     if ( !d_legend || d_legend->isEmpty() )
00296         return;
00297 
00298     QLayout *l = d_legend->contentsWidget()->layout();
00299     if ( l == 0 || !l->inherits("QwtDynGridLayout") )
00300         return;
00301 
00302     QwtDynGridLayout *legendLayout = (QwtDynGridLayout *)l;
00303 
00304     uint numCols = legendLayout->columnsForWidth(rect.width());
00305     QValueList<QRect> itemRects = 
00306         legendLayout->layoutItems(rect, numCols);
00307 
00308     int index = 0;
00309 
00310     QLayoutIterator layoutIterator = legendLayout->iterator();
00311     for ( QLayoutItem *item = layoutIterator.current(); 
00312         item != 0; item = ++layoutIterator)
00313     {
00314         QWidget *w = item->widget();
00315         if ( w )
00316         {
00317             painter->save();
00318             painter->setClipping(TRUE);
00319             QwtPainter::setClipRect(painter, itemRects[index]);
00320 
00321             printLegendItem(painter, w, itemRects[index]);
00322 
00323             index++;
00324             painter->restore();
00325         }
00326     }
00327 }
00328 
00337 void QwtPlot::printLegendItem(QPainter *painter, 
00338     const QWidget *w, const QRect &rect) const
00339 {
00340     const QwtLegendItem *item = NULL;
00341 
00342     if ( w->inherits("QwtLegendButton") )
00343         item = (QwtLegendButton *)w;
00344 
00345     if ( w->inherits("QwtLegendLabel") )
00346         item = (QwtLegendLabel *)w;
00347 
00348     if ( item )
00349     {
00350         painter->setFont(w->font());
00351         item->drawItem(painter, rect);
00352     }
00353 }
00354 
00367 void QwtPlot::printScale(QPainter *painter,
00368     int axis, int startDist, int endDist, int baseDist, 
00369     const QRect &rect) const
00370 {
00371     if (!d_axisEnabled[axis])
00372         return;
00373 
00374     QwtScaleDraw::Orientation o;
00375     int x, y, w;
00376 
00377     switch(axis)
00378     {
00379         case yLeft:
00380         {
00381             x = rect.right() - baseDist;
00382             y = rect.y() + startDist;
00383             w = rect.height() - startDist - endDist;
00384             o = QwtScaleDraw::Left;
00385             break;
00386         }
00387         case yRight:
00388         {
00389             x = rect.left() + baseDist;
00390             y = rect.y() + startDist;
00391             w = rect.height() - startDist - endDist;
00392             o = QwtScaleDraw::Right;
00393             break;
00394         }
00395         case xTop:
00396         {
00397             x = rect.left() + startDist;
00398             y = rect.bottom() - baseDist;
00399             w = rect.width() - startDist - endDist;
00400             o = QwtScaleDraw::Top;
00401             break;
00402         }
00403         case xBottom:
00404         {
00405             x = rect.left() + startDist;
00406             y = rect.top() + baseDist;
00407             w = rect.width() - startDist - endDist;
00408             o = QwtScaleDraw::Bottom;
00409             break;
00410         }
00411         default:
00412             return;
00413     }
00414 
00415     const QwtScale *scale = d_scale[axis];
00416     scale->drawTitle(painter, o, rect);
00417 
00418     painter->save();
00419     QPen pen(painter->pen());
00420     pen.setColor(
00421         scale->palette().color(QPalette::Active, QColorGroup::Foreground));
00422     painter->setPen(pen);
00423     painter->setFont(scale->font());
00424 
00425     QwtScaleDraw *sd = (QwtScaleDraw *)scale->scaleDraw();
00426     int xSd = sd->x();
00427     int ySd = sd->y();
00428     int lengthSd = sd->length();
00429 
00430     sd->setGeometry(x, y, w, o);
00431     sd->draw(painter);
00432     sd->setGeometry(xSd, ySd, lengthSd, o); // reset previous values
00433     painter->restore();
00434 }
00435 
00446 void QwtPlot::printCanvas(QPainter *painter, const QRect &canvasRect,
00447     const QwtArray<QwtDiMap> &map, const QwtPlotPrintFilter &pfilter) const
00448 {
00449     if ( pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground )
00450     {
00451         QwtPainter::fillRect(painter, QRect(canvasRect.x(), canvasRect.y(), 
00452             canvasRect.width() - 1, canvasRect.height() - 1),
00453             canvasBackground());
00454     }
00455     else
00456         QwtPainter::drawRect(painter, canvasRect.x() - 1, canvasRect.y() - 1,
00457             canvasRect.width() + 1, canvasRect.height() + 1);
00458 
00459     painter->setClipping(TRUE);
00460     QwtPainter::setClipRect(painter, canvasRect);
00461 
00462     drawCanvasItems(painter, canvasRect, map, pfilter);
00463 }
00464 
00465 // Local Variables:
00466 // mode: C++
00467 // c-file-style: "stroustrup"
00468 // indent-tabs-mode: nil
00469 // End:

Generated on Sun Nov 21 11:12:43 2004 for Qwt User's Guide by doxygen 1.3.5