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

qwt_painter.cpp

Go to the documentation of this file.
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 #include <qwindowdefs.h>
00011 #include <qrect.h>
00012 #include <qpainter.h>
00013 #include <qpaintdevice.h>
00014 #include <qpaintdevicemetrics.h>
00015 #include "qwt_painter.h"
00016 #include "qwt_math.h"
00017 
00018 #if defined(Q_WS_X11)
00019 bool QwtPainter::d_deviceClipping = TRUE;
00020 #else
00021 bool QwtPainter::d_deviceClipping = FALSE;
00022 #endif
00023 
00024 double QwtPainter::d_scaleMetricsX = 1.0;
00025 double QwtPainter::d_scaleMetricsY = 1.0;
00026 
00032 void QwtPainter::setDeviceClipping(bool enable)
00033 {
00034     d_deviceClipping = enable;
00035 }
00036 
00043 bool QwtPainter::deviceClipping()
00044 {
00045     return d_deviceClipping;
00046 }
00047 
00052 const QRect &QwtPainter::deviceClipRect()
00053 {
00054     static QRect clip;
00055 
00056     if ( !clip.isValid() )
00057     {
00058         clip.setCoords(QWT_COORD_MIN, QWT_COORD_MIN,
00059             QWT_COORD_MAX, QWT_COORD_MAX);
00060     }
00061     return clip;
00062 }
00063 
00072 void QwtPainter::setScaleMetrics(const QPaintDevice *from, 
00073     const QPaintDevice *to)
00074 {
00075     if ( from == 0 || to == 0 )
00076     {
00077         resetScaleMetrics();
00078         return;
00079     }
00080     QPaintDeviceMetrics m1(from);
00081     QPaintDeviceMetrics m2(to);
00082 
00083     d_scaleMetricsX = double(m2.logicalDpiX()) / double(m1.logicalDpiX());
00084     d_scaleMetricsY = double(m2.logicalDpiY()) / double(m1.logicalDpiY());
00085 }
00086 
00091 void QwtPainter::resetScaleMetrics()
00092 {
00093     d_scaleMetricsX = d_scaleMetricsY = 1.0;
00094 }
00095 
00100 double QwtPainter::scaleMetricsX()
00101 {
00102     return d_scaleMetricsX;
00103 }
00104 
00109 double QwtPainter::scaleMetricsY()
00110 {
00111     return d_scaleMetricsY;
00112 }
00113 
00118 QRect QwtPainter::map(const QWMatrix &m, const QRect &rect)
00119 {
00120 #if QT_VERSION < 300
00121     return m.map(rect.normalize());
00122 #else
00123     return m.mapRect(rect);
00124 #endif
00125 }
00126 
00132 QPointArray QwtPainter::map(const QWMatrix &m, const QPointArray &pa)
00133 {
00134 #if QT_VERSION < 300
00135     return m.map(pa);
00136 #else
00137     return m * pa;
00138 #endif
00139 }
00140 
00148 QRect QwtPainter::scale(const QRect &rect, const QPainter *painter)
00149 {
00150     if ( d_scaleMetricsX == 1.0 && d_scaleMetricsY == 1.0 )
00151         return rect;
00152     
00153     QRect scaledRect(rect);
00154     if ( painter )
00155     {
00156         scaledRect = QwtPainter::map(
00157             painter->worldMatrix(), scaledRect);
00158     }
00159 
00160     scaledRect = QRect(
00161         qwtInt(scaledRect.x() * d_scaleMetricsX),
00162         qwtInt(scaledRect.y() * d_scaleMetricsY),
00163         qwtInt(scaledRect.width() * d_scaleMetricsX),
00164         qwtInt(scaledRect.height() * d_scaleMetricsY)
00165     );
00166 
00167     if ( painter )
00168     {
00169         scaledRect = QwtPainter::map(
00170             painter->worldMatrix().invert(), scaledRect);
00171     }
00172 
00173     return scaledRect;
00174 }
00175 
00184 QPoint QwtPainter::scale(const QPoint &pos, const QPainter *painter)
00185 {
00186     if ( d_scaleMetricsX == 1.0 && d_scaleMetricsY == 1.0 )
00187         return pos;
00188 
00189     QPoint scaledPos(pos);
00190 
00191     if ( painter )
00192         scaledPos = painter->worldMatrix().map(scaledPos);
00193 
00194     scaledPos = QPoint(qwtInt(scaledPos.x() * d_scaleMetricsX), 
00195         qwtInt(scaledPos.y() * d_scaleMetricsY));
00196 
00197     if ( painter )
00198         scaledPos = painter->worldMatrix().invert().map(scaledPos);
00199 
00200     return scaledPos;
00201 }
00202 
00211 QPointArray QwtPainter::scale(const QPointArray &pa, 
00212     const QPainter *painter)
00213 {
00214     if ( d_scaleMetricsX == 1.0 && d_scaleMetricsY == 1.0 )
00215         return pa;
00216 
00217     QPointArray scaledPa(pa);
00218 
00219     if ( painter )
00220         scaledPa = QwtPainter::map(painter->worldMatrix(), scaledPa);
00221 
00222     QWMatrix m;
00223     m.scale(d_scaleMetricsX, d_scaleMetricsY);
00224     scaledPa = QwtPainter::map(m, scaledPa);
00225 
00226     if ( painter )
00227     {
00228         scaledPa = QwtPainter::map(
00229             painter->worldMatrix().invert(), scaledPa);
00230     }
00231 
00232     return scaledPa;
00233 }
00234 
00242 QRect QwtPainter::invScale(const QRect &rect, const QPainter *painter)
00243 {
00244     if ( d_scaleMetricsX == 1.0 && d_scaleMetricsY == 1.0 )
00245         return rect;
00246     
00247     QRect scaledRect(rect);
00248     if ( painter )
00249     {
00250         scaledRect = QwtPainter::map(
00251             painter->worldMatrix(), scaledRect);
00252     }
00253 
00254     scaledRect = QRect(
00255         qwtInt(scaledRect.x() / d_scaleMetricsX),
00256         qwtInt(scaledRect.y() / d_scaleMetricsY),
00257         qwtInt(scaledRect.width() / d_scaleMetricsX),
00258         qwtInt(scaledRect.height() / d_scaleMetricsY)
00259     );
00260 
00261     if ( painter )
00262     {
00263         scaledRect = QwtPainter::map(
00264             painter->worldMatrix().invert(), scaledRect);
00265     }
00266 
00267     return scaledRect;
00268 }
00269 
00277 QPoint QwtPainter::invScale(const QPoint &pos, const QPainter *painter)
00278 {
00279     if ( d_scaleMetricsX == 1.0 && d_scaleMetricsY == 1.0 )
00280         return pos;
00281 
00282     QPoint scaledPos(pos);
00283 
00284     if ( painter )
00285         scaledPos = painter->worldMatrix().map(scaledPos);
00286 
00287     scaledPos = QPoint(qwtInt(scaledPos.x() / d_scaleMetricsX), 
00288         qwtInt(scaledPos.y() / d_scaleMetricsY));
00289 
00290     if ( painter )
00291         scaledPos = painter->worldMatrix().invert().map(scaledPos);
00292 
00293     return scaledPos;
00294 }
00295 
00299 void QwtPainter::setClipRect(QPainter *painter, const QRect &rect)
00300 {
00301     painter->setClipRect(scale(rect, painter));
00302 }
00303 
00307 void QwtPainter::drawRect(QPainter *painter, int x, int y, int w, int h) 
00308 {
00309     QwtPainter::drawRect(painter, QRect(x, y, w, h));
00310 }
00311 
00315 void QwtPainter::drawRect(QPainter *painter, const QRect &rect) 
00316 {
00317     painter->drawRect(scale(rect, painter));
00318 }
00319 
00323 void QwtPainter::fillRect(QPainter *painter, 
00324     const QRect &rect, const QBrush &brush)
00325 {
00326     painter->fillRect(scale(rect, painter), brush);
00327 }
00328 
00332 void QwtPainter::drawEllipse(QPainter *painter, const QRect &rect)
00333 {
00334     painter->drawEllipse(scale(rect, painter));
00335 }
00336 
00340 void QwtPainter::drawText(QPainter *painter, int x, int y, 
00341         const QString &text, int len)
00342 {
00343     drawText(painter, QPoint(x, y), text, len);
00344 }
00345 
00349 void QwtPainter::drawText(QPainter *painter, const QPoint &pos, 
00350         const QString &text, int len)
00351 {
00352     painter->drawText(scale(pos, painter), text, len);
00353 }
00354 
00358 void QwtPainter::drawText(QPainter *painter, int x, int y, int w, int h, 
00359         int flags, const QString &text, int len)
00360 {
00361     drawText(painter, QRect(x, y, w, h), flags, text, len);
00362 }
00363 
00367 void QwtPainter::drawText(QPainter *painter, const QRect &rect, 
00368         int flags, const QString &text, int len)
00369 {
00370     painter->drawText(scale(rect, painter), 
00371         flags, text, len);
00372 }
00373 
00377 void QwtPainter::drawLine(QPainter *painter, 
00378     const QPoint &p1, const QPoint &p2) 
00379 {
00380     if ( d_deviceClipping && 
00381         !(deviceClipRect().contains(p1) && deviceClipRect().contains(p2)) )
00382     {
00383         QPointArray pa(2);
00384         pa.setPoint(0, p1);
00385         pa.setPoint(1, p2);
00386         drawPolyline(painter, pa);
00387     }
00388     else
00389     {
00390         painter->drawLine(scale(p1), scale(p2));
00391     }
00392 }
00393 
00398 void QwtPainter::drawLine(QPainter *painter, int x1, int y1, int x2, int y2)
00399 {
00400     drawLine(painter, QPoint(x1, y1), QPoint(x2, y2));
00401 }
00402 
00407 void QwtPainter::drawPolygon(QPainter *painter, const QPointArray &pa)
00408 {
00409     QPointArray cpa = scale(pa);
00410     if ( d_deviceClipping )
00411         cpa = clip(cpa);
00412     painter->drawPolygon(cpa);
00413 }
00414 
00418 void QwtPainter::drawPolyline(QPainter *painter, const QPointArray &pa)
00419 {
00420     QPointArray cpa = scale(pa);
00421     if ( d_deviceClipping )
00422         cpa = clip(cpa);
00423     painter->drawPolyline(cpa);
00424 }
00425 
00430 void QwtPainter::drawPoint(QPainter *painter, int x, int y)
00431 {
00432     if ( d_deviceClipping && !deviceClipRect().contains(x, y) )
00433         return;
00434 
00435     painter->drawPoint(scale(QPoint(x,y)));
00436 }
00437 
00438 QPointArray QwtPainter::clip(const QPointArray &pa)
00439 {
00440     int idx = 0;
00441     int size = pa.size();
00442     
00443     return clipPolyline(deviceClipRect(), pa, idx, size);
00444 }
00445 
00446 bool QwtPainter::insideEdge( const QPoint &p, const QRect &r, int edge )
00447 {
00448     switch ( edge ) 
00449     {
00450         case 0:
00451             return p.x() > r.left();
00452         case 1:
00453             return p.y() > r.top();
00454         case 2:
00455             return p.x() < r.right();
00456         case 3:
00457             return p.y() < r.bottom();
00458     }
00459 
00460     return FALSE;
00461 }
00462 
00463 QPoint QwtPainter::intersectEdge(const QPoint &p1, const QPoint &p2,
00464     const QRect &r, int edge )
00465 {
00466     int x=0, y=0;
00467     double m = 0;
00468     double dy = p2.y() - p1.y();
00469     double dx = p2.x() - p1.x();
00470 
00471     switch ( edge ) 
00472     {
00473         case 0:
00474             x = r.left();
00475             m = double(QABS(p1.x() - x)) / QABS(dx);
00476             y = p1.y() + int(dy * m);
00477             break;
00478         case 1:
00479             y = r.top();
00480             m = double(QABS(p1.y() - y)) / QABS(dy);
00481             x = p1.x() + int(dx * m);
00482             break;
00483         case 2:
00484             x = r.right();
00485             m = double(QABS(p1.x() - x)) / QABS(dx);
00486             y = p1.y() + int(dy * m);
00487             break;
00488         case 3:
00489             y = r.bottom();
00490             m = double(QABS(p1.y() - y)) / QABS(dy);
00491             x = p1.x() + int(dx * m);
00492             break;
00493     }
00494 
00495     return QPoint(x,y);
00496 }
00497 
00502 QPointArray QwtPainter::clipPolyline(const QRect &r,
00503     const QPointArray &pa, int &index, int &npoints )
00504 {
00505     if ( r.contains( pa.boundingRect() ) )
00506         return pa;
00507 
00508     QPointArray rpa = pa;
00509     QPointArray cpa( pa.size() );
00510     unsigned int count = 0;
00511 
00512 #define ADD_POINT(p) if ( cpa.size() == count ) cpa.resize( count+5 ); \
00513              cpa.setPoint( count++, p );
00514 
00515     for ( int e = 0; e < 4; e++ ) 
00516     {
00517         count = 0;
00518         QPoint s = rpa.point( index );
00519         for ( int j = 0; j < npoints; j++ ) 
00520         {
00521             QPoint p = rpa.point( index+j );
00522             if ( insideEdge( p, r, e ) ) 
00523             {
00524                 if ( insideEdge( s, r, e ) ) 
00525                 {
00526                     ADD_POINT(p);
00527                 } 
00528                 else 
00529                 {
00530                     QPoint i = intersectEdge( s, p, r, e );
00531                     ADD_POINT(i);
00532                     ADD_POINT(p);
00533                 }
00534             } 
00535             else 
00536             {
00537                 if ( insideEdge( s, r, e ) ) 
00538                 {
00539                     QPoint i = intersectEdge( s, p, r, e );
00540                     ADD_POINT(i);
00541                 }
00542             }
00543             s = p;
00544         }
00545         index = 0;
00546         npoints = count;
00547         rpa = cpa.copy();
00548     }
00549 
00550 #undef ADD_POINT
00551 
00552     cpa.resize( npoints );
00553 
00554     return cpa;
00555 }
00556 
00557 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00558     int width, bool sunken)
00559 {
00560     const int colorDelta = 5;
00561     const int offset = 4;
00562 
00563     int color = 255;
00564     for ( int angle = 0; angle < 360; angle += offset )
00565     {
00566         int c = color;
00567         if ( !sunken )
00568             c = 100 + 255 - c;
00569 
00570         QPen pen(QColor(c, c, c), width);
00571         painter->setPen(pen);
00572         painter->drawArc(rect, angle * 16, offset * 16);
00573 
00574         if ( ( angle > 145 ) && ( angle < 360 ) ) 
00575             color += colorDelta;         // brighter
00576         else 
00577             color -= colorDelta;         // darker
00578 
00579         if ( color < 100 )
00580             color = 100;
00581 
00582         if ( color > 255 )
00583             color = 255;
00584     }
00585 }
00586 

Generated on Fri Nov 7 14:11:45 2003 for Qwt Developer's Guide by doxygen 1.3.2