00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qwindowdefs.h>
00013 #include <qwidget.h>
00014 #include <qrect.h>
00015 #include <qpainter.h>
00016 #include <qpalette.h>
00017 #include <qpaintdevice.h>
00018 #include <qpixmap.h>
00019 #include <qstyle.h>
00020 #if QT_VERSION < 0x040000
00021 #include <qsimplerichtext.h>
00022 #else
00023 #include <qtextdocument.h>
00024 #include <qabstracttextdocumentlayout.h>
00025 #include <qstyleoption.h>
00026 #endif
00027
00028 #include "qwt_rect.h"
00029 #include "qwt_math.h"
00030 #include "qwt_color_map.h"
00031 #include "qwt_scale_map.h"
00032 #include "qwt_painter.h"
00033
00034 QwtMetricsMap QwtPainter::d_metricsMap;
00035
00036 #if defined(Q_WS_X11)
00037 bool QwtPainter::d_deviceClipping = true;
00038 #else
00039 bool QwtPainter::d_deviceClipping = false;
00040 #endif
00041
00042 #if QT_VERSION < 0x040000
00043 bool QwtPainter::d_SVGMode = false;
00044 #endif
00045
00046 static inline bool needDeviceClipping(
00047 const QPainter *painter, bool deviceClipping)
00048 {
00049 return deviceClipping &&
00050 (painter->device()->devType() == QInternal::Widget ||
00051 painter->device()->devType() == QInternal::Pixmap );
00052 }
00053
00061 void QwtPainter::setDeviceClipping(bool enable)
00062 {
00063 d_deviceClipping = enable;
00064 }
00065
00072 bool QwtPainter::deviceClipping()
00073 {
00074 return d_deviceClipping;
00075 }
00076
00081 const QRect &QwtPainter::deviceClipRect()
00082 {
00083 static QRect clip;
00084
00085 if ( !clip.isValid() )
00086 {
00087 clip.setCoords(QWT_COORD_MIN, QWT_COORD_MIN,
00088 QWT_COORD_MAX, QWT_COORD_MAX);
00089 }
00090 return clip;
00091 }
00092
00094 QwtPolygon QwtPainter::clip(const QwtPolygon &pa)
00095 {
00096 const QwtRect rect(deviceClipRect());
00097 return rect.clip(pa);
00098 }
00099
00100 #if QT_VERSION < 0x040000
00101
00113 void QwtPainter::setSVGMode(bool on)
00114 {
00115 d_SVGMode = on;
00116 }
00117
00118 bool QwtPainter::isSVGMode()
00119 {
00120 return d_SVGMode;
00121 }
00122
00123 #endif // QT_VERSION < 0x040000
00124
00133 void QwtPainter::setMetricsMap(const QPaintDevice *layout,
00134 const QPaintDevice *device)
00135 {
00136 d_metricsMap.setMetrics(layout, device);
00137 }
00138
00143 void QwtPainter::setMetricsMap(const QwtMetricsMap &map)
00144 {
00145 d_metricsMap = map;
00146 }
00147
00152 void QwtPainter::resetMetricsMap()
00153 {
00154 d_metricsMap = QwtMetricsMap();
00155 }
00156
00160 const QwtMetricsMap &QwtPainter::metricsMap()
00161 {
00162 return d_metricsMap;
00163 }
00164
00168 void QwtPainter::setClipRect(QPainter *painter, const QRect &rect)
00169 {
00170 painter->setClipRect(d_metricsMap.layoutToDevice(rect, painter));
00171 }
00172
00176 void QwtPainter::drawRect(QPainter *painter, int x, int y, int w, int h)
00177 {
00178 drawRect(painter, QRect(x, y, w, h));
00179 }
00180
00184 void QwtPainter::drawRect(QPainter *painter, const QRect &rect)
00185 {
00186 QRect r = d_metricsMap.layoutToDevice(rect, painter);
00187
00188 QRect clipRect;
00189
00190 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00191 if ( deviceClipping )
00192 clipRect = deviceClipRect();
00193
00194 if ( clipRect.isValid() )
00195 {
00196 if ( !clipRect.intersects(r) )
00197 return;
00198
00199 if ( !clipRect.contains(r) )
00200 {
00201 fillRect(painter, r & clipRect, painter->brush());
00202
00203 int pw = painter->pen().width();
00204 pw = pw % 2 + pw / 2;
00205
00206 QwtPolygon pa(5);
00207 pa.setPoint(0, r.left(), r.top());
00208 pa.setPoint(1, r.right() - pw, r.top());
00209 pa.setPoint(2, r.right() - pw, r.bottom() - pw);
00210 pa.setPoint(3, r.left(), r.bottom() - pw);
00211 pa.setPoint(4, r.left(), r.top());
00212
00213 painter->save();
00214 painter->setBrush(Qt::NoBrush);
00215 drawPolyline(painter, pa);
00216 painter->restore();
00217
00218 return;
00219 }
00220 }
00221
00222 #if QT_VERSION >= 0x040000
00223 if ( painter->pen().style() != Qt::NoPen &&
00224 painter->pen().color().isValid() )
00225 {
00226
00227 int pw = painter->pen().width();
00228 if ( pw == 0 )
00229 pw = 1;
00230
00231 r.setWidth(r.width() - pw);
00232 r.setHeight(r.height() - pw);
00233 }
00234 #endif
00235 painter->drawRect(r);
00236 }
00237
00241 void QwtPainter::fillRect(QPainter *painter,
00242 const QRect &rect, const QBrush &brush)
00243 {
00244 if ( !rect.isValid() )
00245 return;
00246
00247 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00248
00249 QRect clipRect;
00250 #if QT_VERSION >= 0x040000
00251
00252
00253
00254
00255
00256
00257
00258 clipRect = painter->window();
00259 if ( painter->hasClipping() )
00260 clipRect &= painter->clipRegion().boundingRect();
00261 if ( deviceClipping )
00262 clipRect &= deviceClipRect();
00263 #else
00264 if ( deviceClipping )
00265 clipRect = deviceClipRect();
00266 #endif
00267
00268 QRect r = d_metricsMap.layoutToDevice(rect, painter);
00269 if ( clipRect.isValid() )
00270 r = r.intersect(clipRect);
00271
00272 if ( r.isValid() )
00273 painter->fillRect(r, brush);
00274 }
00275
00279 void QwtPainter::drawPie(QPainter *painter, const QRect &rect,
00280 int a, int alen)
00281 {
00282 QRect r = d_metricsMap.layoutToDevice(rect, painter);
00283
00284 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00285 if ( deviceClipping && !deviceClipRect().contains(rect) )
00286 return;
00287
00288 painter->drawPie(r, a, alen);
00289 }
00290
00294 void QwtPainter::drawEllipse(QPainter *painter, const QRect &rect)
00295 {
00296 QRect r = d_metricsMap.layoutToDevice(rect, painter);
00297
00298 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00299
00300 if ( deviceClipping && !deviceClipRect().contains(rect) )
00301 return;
00302
00303 #if QT_VERSION >= 0x040000
00304 if ( painter->pen().style() != Qt::NoPen &&
00305 painter->pen().color().isValid() )
00306 {
00307
00308 int pw = painter->pen().width();
00309 if ( pw == 0 )
00310 pw = 1;
00311
00312 r.setWidth(r.width() - pw);
00313 r.setHeight(r.height() - pw);
00314 }
00315 #endif
00316
00317 painter->drawEllipse(r);
00318 }
00319
00323 void QwtPainter::drawText(QPainter *painter, int x, int y,
00324 const QString &text)
00325 {
00326 drawText(painter, QPoint(x, y), text);
00327 }
00328
00332 void QwtPainter::drawText(QPainter *painter, const QPoint &pos,
00333 const QString &text)
00334 {
00335 const QPoint p = d_metricsMap.layoutToDevice(pos, painter);
00336
00337 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00338
00339 if ( deviceClipping && !deviceClipRect().contains(p) )
00340 return;
00341
00342 painter->drawText(p, text);
00343 }
00344
00348 void QwtPainter::drawText(QPainter *painter, int x, int y, int w, int h,
00349 int flags, const QString &text)
00350 {
00351 drawText(painter, QRect(x, y, w, h), flags, text);
00352 }
00353
00357 void QwtPainter::drawText(QPainter *painter, const QRect &rect,
00358 int flags, const QString &text)
00359 {
00360 QRect textRect = d_metricsMap.layoutToDevice(rect, painter);
00361 #if QT_VERSION < 0x040000
00362 if ( d_SVGMode &&
00363 ( flags == 0 || flags & Qt::AlignVCenter )
00364 && painter->device()->devType() & QInternal::Picture )
00365 {
00366
00367
00368
00369
00370 textRect.setY(textRect.y() - painter->fontMetrics().height() / 4);
00371 }
00372 #endif
00373 painter->drawText(textRect, flags, text);
00374 }
00375
00376 #ifndef QT_NO_RICHTEXT
00377
00381 #if QT_VERSION < 0x040000
00382
00383 void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect,
00384 int flags, QSimpleRichText &text)
00385 {
00386 QColorGroup cg;
00387 cg.setColor(QColorGroup::Text, painter->pen().color());
00388
00389 const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter);
00390
00391 text.setWidth(painter, scaledRect.width());
00392
00393
00394
00395 int y = scaledRect.y();
00396 if (flags & Qt::AlignBottom)
00397 y += (scaledRect.height() - text.height());
00398 else if (flags & Qt::AlignVCenter)
00399 y += (scaledRect.height() - text.height())/2;
00400
00401 text.draw(painter, scaledRect.x(), y, scaledRect, cg);
00402 }
00403 #else
00404 void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect,
00405 int flags, QTextDocument &text)
00406 {
00407 const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter);
00408 text.setPageSize(QSize(scaledRect.width(), QWIDGETSIZE_MAX));
00409
00410 QAbstractTextDocumentLayout* layout = text.documentLayout();
00411
00412 const int height = qRound(layout->documentSize().height());
00413 int y = scaledRect.y();
00414 if (flags & Qt::AlignBottom)
00415 y += (scaledRect.height() - height);
00416 else if (flags & Qt::AlignVCenter)
00417 y += (scaledRect.height() - height)/2;
00418
00419 QAbstractTextDocumentLayout::PaintContext context;
00420 context.palette.setColor(QPalette::Text, painter->pen().color());
00421
00422 painter->save();
00423
00424 painter->translate(scaledRect.x(), scaledRect.y());
00425 layout->draw(painter, context);
00426
00427 painter->restore();
00428 }
00429 #endif
00430
00431 #endif // !QT_NO_RICHTEXT
00432
00433
00437 void QwtPainter::drawLine(QPainter *painter, int x1, int y1, int x2, int y2)
00438 {
00439 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00440
00441 if ( deviceClipping &&
00442 !(deviceClipRect().contains(x1, y1) && deviceClipRect().contains(x2, y2)) )
00443 {
00444 QwtPolygon pa(2);
00445 pa.setPoint(0, x1, y1);
00446 pa.setPoint(1, x2, y2);
00447 drawPolyline(painter, pa);
00448 return;
00449 }
00450
00451 if ( d_metricsMap.isIdentity() )
00452 {
00453 #if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000
00454 if ( !painter->device()->isExtDev() )
00455 #endif
00456 {
00457 painter->drawLine(x1, y1, x2, y2);
00458 return;
00459 }
00460 }
00461
00462 const QPoint p1 = d_metricsMap.layoutToDevice(QPoint(x1, y1));
00463 const QPoint p2 = d_metricsMap.layoutToDevice(QPoint(x2, y2));
00464
00465 #if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000
00466 if ( painter->device()->isExtDev() )
00467 {
00468
00469
00470
00471
00472 QwtPolygon pa(2);
00473 pa.setPoint(0, p1);
00474 pa.setPoint(1, p2);
00475 painter->drawLineSegments(pa);
00476 }
00477 else
00478 painter->drawLine(p1, p2);
00479 #else
00480 painter->drawLine(p1, p2);
00481 #endif
00482 }
00483
00487 void QwtPainter::drawPolygon(QPainter *painter, const QwtPolygon &pa)
00488 {
00489 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00490
00491 QwtPolygon cpa = d_metricsMap.layoutToDevice(pa);
00492 if ( deviceClipping )
00493 {
00494 #ifdef __GNUC__
00495 #endif
00496 cpa = clip(cpa);
00497 }
00498 painter->drawPolygon(cpa);
00499 }
00500
00504 void QwtPainter::drawPolyline(QPainter *painter, const QwtPolygon &pa)
00505 {
00506 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00507
00508 QwtPolygon cpa = d_metricsMap.layoutToDevice(pa);
00509 if ( deviceClipping )
00510 cpa = clip(cpa);
00511 painter->drawPolyline(cpa);
00512 }
00513
00518 void QwtPainter::drawPoint(QPainter *painter, int x, int y)
00519 {
00520 const bool deviceClipping = needDeviceClipping(painter, d_deviceClipping);
00521
00522 const QPoint pos = d_metricsMap.layoutToDevice(QPoint(x, y));
00523
00524 if ( deviceClipping && !deviceClipRect().contains(pos) )
00525 return;
00526
00527 painter->drawPoint(pos);
00528 }
00529
00530 void QwtPainter::drawColoredArc(QPainter *painter, const QRect &rect,
00531 int peak, int arc, int interval, const QColor &c1, const QColor &c2)
00532 {
00533 int h1, s1, v1;
00534 int h2, s2, v2;
00535
00536 #if QT_VERSION < 0x040000
00537 c1.hsv(&h1, &s1, &v1);
00538 c2.hsv(&h2, &s2, &v2);
00539 #else
00540 c1.getHsv(&h1, &s1, &v1);
00541 c2.getHsv(&h2, &s2, &v2);
00542 #endif
00543
00544 arc /= 2;
00545 for ( int angle = -arc; angle < arc; angle += interval)
00546 {
00547 double ratio;
00548 if ( angle >= 0 )
00549 ratio = 1.0 - angle / double(arc);
00550 else
00551 ratio = 1.0 + angle / double(arc);
00552
00553
00554 QColor c;
00555 c.setHsv( h1 + qRound(ratio * (h2 - h1)),
00556 s1 + qRound(ratio * (s2 - s1)),
00557 v1 + qRound(ratio * (v2 - v1)) );
00558
00559 painter->setPen(QPen(c, painter->pen().width()));
00560 painter->drawArc(rect, (peak + angle) * 16, interval * 16);
00561 }
00562 }
00563
00564 void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget)
00565 {
00566 drawFocusRect(painter, widget, widget->rect());
00567 }
00568
00569 void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget,
00570 const QRect &rect)
00571 {
00572 #if QT_VERSION < 0x040000
00573 widget->style().drawPrimitive(QStyle::PE_FocusRect, painter,
00574 rect, widget->colorGroup());
00575 #else
00576 QStyleOptionFocusRect opt;
00577 opt.init(widget);
00578 opt.rect = rect;
00579 opt.state |= QStyle::State_HasFocus;
00580
00581 widget->style()->drawPrimitive(QStyle::PE_FrameFocusRect,
00582 &opt, painter, widget);
00583 #endif
00584
00585 }
00586
00588 #if QT_VERSION < 0x040000
00589 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00590 int width, const QColorGroup &cg, bool sunken)
00591 #else
00592 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00593 int width, const QPalette &palette, bool sunken)
00594 #endif
00595 {
00596
00597 #if QT_VERSION < 0x040000
00598 QColor c0 = cg.mid();
00599 QColor c1, c2;
00600 if ( sunken )
00601 {
00602 c1 = cg.dark();
00603 c2 = cg.light();
00604 }
00605 else
00606 {
00607 c1 = cg.light();
00608 c2 = cg.dark();
00609 }
00610 #else
00611 QColor c0 = palette.color(QPalette::Mid);
00612 QColor c1, c2;
00613 if ( sunken )
00614 {
00615 c1 = palette.color(QPalette::Dark);
00616 c2 = palette.color(QPalette::Light);
00617 }
00618 else
00619 {
00620 c1 = palette.color(QPalette::Light);
00621 c2 = palette.color(QPalette::Dark);
00622 }
00623 #endif
00624
00625 painter->setPen(QPen(c0, width));
00626 painter->drawArc(rect, 0, 360 * 16);
00627
00628 const int peak = 150;
00629 const int interval = 2;
00630
00631 if ( c0 != c1 )
00632 drawColoredArc(painter, rect, peak, 160, interval, c0, c1);
00633 if ( c0 != c2 )
00634 drawColoredArc(painter, rect, peak + 180, 120, interval, c0, c2);
00635 }
00636
00637 void QwtPainter::drawColorBar(QPainter *painter,
00638 const QwtColorMap &colorMap, const QwtDoubleInterval &interval,
00639 const QwtScaleMap &scaleMap, Qt::Orientation orientation,
00640 const QRect &rect)
00641 {
00642 painter->save();
00643
00644 QwtPainter::setClipRect(painter, rect);
00645
00646 #if QT_VERSION < 0x040000
00647 QValueVector<QRgb> colorTable;
00648 #else
00649 QVector<QRgb> colorTable;
00650 #endif
00651 if ( colorMap.format() == QwtColorMap::Indexed )
00652 colorTable = colorMap.colorTable(interval);
00653
00654 QColor c;
00655
00656 const QRect devRect = d_metricsMap.layoutToDevice(rect);
00657
00658 if ( orientation == Qt::Horizontal )
00659 {
00660 QwtScaleMap sMap = scaleMap;
00661 sMap.setPaintInterval(devRect.left(), devRect.right());
00662
00663 for ( int x = devRect.left(); x <= devRect.right(); x++ )
00664 {
00665 const double value = sMap.invTransform(x);
00666
00667 if ( colorMap.format() == QwtColorMap::RGB )
00668 c.setRgb(colorMap.rgb(interval, value));
00669 else
00670 c = colorTable[colorMap.colorIndex(interval, value)];
00671
00672 painter->setBrush(QBrush(c));
00673
00674 const QRect r(x, devRect.top(), 1, devRect.height());
00675 QwtPainter::drawRect(painter, r);
00676 painter->setPen(c);
00677 painter->drawLine(x, devRect.top(), x, devRect.bottom() - 1);
00678 }
00679 }
00680 else
00681 {
00682 QwtScaleMap sMap = scaleMap;
00683 sMap.setPaintInterval(devRect.bottom(), devRect.top());
00684
00685 for ( int y = devRect.top(); y <= devRect.bottom(); y++ )
00686 {
00687 const double value = sMap.invTransform(y);
00688
00689 if ( colorMap.format() == QwtColorMap::RGB )
00690 c.setRgb(colorMap.rgb(interval, value));
00691 else
00692 c = colorTable[colorMap.colorIndex(interval, value)];
00693
00694 painter->setPen(c);
00695 painter->drawLine(devRect.left(), y, devRect.right() - 1, y);
00696 }
00697 }
00698 painter->restore();
00699 }