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: