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 Tue Nov 16 21:12:21 2004 for Qwt User's Guide by doxygen 1.3.8