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

qwt_painter.cpp

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 // vim: expandtab 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 // QwtPainter::textFontSubstitutionMode does not exist for Qt-2.3. 00036 00037 // Calling qt_use_xft() from Qt-2.3 internals gives a segmentation error, 00038 // because qt_use_xft() requires presumably an open X display. 00039 // Steal qt_use_xft() but check only the environment variable QT_XFT. 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 // XorROP text drawing does not work with xft 00227 #if QT_VERSION >= 300 00228 if (Qt::XorROP == painter->rasterOp() 00229 && d_textXorRopMode == XorRopTextKeepColor) 00230 { 00231 // step 1: disable xft 00232 extern bool qt_has_xft; 00233 const bool XftEnabled = qt_has_xft; 00234 qt_has_xft = FALSE; 00235 00236 // step 2: substitute the font by a bitmap font 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 // restore state 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 // step 1: create a buffer pixmap, but we have to guess its size. 00255 #if QT_VERSION < 300 00256 int flags = Qt::AlignLeft; 00257 #else 00258 int flags = Qt::AlignAuto; // OK for QwtScaleDraw, but ??? 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 // step 2: draw the text on the pixmap 00266 QPainter pmPainter(&pixmap); 00267 pmPainter.setPen(painter->pen()); 00268 pmPainter.setFont(painter->font()); 00269 pmPainter.drawText(pixmap.rect(), flags, text, len); 00270 00271 // step 3: draw the pixmap 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 // XorROP text drawing does not work with xft 00298 #if QT_VERSION >= 300 00299 if (Qt::XorROP == painter->rasterOp() 00300 && d_textXorRopMode == XorRopTextKeepColor) 00301 { 00302 // step 1: disable xft 00303 extern bool qt_has_xft; 00304 const bool XftEnabled = qt_has_xft; 00305 qt_has_xft = FALSE; 00306 00307 // step 2: substitute the font by a bitmap font 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 // restore state 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 // step 1: create a buffer pixmap 00327 QRect target = d_metricsMap.layoutToDevice(rect, painter); 00328 QPixmap pixmap(target.size()); 00329 pixmap.fill(QColor(0, 0, 0)); 00330 00331 // step 2: draw the text on the pixmap 00332 QPainter pmPainter(&pixmap); 00333 pmPainter.setPen(painter->pen()); 00334 pmPainter.setFont(painter->font()); 00335 pmPainter.drawText(pixmap.rect(), flags, text, len); 00336 00337 // step 3: draw the pixmap 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 // QSimpleRichText is Qt::AlignTop by default 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 // XorROP text drawing does not work with xft 00382 #if QT_VERSION >= 300 00383 if (Qt::XorROP == painter->rasterOp() 00384 && d_textXorRopMode == XorRopTextKeepColor) 00385 { 00386 // step 1: disable xft 00387 extern bool qt_has_xft; 00388 const bool XftEnabled = qt_has_xft; 00389 qt_has_xft = FALSE; 00390 00391 // step 2: substitute the font by a bitmap font 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 // restore state 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 // step 1: create a buffer pixmap 00410 QPixmap pixmap(scaledRect.size()); 00411 pixmap.fill(QColor(0, 0, 0)); 00412 00413 // step 2: draw the text on the pixmap 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 // step 3: draw the pixmap 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 // Strange: the postscript driver of QPrinter adds an offset 00464 // of 0.5 to the start/endpoint when using drawLine, but not 00465 // for lines painted with drawLineSegments. 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); // full 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 // Local Variables: 00648 // mode: C++ 00649 // c-file-style: "stroustrup" 00650 // indent-tabs-mode: nil 00651 // End:

Generated on Tue Nov 16 21:12:20 2004 for Qwt User's Guide by doxygen 1.3.8