Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | 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 <qpainter.h>
00013 #if QT_VERSION < 0x040000
00014 #include <qpaintdevicemetrics.h>
00015 #else
00016 #include <qpaintengine.h>
00017 #endif
00018 #include "qwt_painter.h"
00019 #include "qwt_legend_item.h"
00020 #include "qwt_plot.h"
00021 #include "qwt_plot_canvas.h"
00022 #include "qwt_plot_layout.h"
00023 #include "qwt_legend.h"
00024 #include "qwt_rect.h"
00025 #include "qwt_dyngrid_layout.h"
00026 #include "qwt_scale_widget.h"
00027 #include "qwt_scale_engine.h"
00028 #include "qwt_text.h"
00029 #include "qwt_text_label.h"
00030 #include "qwt_math.h"
00031 
00044 void QwtPlot::print(QPaintDevice &paintDev,
00045    const QwtPlotPrintFilter &pfilter) const
00046 {
00047 #if QT_VERSION < 0x040000
00048     QPaintDeviceMetrics mpr(&paintDev);
00049     int w = mpr.width();
00050     int h = mpr.height();
00051 #else
00052     int w = paintDev.width();
00053     int h = paintDev.height();
00054 #endif
00055 
00056     QRect rect(0, 0, w, h);
00057     double aspect = double(rect.width())/double(rect.height());
00058     if ((aspect < 1.0))
00059         rect.setHeight(int(aspect*rect.width()));
00060 
00061     QPainter p(&paintDev);
00062     print(&p, rect, pfilter);
00063 }
00064 
00074 void QwtPlot::print(QPainter *painter, const QRect &plotRect,
00075         const QwtPlotPrintFilter &pfilter) const
00076 {
00077     int axisId;
00078 
00079     if ( painter == 0 || !painter->isActive() ||
00080             !plotRect.isValid() || size().isNull() )
00081        return;
00082 
00083     painter->save();
00084 
00085     // All paint operations need to be scaled according to
00086     // the paint device metrics. 
00087 
00088     QwtPainter::setMetricsMap(this, painter->device());
00089     const QwtMetricsMap &metricsMap = QwtPainter::metricsMap();
00090 
00091     // It is almost impossible to integrate into the Qt layout
00092     // framework, when using different fonts for printing
00093     // and screen. To avoid writing different and Qt unconform
00094     // layout engines we change the widget attributes, print and 
00095     // reset the widget attributes again. This way we produce a lot of
00096     // useless layout events ...
00097 
00098     pfilter.apply((QwtPlot *)this);
00099 
00100     int baseLineDists[QwtPlot::axisCnt];
00101     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00102     {
00103         // In case of no background we set the backbone of
00104         // the scale on the frame of the canvas.
00105 
00106         for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00107         {
00108             QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00109             if ( scaleWidget )
00110             {
00111                 baseLineDists[axisId] = scaleWidget->baseLineDist();
00112                 scaleWidget->setBaselineDist(0);
00113             }
00114         }
00115     }
00116     // Calculate the layout for the print.
00117 
00118     int layoutOptions = QwtPlotLayout::IgnoreScrollbars 
00119         | QwtPlotLayout::IgnoreFrames;
00120     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintMargin) )
00121         layoutOptions |= QwtPlotLayout::IgnoreMargin;
00122     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintLegend) )
00123         layoutOptions |= QwtPlotLayout::IgnoreLegend;
00124 
00125     ((QwtPlot *)this)->plotLayout()->activate(this, 
00126         QwtPainter::metricsMap().deviceToLayout(plotRect), 
00127         layoutOptions);
00128 
00129     if ((pfilter.options() & QwtPlotPrintFilter::PrintTitle)
00130         && (!titleLabel()->text().isEmpty()))
00131     {
00132         printTitle(painter, plotLayout()->titleRect());
00133     }
00134 
00135     if ( (pfilter.options() & QwtPlotPrintFilter::PrintLegend)
00136         && legend() && !legend()->isEmpty() )
00137     {
00138         printLegend(painter, plotLayout()->legendRect());
00139     }
00140 
00141     for ( axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00142     {
00143         QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00144         if (scaleWidget)
00145         {
00146             int baseDist = scaleWidget->baseLineDist();
00147 
00148             int startDist, endDist;
00149             scaleWidget->getBorderDistHint(startDist, endDist);
00150 
00151             printScale(painter, axisId, startDist, endDist,
00152                 baseDist, plotLayout()->scaleRect(axisId));
00153         }
00154     }
00155 
00156     const QRect canvasRect = metricsMap.layoutToDevice(plotLayout()->canvasRect());
00157 
00158     // When using QwtPainter all sizes where computed in pixel
00159     // coordinates and scaled by QwtPainter later. This limits
00160     // the precision to screen resolution. A much better solution
00161     // is to scale the maps and print in unlimited resolution.
00162 
00163     QwtArray<QwtScaleMap> map(axisCnt);
00164     for (axisId = 0; axisId < axisCnt; axisId++)
00165     {
00166         map[axisId].setTransformation(axisScaleEngine(axisId)->transformation());
00167 
00168         const QwtScaleDiv &scaleDiv = *axisScaleDiv(axisId);
00169         map[axisId].setScaleInterval(scaleDiv.lBound(), scaleDiv.hBound());
00170 
00171         double from, to;
00172         if ( axisEnabled(axisId) )
00173         {
00174             const int sDist = axisWidget(axisId)->startBorderDist();
00175             const int eDist = axisWidget(axisId)->endBorderDist();
00176             const QRect &scaleRect = plotLayout()->scaleRect(axisId);
00177 
00178             if ( axisId == xTop || axisId == xBottom )
00179             {
00180                 from = metricsMap.layoutToDeviceX(scaleRect.left() + sDist);
00181                 to = metricsMap.layoutToDeviceX(scaleRect.right() - eDist);
00182             }
00183             else
00184             {
00185                 from = metricsMap.layoutToDeviceY(scaleRect.bottom() - sDist);
00186                 to = metricsMap.layoutToDeviceY(scaleRect.top() + eDist);
00187             }
00188         }
00189         else
00190         {
00191             const int margin = plotLayout()->canvasMargin(axisId);
00192 
00193             const QRect &canvasRect = plotLayout()->canvasRect();
00194             if ( axisId == yLeft || axisId == yRight )
00195             {
00196                 from = metricsMap.layoutToDeviceX(canvasRect.bottom() - margin);
00197                 to = metricsMap.layoutToDeviceX(canvasRect.top() + margin);
00198             }
00199             else
00200             {
00201                 from = metricsMap.layoutToDeviceY(canvasRect.left() + margin);
00202                 to = metricsMap.layoutToDeviceY(canvasRect.right() - margin);
00203             }
00204         }
00205         map[axisId].setPaintXInterval(from, to);
00206     }
00207 
00208 
00209     // The canvas maps are already scaled. 
00210     QwtPainter::setMetricsMap(painter->device(), painter->device());
00211 
00212     printCanvas(painter, canvasRect, map, pfilter);
00213 
00214     QwtPainter::resetMetricsMap();
00215 
00216     ((QwtPlot *)this)->plotLayout()->invalidate();
00217 
00218     // reset all widgets with their original attributes.
00219     if ( !(pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground) )
00220     {
00221         // restore the previous base line dists
00222 
00223         for (axisId = 0; axisId < QwtPlot::axisCnt; axisId++ )
00224         {
00225             QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(axisId);
00226             if ( scaleWidget  )
00227                 scaleWidget->setBaselineDist(baseLineDists[axisId]);
00228         }
00229     }
00230 
00231     pfilter.reset((QwtPlot *)this);
00232 
00233     painter->restore();
00234 }
00235 
00243 void QwtPlot::printTitle(QPainter *painter, const QRect &rect) const
00244 {
00245     painter->setFont(titleLabel()->font());
00246 
00247     const QColor color = 
00248 #if QT_VERSION < 0x040000
00249         titleLabel()->palette().color(
00250             QPalette::Active, QColorGroup::Text);
00251 #else
00252         titleLabel()->palette().color(
00253             QPalette::Active, QPalette::Text);
00254 #endif
00255 
00256     painter->setPen(color);
00257     titleLabel()->text().draw(painter, rect);
00258 }
00259 
00267 void QwtPlot::printLegend(QPainter *painter, const QRect &rect) const
00268 {
00269     if ( !legend() || legend()->isEmpty() )
00270         return;
00271 
00272     QLayout *l = legend()->contentsWidget()->layout();
00273     if ( l == 0 || !l->inherits("QwtDynGridLayout") )
00274         return;
00275 
00276     QwtDynGridLayout *legendLayout = (QwtDynGridLayout *)l;
00277 
00278     uint numCols = legendLayout->columnsForWidth(rect.width());
00279 #if QT_VERSION < 0x040000
00280     QValueList<QRect> itemRects = 
00281         legendLayout->layoutItems(rect, numCols);
00282 #else
00283     QList<QRect> itemRects = 
00284         legendLayout->layoutItems(rect, numCols);
00285 #endif
00286 
00287     int index = 0;
00288 
00289 #if QT_VERSION < 0x040000
00290     QLayoutIterator layoutIterator = legendLayout->iterator();
00291     for ( QLayoutItem *item = layoutIterator.current(); 
00292         item != 0; item = ++layoutIterator)
00293     {
00294 #else
00295     for ( int i = 0; i < legendLayout->count(); i++ )
00296     {
00297         QLayoutItem *item = legendLayout->itemAt(i);
00298 #endif
00299         QWidget *w = item->widget();
00300         if ( w )
00301         {
00302             painter->save();
00303             painter->setClipping(true);
00304             QwtPainter::setClipRect(painter, itemRects[index]);
00305 
00306             printLegendItem(painter, w, itemRects[index]);
00307 
00308             index++;
00309             painter->restore();
00310         }
00311     }
00312 }
00313 
00322 void QwtPlot::printLegendItem(QPainter *painter, 
00323     const QWidget *w, const QRect &rect) const
00324 {
00325     if ( w->inherits("QwtLegendItem") )
00326     {
00327         QwtLegendItem *item = (QwtLegendItem *)w;
00328 
00329         painter->setFont(item->font());
00330         item->drawItem(painter, rect);
00331     }
00332 }
00333 
00346 void QwtPlot::printScale(QPainter *painter,
00347     int axisId, int startDist, int endDist, int baseDist, 
00348     const QRect &rect) const
00349 {
00350     if (!axisEnabled(axisId))
00351         return;
00352 
00353     QwtScaleDraw::Alignment align;
00354     int x, y, w;
00355 
00356     switch(axisId)
00357     {
00358         case yLeft:
00359         {
00360             x = rect.right() - baseDist + 1;
00361             y = rect.y() + startDist;
00362             w = rect.height() - startDist - endDist;
00363             align = QwtScaleDraw::LeftScale;
00364             break;
00365         }
00366         case yRight:
00367         {
00368             x = rect.left() + baseDist;
00369             y = rect.y() + startDist;
00370             w = rect.height() - startDist - endDist;
00371             align = QwtScaleDraw::RightScale;
00372             break;
00373         }
00374         case xTop:
00375         {
00376             x = rect.left() + startDist;
00377             y = rect.bottom() - baseDist + 1;
00378             w = rect.width() - startDist - endDist;
00379             align = QwtScaleDraw::TopScale;
00380             break;
00381         }
00382         case xBottom:
00383         {
00384             x = rect.left() + startDist;
00385             y = rect.top() + baseDist;
00386             w = rect.width() - startDist - endDist;
00387             align = QwtScaleDraw::BottomScale;
00388             break;
00389         }
00390         default:
00391             return;
00392     }
00393 
00394     const QwtScaleWidget *scaleWidget = axisWidget(axisId);
00395     scaleWidget->drawTitle(painter, align, rect);
00396 
00397     painter->save();
00398     painter->setFont(scaleWidget->font());
00399 
00400     QwtScaleDraw *sd = (QwtScaleDraw *)scaleWidget->scaleDraw();
00401     const QPoint sdPos = sd->pos();
00402     const int sdLength = sd->length();
00403 
00404     sd->move(x, y);
00405     sd->setLength(w);
00406 
00407 #if QT_VERSION < 0x040000
00408     sd->draw(painter, scaleWidget->palette().active());
00409 #else
00410     QPalette palette = scaleWidget->palette();
00411     palette.setCurrentColorGroup(QPalette::Active);
00412     sd->draw(painter, palette);
00413 #endif
00414     // reset previous values
00415     sd->move(sdPos); 
00416     sd->setLength(sdLength); 
00417 
00418     painter->restore();
00419 }
00420 
00431 void QwtPlot::printCanvas(QPainter *painter, const QRect &canvasRect,
00432     const QwtArray<QwtScaleMap> &map, const QwtPlotPrintFilter &pfilter) const
00433 {
00434     if ( pfilter.options() & QwtPlotPrintFilter::PrintCanvasBackground )
00435     {
00436         painter->setPen(Qt::NoPen);
00437 
00438         QBrush bgBrush;
00439 #if QT_VERSION >= 0x040000
00440             bgBrush = canvas()->palette().brush(backgroundRole());
00441 #else
00442         QColorGroup::ColorRole role =
00443             QPalette::backgroundRoleFromMode( backgroundMode() ); 
00444         bgBrush = canvas()->colorGroup().brush( role );
00445 #endif
00446         painter->setBrush(bgBrush);
00447         
00448         int x1 = 0;
00449         int x2 = 0;
00450         int y1 = 0;
00451         int y2 = 0;
00452 
00453 #if QT_VERSION >= 0x040000
00454         switch(painter->device()->paintEngine()->type())
00455         {
00456             case QPaintEngine::PostScript:
00457                 x2 = 1;
00458                 y2 = 1;
00459                 break;
00460             default:;
00461         }
00462 #endif
00463 
00464         const QwtMetricsMap map = QwtPainter::metricsMap();
00465         x1 = map.screenToLayoutX(x1);
00466         x2 = map.screenToLayoutX(x2);
00467         y1 = map.screenToLayoutY(y1);
00468         y2 = map.screenToLayoutY(y2);
00469 
00470         QwtPainter::drawRect(painter, 
00471             canvasRect.x() + x1, canvasRect.y() + y1, 
00472             canvasRect.width() - x2, canvasRect.height() - y2); 
00473     }
00474     else
00475     {
00476         // Paint the canvas borders instead.
00477         painter->setPen(QPen(Qt::black));
00478         painter->setBrush(QBrush(Qt::NoBrush));
00479         QwtPainter::drawRect(painter, canvasRect); 
00480     }
00481 
00482 
00483     painter->setClipping(true);
00484     QwtPainter::setClipRect(painter, canvasRect);
00485 
00486     drawItems(painter, canvasRect, map, pfilter);
00487 }

Generated on Mon Jan 30 22:16:26 2006 for Qwt User's Guide by  doxygen 1.4.4