00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <qwindowdefs.h>
00013 #include <qrect.h>
00014 #include <qpainter.h>
00015 #include <qpalette.h>
00016 #include <qpaintdevice.h>
00017 #include <qpaintdevicemetrics.h>
00018 #include <qpixmap.h>
00019 #include <qsimplerichtext.h>
00020
00021 #include "qwt_painter.h"
00022 #include "qwt_rect.h"
00023 #include "qwt_math.h"
00024
00025 #if defined(Q_WS_X11)
00026 bool QwtPainter::d_deviceClipping = TRUE;
00027 #else
00028 bool QwtPainter::d_deviceClipping = FALSE;
00029 #endif
00030
00031 QwtMetricsMap QwtPainter::d_metricsMap;
00032
00033 #if defined(QWT_BROKEN_RASTEROP_FONT)
00034 #if QT_VERSION < 300
00035
00036
00037
00038
00039
00040 #include <stdlib.h>
00041 static int qwt_use_xft (void)
00042 {
00043 static int checked_env=0;
00044 static int use_xft=0;
00045
00046 if (!checked_env) {
00047 char *e = getenv ("QT_XFT");
00048 if ( e && (*e == '1' ||
00049 *e == 'y' || *e == 'Y' ||
00050 *e == 't' || *e == 'T' ))
00051 use_xft = 1;
00052 else
00053 use_xft = 0;
00054 }
00055 checked_env = 1;
00056
00057 return use_xft;
00058 }
00059 int QwtPainter::d_textXorRopMode = qwt_use_xft() ?
00060 QwtPainter::XorRopTextKeepFont : QwtPainter::XorRopTextNormal;
00061 #else // QT_VERSION >= 300
00062 #if 1
00063 int QwtPainter::d_textXorRopMode = QwtPainter::XorRopTextKeepFont;
00064 #else
00065 int QwtPainter::d_textXorRopMode = QwtPainter::XorRopTextKeepColor;
00066 #endif
00067 #endif // QT_VERSION
00068 #else
00069 int QwtPainter::d_textXorRopMode = QwtPainter::XorRopTextNormal;
00070 #endif
00071
00077 void QwtPainter::setDeviceClipping(bool enable)
00078 {
00079 d_deviceClipping = enable;
00080 }
00081
00088 bool QwtPainter::deviceClipping()
00089 {
00090 return d_deviceClipping;
00091 }
00092
00097 const QRect &QwtPainter::deviceClipRect()
00098 {
00099 static QRect clip;
00100
00101 if ( !clip.isValid() )
00102 {
00103 clip.setCoords(QWT_COORD_MIN, QWT_COORD_MIN,
00104 QWT_COORD_MAX, QWT_COORD_MAX);
00105 }
00106 return clip;
00107 }
00108
00117 void QwtPainter::setMetricsMap(const QPaintDevice *layout,
00118 const QPaintDevice *device)
00119 {
00120 d_metricsMap.setMetrics(layout, device);
00121 }
00122
00127 void QwtPainter::setMetricsMap(const QwtMetricsMap &map)
00128 {
00129 d_metricsMap = map;
00130 }
00131
00136 void QwtPainter::resetMetricsMap()
00137 {
00138 d_metricsMap = QwtMetricsMap();
00139 }
00140
00144 const QwtMetricsMap &QwtPainter::metricsMap()
00145 {
00146 return d_metricsMap;
00147 }
00148
00152 void QwtPainter::setClipRect(QPainter *painter, const QRect &rect)
00153 {
00154 painter->setClipRect(d_metricsMap.layoutToDevice(rect, painter));
00155 }
00156
00160 void QwtPainter::drawRect(QPainter *painter, int x, int y, int w, int h)
00161 {
00162 drawRect(painter, QRect(x, y, w, h));
00163 }
00164
00168 void QwtPainter::drawRect(QPainter *painter, const QRect &rect)
00169 {
00170 const QRect r = d_metricsMap.layoutToDevice(rect, painter);
00171
00172 if ( d_deviceClipping && !deviceClipRect().contains(r) )
00173 return;
00174
00175 painter->drawRect(r);
00176 }
00177
00181 void QwtPainter::fillRect(QPainter *painter,
00182 const QRect &rect, const QBrush &brush)
00183 {
00184 const QRect r = d_metricsMap.layoutToDevice(rect, painter);
00185
00186 if ( d_deviceClipping && !deviceClipRect().contains(r) )
00187 return;
00188
00189 painter->fillRect(r, brush);
00190 }
00191
00195 void QwtPainter::drawEllipse(QPainter *painter, const QRect &rect)
00196 {
00197 const QRect r = d_metricsMap.layoutToDevice(rect, painter);
00198
00199 if ( d_deviceClipping && !deviceClipRect().contains(rect) )
00200 return;
00201
00202 painter->drawEllipse(r);
00203 }
00204
00208 void QwtPainter::drawText(QPainter *painter, int x, int y,
00209 const QString &text, int len)
00210 {
00211 drawText(painter, QPoint(x, y), text, len);
00212 }
00213
00217 void QwtPainter::drawText(QPainter *painter, const QPoint &pos,
00218 const QString &text, int len)
00219 {
00220 const QPoint p = d_metricsMap.layoutToDevice(pos, painter);
00221
00222 if ( d_deviceClipping && !deviceClipRect().contains(p) )
00223 return;
00224
00225 #if defined(QWT_BROKEN_RASTEROP_FONT)
00226
00227 #if QT_VERSION >= 300
00228 if (Qt::XorROP == painter->rasterOp()
00229 && d_textXorRopMode == XorRopTextKeepColor)
00230 {
00231
00232 extern bool qt_has_xft;
00233 const bool XftEnabled = qt_has_xft;
00234 qt_has_xft = FALSE;
00235
00236
00237 painter->save();
00238 QFont font = painter->font();
00239 font.setStyleStrategy(QFont::PreferBitmap);
00240 painter->setFont(font);
00241
00242 painter->drawText(p, text, len);
00243
00244
00245 qt_has_xft = XftEnabled;
00246 painter->restore();
00247
00248 }
00249 else
00250 #endif
00251 if (Qt::XorROP == painter->rasterOp()
00252 && d_textXorRopMode == XorRopTextKeepFont)
00253 {
00254
00255 #if QT_VERSION < 300
00256 int flags = Qt::AlignLeft;
00257 #else
00258 int flags = Qt::AlignAuto;
00259 #endif
00260 QFontMetrics fm = painter->fontMetrics();
00261 QPixmap pixmap(fm.boundingRect(
00262 0, 0, QCOORD_MAX, QCOORD_MAX, flags, text, len).size());
00263 pixmap.fill(QColor(0, 0, 0));
00264
00265
00266 QPainter pmPainter(&pixmap);
00267 pmPainter.setPen(painter->pen());
00268 pmPainter.setFont(painter->font());
00269 pmPainter.drawText(pixmap.rect(), flags, text, len);
00270
00271
00272 painter->drawPixmap(p.x(), p.y() - fm.ascent(), pixmap);
00273 }
00274 else
00275 #endif
00276 {
00277 painter->drawText(p, text, len);
00278 }
00279 }
00280
00284 void QwtPainter::drawText(QPainter *painter, int x, int y, int w, int h,
00285 int flags, const QString &text, int len)
00286 {
00287 drawText(painter, QRect(x, y, w, h), flags, text, len);
00288 }
00289
00293 void QwtPainter::drawText(QPainter *painter, const QRect &rect,
00294 int flags, const QString &text, int len)
00295 {
00296 #if defined(QWT_BROKEN_RASTEROP_FONT)
00297
00298 #if QT_VERSION >= 300
00299 if (Qt::XorROP == painter->rasterOp()
00300 && d_textXorRopMode == XorRopTextKeepColor)
00301 {
00302
00303 extern bool qt_has_xft;
00304 const bool XftEnabled = qt_has_xft;
00305 qt_has_xft = FALSE;
00306
00307
00308 painter->save();
00309 QFont font = painter->font();
00310 font.setStyleStrategy(QFont::PreferBitmap);
00311 painter->setFont(font);
00312
00313 painter->drawText(
00314 d_metricsMap.layoutToDevice(rect, painter), flags, text, len);
00315
00316
00317 painter->restore();
00318 qt_has_xft = XftEnabled;
00319
00320 }
00321 else
00322 #endif
00323 if (Qt::XorROP == painter->rasterOp()
00324 && d_textXorRopMode == XorRopTextKeepFont)
00325 {
00326
00327 QRect target = d_metricsMap.layoutToDevice(rect, painter);
00328 QPixmap pixmap(target.size());
00329 pixmap.fill(QColor(0, 0, 0));
00330
00331
00332 QPainter pmPainter(&pixmap);
00333 pmPainter.setPen(painter->pen());
00334 pmPainter.setFont(painter->font());
00335 pmPainter.drawText(pixmap.rect(), flags, text, len);
00336
00337
00338 #if QT_VERSION < 300
00339 painter->drawPixmap(target.x(), target.y(), pixmap);
00340 #else
00341 painter->drawPixmap(target, pixmap);
00342 #endif
00343 }
00344 else
00345 #endif
00346 {
00347 painter->drawText(
00348 d_metricsMap.layoutToDevice(rect, painter), flags, text, len);
00349 }
00350 }
00351
00352 #ifndef QT_NO_RICHTEXT
00353
00357 void QwtPainter::drawSimpleRichText(QPainter *painter, const QRect &rect,
00358 int flags, QSimpleRichText &text)
00359 {
00360 QColorGroup cg;
00361 cg.setColor(QColorGroup::Text, painter->pen().color());
00362
00363 #if QT_VERSION < 300
00364 const QFont defaultFont = QFont::defaultFont();
00365 QFont::setDefaultFont(painter->font());
00366 #endif
00367
00368 const QRect scaledRect = d_metricsMap.layoutToDevice(rect, painter);
00369
00370 text.setWidth(painter, scaledRect.width());
00371
00372
00373
00374 int y = scaledRect.y();
00375 if (flags & Qt::AlignBottom)
00376 y += (scaledRect.height() - text.height());
00377 else if (flags & Qt::AlignVCenter)
00378 y += (scaledRect.height() - text.height())/2;
00379
00380 #if defined(QWT_BROKEN_RASTEROP_FONT)
00381
00382 #if QT_VERSION >= 300
00383 if (Qt::XorROP == painter->rasterOp()
00384 && d_textXorRopMode == XorRopTextKeepColor)
00385 {
00386
00387 extern bool qt_has_xft;
00388 const bool XftEnabled = qt_has_xft;
00389 qt_has_xft = FALSE;
00390
00391
00392 painter->save();
00393 QFont font = painter->font();
00394 font.setStyleStrategy(QFont::PreferBitmap);
00395 painter->setFont(font);
00396
00397 text.draw(painter, scaledRect.x(), y, scaledRect, cg);
00398
00399
00400 painter->restore();
00401 qt_has_xft = XftEnabled;
00402
00403 }
00404 else
00405 #endif
00406 if (Qt::XorROP == painter->rasterOp()
00407 && d_textXorRopMode == XorRopTextKeepFont)
00408 {
00409
00410 QPixmap pixmap(scaledRect.size());
00411 pixmap.fill(QColor(0, 0, 0));
00412
00413
00414 QPainter pmPainter(&pixmap);
00415 pmPainter.setPen(painter->pen());
00416 pmPainter.setFont(painter->font());
00417 text.draw(&pmPainter, scaledRect.x(), y, scaledRect, cg);
00418
00419
00420 #if QT_VERSION < 300
00421 painter->drawPixmap(scaledRect.x(), scaledRect.y(), pixmap);
00422 #else
00423 painter->drawPixmap(scaledRect, pixmap);
00424 #endif
00425 }
00426 else
00427 #endif
00428 {
00429 text.draw(painter, scaledRect.x(), y, scaledRect, cg);
00430 }
00431
00432 #if QT_VERSION < 300
00433 QFont::setDefaultFont(defaultFont);
00434 #endif
00435 }
00436
00437 #endif // !QT_NO_RICHTEXT
00438
00439
00443 void QwtPainter::drawLine(QPainter *painter,
00444 const QPoint &p1, const QPoint &p2)
00445 {
00446 QPointArray pa(2);
00447
00448 if ( d_deviceClipping &&
00449 !(deviceClipRect().contains(p1) && deviceClipRect().contains(p2)) )
00450 {
00451 pa.setPoint(0, p1);
00452 pa.setPoint(1, p2);
00453 drawPolyline(painter, pa);
00454 }
00455 else
00456 {
00457 pa.setPoint(0, d_metricsMap.layoutToDevice(p1));
00458 pa.setPoint(1, d_metricsMap.layoutToDevice(p2));
00459
00460 #if QT_VERSION >= 0x030200
00461 if ( painter->device()->isExtDev() )
00462 {
00463
00464
00465
00466
00467 painter->drawLineSegments(pa);
00468 }
00469 else
00470 painter->drawLine(pa[0], pa[1]);
00471 #else
00472 painter->drawLine(pa[0], pa[1]);
00473 #endif
00474 }
00475 }
00476
00481 void QwtPainter::drawLine(QPainter *painter, int x1, int y1, int x2, int y2)
00482 {
00483 drawLine(painter, QPoint(x1, y1), QPoint(x2, y2));
00484 }
00485
00490 void QwtPainter::drawPolygon(QPainter *painter, const QPointArray &pa)
00491 {
00492 QPointArray cpa = d_metricsMap.layoutToDevice(pa);
00493 if ( d_deviceClipping )
00494 cpa = clip(cpa);
00495 painter->drawPolygon(cpa);
00496 }
00497
00501 void QwtPainter::drawPolyline(QPainter *painter, const QPointArray &pa)
00502 {
00503 QPointArray cpa = d_metricsMap.layoutToDevice(pa);
00504 if ( d_deviceClipping )
00505 cpa = clip(cpa);
00506 painter->drawPolyline(cpa);
00507 }
00508
00513 void QwtPainter::drawPoint(QPainter *painter, int x, int y)
00514 {
00515 const QPoint pos = d_metricsMap.layoutToDevice(QPoint(x, y));
00516
00517 if ( d_deviceClipping && !deviceClipRect().contains(pos) )
00518 return;
00519
00520 painter->drawPoint(pos);
00521 }
00522
00524 QPointArray QwtPainter::clip(const QPointArray &pa)
00525 {
00526 const QwtRect rect(deviceClipRect());
00527 return rect.clip(pa);
00528 }
00529
00530 void QwtPainter::drawColoredArc(QPainter *painter, const QRect &rect,
00531 int peak, int arc, int intervall, const QColor &c1, const QColor &c2)
00532 {
00533 int h1, s1, v1;
00534 int h2, s2, v2;
00535
00536 c1.hsv(&h1, &s1, &v1);
00537 c2.hsv(&h2, &s2, &v2);
00538
00539 arc /= 2;
00540 for ( int angle = -arc; angle < arc; angle += intervall)
00541 {
00542 double ratio;
00543 if ( angle >= 0 )
00544 ratio = 1.0 - angle / double(arc);
00545 else
00546 ratio = 1.0 + angle / double(arc);
00547
00548
00549 const QColor c(h1 + qRound(ratio * (h2 - h1)),
00550 s1 + qRound(ratio * (s2 - s1)),
00551 v1 + qRound(ratio * (v2 - v1)),
00552 QColor::Hsv);
00553
00554 painter->setPen(QPen(c, painter->pen().width()));
00555 painter->drawArc(rect, (peak + angle) * 16, intervall * 16);
00556 }
00557 }
00558
00560 void QwtPainter::drawRoundFrame(QPainter *painter, const QRect &rect,
00561 int width, const QColorGroup &cg, bool sunken)
00562 {
00563 QColor c0 = cg.mid();
00564 QColor c1, c2;
00565 if ( sunken )
00566 {
00567 c1 = cg.dark();
00568 c2 = cg.light();
00569 }
00570 else
00571 {
00572 c1 = cg.light();
00573 c2 = cg.dark();
00574 }
00575
00576 painter->setPen(QPen(c0, width));
00577 painter->drawArc(rect, 0, 360 * 16);
00578
00579 const int peak = 150;
00580 const int intervall = 2;
00581
00582 if ( c0 != c1 )
00583 drawColoredArc(painter, rect, peak, 160, intervall, c0, c1);
00584 if ( c0 != c2 )
00585 drawColoredArc(painter, rect, peak + 180, 120, intervall, c0, c2);
00586 }
00587
00594 int QwtPainter::textXorRopMode()
00595 {
00596 return d_textXorRopMode;
00597 }
00598
00618 #if defined(QWT_BROKEN_RASTEROP_FONT)
00619
00620 int QwtPainter::setTextXorRopMode(TextXorRopMode mode)
00621 {
00622 if ((mode == XorRopTextNormal)
00623 || (mode == XorRopTextKeepFont)
00624 #if QT_VERSION >= 300
00625 || (mode == XorRopTextKeepColor)
00626 #endif
00627 )
00628 d_textXorRopMode = mode;
00629
00630 #if QT_VERSION < 300
00631 if (!qwt_use_xft())
00632 d_textXorRopMode = XorRopTextNormal;
00633 #endif
00634
00635 return d_textXorRopMode;
00636 }
00637
00638 #else
00639
00640 int QwtPainter::setTextXorRopMode(TextXorRopMode)
00641 {
00642 return d_textXorRopMode;
00643 }
00644
00645 #endif
00646
00647
00648
00649
00650
00651