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: