00001
00002
00003
00004
00005
00006
00007
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;
00576 else
00577 color -= colorDelta;
00578
00579 if ( color < 100 )
00580 color = 100;
00581
00582 if ( color > 255 )
00583 color = 255;
00584 }
00585 }
00586