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 Sun Nov 21 11:12:43 2004 for Qwt User's Guide by doxygen 1.3.5