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 #include <qpointarray.h>
00023 #define QwtPointArray QPointArray
00024 #else
00025 #include <qtextdocument.h>
00026 #include <qabstracttextdocumentlayout.h>
00027 #include <qstyleoption.h>
00028 #include <qpolygon.h>
00029 #define QwtPointArray QPolygon
00030 #endif
00031
00032 #include "qwt_painter.h"
00033 #include "qwt_rect.h"
00034 #include "qwt_math.h"
00035
00036 QwtMetricsMap QwtPainter::d_metricsMap;
00037
00038 #if defined(Q_WS_X11)
00039 bool QwtPainter::d_deviceClipping = true;
00040 #else
00041 bool QwtPainter::d_deviceClipping = false;
00042 #endif
00043
00049 void QwtPainter::setDeviceClipping(bool enable)
00050 {
00051 d_deviceClipping = enable;
00052 }
00053
00060 bool QwtPainter::deviceClipping()
00061 {
00062 return d_deviceClipping;
00063 }
00064
00069 const QRect &QwtPainter::deviceClipRect()
00070 {
00071 static QRect clip;
00072
00073 if ( !clip.isValid() )
00074 {
00075 clip.setCoords(QWT_COORD_MIN, QWT_COORD_MIN,
00076 QWT_COORD_MAX, QWT_COORD_MAX);
00077 }
00078 return clip;
00079 }
00080
00082 QwtPointArray QwtPainter::clip(const QwtPointArray &pa)
00083 {
00084 const QwtRect rect(deviceClipRect());
00085 return rect.clip(pa);
00086 }
00087
00096 void QwtPainter::setMetricsMap(const QPaintDevice *layout,
00097 const QPaintDevice *device)
00098 {
00099 d_metricsMap.setMetrics(layout, device);
00100 }
00101
00106 void QwtPainter::setMetricsMap(const QwtMetricsMap &map)
00107 {
00108 d_metricsMap = map;
00109 }
00110
00115 void QwtPainter::resetMetricsMap()
00116 {
00117 d_metricsMap = QwtMetricsMap();
00118 }
00119
00123 const QwtMetricsMap &QwtPainter::metricsMap()
00124 {
00125 return d_metricsMap;
00126 }
00127
00131 void QwtPainter::setClipRect(QPainter *painter, const QRect &rect)
00132 {
00133 painter->setClipRect(d_metricsMap.layoutToDevice(rect, painter));
00134 }
00135
00139 void QwtPainter::drawRect(QPainter *painter, int x, int y, int w, int h)
00140 {
00141 drawRect(painter, QRect(x, y, w, h));
00142 }
00143
00147 void QwtPainter::drawRect(QPainter *painter, const QRect &rect)
00148 {
00149 const QRect r = d_metricsMap.layoutToDevice(rect, painter);
00150
00151 QRect clipRect;
00152
00153 #if QT_VERSION == 0x040000
00154
00155
00156
00157
00158
00159 clipRect = painter->window();
00160 if ( painter->hasClipping() )
00161 clipRect &= painter->clipRegion().boundingRect();
00162 if ( d_deviceClipping )
00163 clipRect &= deviceClipRect();
00164 #else
00165 if ( d_deviceClipping )
00166 clipRect = deviceClipRect();
00167 #endif
00168 if ( clipRect.isValid() )
00169 {
00170 if ( !clipRect.intersects(r) )
00171 return;
00172
00173 if ( !clipRect.contains(r) )
00174 {
00175 fillRect(painter, r & clipRect, painter->brush());
00176
00177 #ifdef __GNUC__
00178 #warning alignment of rects needs to be checked
00179 #endif
00180 int pw = painter->pen().width();
00181 pw = pw % 2 + pw / 2;
00182
00183 QwtPointArray pa(5);
00184 pa.setPoint(0, r.left(), r.top());
00185 pa.setPoint(1, r.right() - pw, r.top());
00186 pa.setPoint(2, r.right() - pw, r.bottom() - pw);
00187 pa.setPoint(3, r.left(), r.bottom() - pw);
00188 pa.setPoint(4, r.left(), r.top());
00189
00190 painter->save();
00191 painter->setBrush(Qt::NoBrush);
00192 drawPolyline(painter, pa);
00193 painter->restore();
00194
00195 return;
00196 }
00197 }
00198
00199 painter->drawRect(r);
00200 }
00201
00205 void QwtPainter::fillRect(QPainter *painter,
00206 const QRect &rect, const QBrush &brush)
00207 {
00208 if ( !rect.isValid() )
00209 return;
00210
00211 QRect clipRect;
00212 #if QT_VERSION >= 0x040000
00213
00214
00215
00216
00217
00218
00219
00220 clipRect = painter->window();
00221 if ( painter->hasClipping() )
00222 clipRect &= painter->clipRegion().boundingRect();
00223 if ( d_deviceClipping )
00224 clipRect &= deviceClipRect();
00225 #else
00226 if ( d_deviceClipping )
00227 clipRect = deviceClipRect();
00228 #endif
00229
00230 QRect r = d_metricsMap.layoutToDevice(rect, painter);
00231 if ( clipRect.isValid() )
00232 r = r.intersect(clipRect);
00233
00234 if ( r.isValid() )
00235 painter->fillRect(r, brush);
00236 }
00237
00241 void QwtPainter::drawEllipse(QPainter *painter, const QRect &rect)
00242 {
00243 const QRect r = d_metricsMap.layoutToDevice(rect, painter);
00244
00245 if ( d_deviceClipping && !deviceClipRect().contains(rect) )
00246 return;
00247
00248 painter->drawEllipse(r);
00249 }
00250
00254 void QwtPainter::drawText(QPainter *painter, int x, int y,
00255 const QString &text)
00256 {
00257 drawText(painter, QPoint(x, y), text);
00258 }
00259
00263 void QwtPainter::drawText(QPainter *painter, const QPoint &pos,
00264 const QString &text)
00265 {
00266 const QPoint p = d_metricsMap.layoutToDevice(pos, painter);
00267
00268 if ( d_deviceClipping && !deviceClipRect().contains(p) )
00269 return;
00270
00271 painter->drawText(p, text);
00272 }
00273
00277 void QwtPainter::drawText(QPainter *painter, int x, int y, int w, int h,
00278 int flags, const QString &text)
00279 {
00280 drawText(painter, QRect(x, y, w, h), flags, text);
00281 }
00282
00286 void QwtPainter::drawText(QPainter *painter, const QRect &rect,
00287 int flags, const QString &text)
00288 {
00289 painter->drawText(
00290 d_metricsMap.layoutToDevice(rect, painter), flags, text);
00291 }
00292
00293 #ifndef QT_NO_RICHTEXT
00294
00298 #if QT_VERSION < 0x040000
00299
00300 void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect,
00301 int flags, QSimpleRichText &text)
00302 {
00303 QColorGroup cg;
00304 cg.setColor(QColorGroup::Text, painter->pen().color());
00305
00306 const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter);
00307
00308 text.setWidth(painter, scaledRect.width());
00309
00310
00311
00312 int y = scaledRect.y();
00313 if (flags & Qt::AlignBottom)
00314 y += (scaledRect.height() - text.height());
00315 else if (flags & Qt::AlignVCenter)
00316 y += (scaledRect.height() - text.height())/2;
00317
00318 text.draw(painter, scaledRect.x(), y, scaledRect, cg);
00319 }
00320 #else
00321 void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect,
00322 int flags, QTextDocument &text)
00323 {
00324 const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter);
00325 text.setPageSize(QSize(scaledRect.width(), QWIDGETSIZE_MAX));
00326
00327 QAbstractTextDocumentLayout* layout = text.documentLayout();
00328
00329 const int height = qRound(layout->documentSize().height());
00330 int y = scaledRect.y();
00331 if (flags & Qt::AlignBottom)
00332 y += (scaledRect.height() - height);
00333 else if (flags & Qt::AlignVCenter)
00334 y += (scaledRect.height() - height)/2;
00335
00336 QAbstractTextDocumentLayout::PaintContext context;
00337 context.palette.setColor(QPalette::Text, painter->pen().color());
00338
00339 painter->save();
00340
00341 painter->translate(scaledRect.x(), scaledRect.y());
00342 layout->draw(painter, context);
00343
00344 painter->restore();
00345 }
00346 #endif
00347
00348 #endif // !QT_NO_RICHTEXT
00349
00350
00354 void QwtPainter::drawLine(QPainter *painter, int x1, int y1, int x2, int y2)
00355 {
00356 if ( d_deviceClipping &&
00357 !(deviceClipRect().contains(x1, y1) && deviceClipRect().contains(x2, y2)) )
00358 {
00359 QwtPointArray pa(2);
00360 pa.setPoint(0, x1, y1);
00361 pa.setPoint(1, x2, y2);
00362 drawPolyline(painter, pa);
00363 return;
00364 }
00365
00366 if ( d_metricsMap.isIdentity() )
00367 {
00368 #if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000
00369 if ( !painter->device()->isExtDev() )
00370 #endif
00371 {
00372 painter->drawLine(x1, y1, x2, y2);
00373 return;
00374 }
00375 }
00376
00377 const QPoint p1 = d_metricsMap.layoutToDevice(QPoint(x1, y1));
00378 const QPoint p2 = d_metricsMap.layoutToDevice(QPoint(x2, y2));
00379
00380 #if QT_VERSION >= 0x030200 && QT_VERSION < 0x040000
00381 if ( painter->device()->isExtDev() )
00382 {
00383
00384
00385
00386
00387 QwtPointArray pa(2);
00388 pa.setPoint(0, p1);
00389 pa.setPoint(1, p2);
00390 painter->drawLineSegments(pa);
00391 }
00392 else
00393 painter->drawLine(p1, p2);
00394 #else
00395 painter->drawLine(p1, p2);
00396 #endif
00397 }
00398
00402 void QwtPainter::drawPolygon(QPainter *painter, const QwtPointArray &pa)
00403 {
00404 QwtPointArray cpa = d_metricsMap.layoutToDevice(pa);
00405 if ( d_deviceClipping )
00406 {
00407 #ifdef __GNUC__
00408 #warning clipping ignores painter transformations
00409 #endif
00410 cpa = clip(cpa);
00411 }
00412 painter->drawPolygon(cpa);
00413 }
00414
00418 void QwtPainter::drawPolyline(QPainter *painter, const QwtPointArray &pa)
00419 {
00420 QwtPointArray cpa = d_metricsMap.layoutToDevice(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 const QPoint pos = d_metricsMap.layoutToDevice(QPoint(x, y));
00433
00434 if ( d_deviceClipping && !deviceClipRect().contains(pos) )
00435 return;
00436
00437 painter->drawPoint(pos);
00438 }
00439
00440 void QwtPainter::drawColoredArc(QPainter *painter, const QRect &rect,
00441 int peak, int arc, int interval, const QColor &c1, const QColor &c2)
00442 {
00443 int h1, s1, v1;
00444 int h2, s2, v2;
00445
00446 #if QT_VERSION < 0x040000
00447 c1.hsv(&h1, &s1, &v1);
00448 c2.hsv(&h2, &s2, &v2);
00449 #else
00450 c1.getHsv(&h1, &s1, &v1);
00451 c2.getHsv(&h2, &s2, &v2);
00452 #endif
00453
00454 arc /= 2;
00455 for ( int angle = -arc; angle < arc; angle += interval)
00456 {
00457 double ratio;
00458 if ( angle >= 0 )
00459 ratio = 1.0 - angle / double(arc);
00460 else
00461 ratio = 1.0 + angle / double(arc);
00462
00463
00464 QColor c;
00465 c.setHsv( h1 + qRound(ratio * (h2 - h1)),
00466 s1 + qRound(ratio * (s2 - s1)),
00467 v1 + qRound(ratio * (v2 - v1)) );
00468
00469 painter->setPen(QPen(c, painter->pen().width()));
00470 painter->drawArc(rect, (peak + angle) * 16, interval * 16);
00471 }
00472 }
00473
00474 void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget)
00475 {
00476 drawFocusRect(painter, widget, widget->rect());
00477 }
00478
00479 void QwtPainter::drawFocusRect(QPainter *painter, QWidget *widget,
00480 const QRect &rect)
00481 {
00482 #if QT_VERSION < 0x040000
00483 widget->style().drawPrimitive(QStyle::PE_FocusRect, painter,
00484 rect, widget->colorGroup());
00485 #else
00486 QStyleOptionFocusRect opt;
00487 opt.init(widget);
00488 opt.rect = rect;
00489 opt.state |= QStyle::State_HasFocus;
00490
00491 widget->style()->drawPrimitive(QStyle::PE_FrameFocusRect,
00492 &opt, painter, widget);
00493 #endif
00494
00495 }
00496
00498 #if QT_VERSION < 0x040000
00499 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00500 int width, const QColorGroup &cg, bool sunken)
00501 #else
00502 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00503 int width, const QPalette &palette, bool sunken)
00504 #endif
00505 {
00506
00507 #if QT_VERSION < 0x040000
00508 QColor c0 = cg.mid();
00509 QColor c1, c2;
00510 if ( sunken )
00511 {
00512 c1 = cg.dark();
00513 c2 = cg.light();
00514 }
00515 else
00516 {
00517 c1 = cg.light();
00518 c2 = cg.dark();
00519 }
00520 #else
00521 QColor c0 = palette.color(QPalette::Mid);
00522 QColor c1, c2;
00523 if ( sunken )
00524 {
00525 c1 = palette.color(QPalette::Dark);
00526 c2 = palette.color(QPalette::Light);
00527 }
00528 else
00529 {
00530 c1 = palette.color(QPalette::Light);
00531 c2 = palette.color(QPalette::Dark);
00532 }
00533 #endif
00534
00535 painter->setPen(QPen(c0, width));
00536 painter->drawArc(rect, 0, 360 * 16);
00537
00538 const int peak = 150;
00539 const int interval = 2;
00540
00541 if ( c0 != c1 )
00542 drawColoredArc(painter, rect, peak, 160, interval, c0, c1);
00543 if ( c0 != c2 )
00544 drawColoredArc(painter, rect, peak + 180, 120, interval, c0, c2);
00545 }