00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_painter.h"
00011 #include "qwt_math.h"
00012 #include "qwt_clipper.h"
00013 #include "qwt_color_map.h"
00014 #include "qwt_scale_map.h"
00015 #include <qwindowdefs.h>
00016 #include <qwidget.h>
00017 #include <qframe.h>
00018 #include <qrect.h>
00019 #include <qpainter.h>
00020 #include <qpalette.h>
00021 #include <qpaintdevice.h>
00022 #include <qpixmap.h>
00023 #include <qstyle.h>
00024 #include <qtextdocument.h>
00025 #include <qabstracttextdocumentlayout.h>
00026 #include <qstyleoption.h>
00027 #include <qpaintengine.h>
00028 #include <qapplication.h>
00029 #include <qdesktopwidget.h>
00030
00031 #if QT_VERSION >= 0x050000
00032 #include <qwindow.h>
00033 #endif
00034
00035 #if QT_VERSION < 0x050000
00036
00037 #ifdef Q_WS_X11
00038 #include <qx11info_x11.h>
00039 #endif
00040
00041 #endif
00042
00043 bool QwtPainter::d_polylineSplitting = true;
00044 bool QwtPainter::d_roundingAlignment = true;
00045
00046 static inline bool qwtIsRasterPaintEngineBuggy()
00047 {
00048 #if 0
00049 static int isBuggy = -1;
00050 if ( isBuggy < 0 )
00051 {
00052
00053
00054
00055 QImage image( 2, 3, QImage::Format_ARGB32 );
00056 image.fill( 0u );
00057
00058 QPolygonF p;
00059 p += QPointF(0, 1);
00060 p += QPointF(0, 0);
00061 p += QPointF(1, 0 );
00062 p += QPointF(1, 2 );
00063
00064 QPainter painter( &image );
00065 painter.drawPolyline( p );
00066 painter.end();
00067
00068 isBuggy = ( image.pixel( 1, 1 ) == 0 ) ? 1 : 0;
00069 }
00070
00071 return isBuggy == 1;
00072 #endif
00073
00074 #if QT_VERSION < 0x040800
00075 return false;
00076 #elif QT_VERSION < 0x050000
00077 return true;
00078 #elif QT_VERSION < 0x050100
00079 return false;
00080 #elif QT_VERSION < 0x050400
00081 return true;
00082 #else
00083 return false;
00084 #endif
00085 }
00086
00087 static inline bool qwtIsClippingNeeded(
00088 const QPainter *painter, QRectF &clipRect )
00089 {
00090 bool doClipping = false;
00091 const QPaintEngine *pe = painter->paintEngine();
00092 if ( pe && pe->type() == QPaintEngine::SVG )
00093 {
00094
00095
00096 if ( painter->hasClipping() )
00097 {
00098 doClipping = true;
00099 clipRect = painter->clipRegion().boundingRect();
00100 }
00101 }
00102
00103 return doClipping;
00104 }
00105
00106 template <class T>
00107 static inline void qwtDrawPolyline( QPainter *painter,
00108 const T *points, int pointCount, bool polylineSplitting )
00109 {
00110 bool doSplit = false;
00111 if ( polylineSplitting && pointCount > 3 )
00112 {
00113 const QPaintEngine *pe = painter->paintEngine();
00114 if ( pe && pe->type() == QPaintEngine::Raster )
00115 {
00116 if ( painter->pen().width() <= 1 )
00117 {
00118 #if QT_VERSION < 0x040800
00119 if ( painter->renderHints() & QPainter::Antialiasing )
00120 {
00121
00122
00123
00124
00125
00126 doSplit = true;
00127 }
00128 #endif
00129
00130
00131
00132 doSplit = qwtIsRasterPaintEngineBuggy();
00133 }
00134 else
00135 {
00136
00137
00138
00139
00140
00141 doSplit = true;
00142 }
00143 }
00144 }
00145
00146 if ( doSplit )
00147 {
00148 QPen pen = painter->pen();
00149
00150 const int splitSize = 6;
00151
00152 if ( pen.width() <= 1 && pen.isSolid() && qwtIsRasterPaintEngineBuggy()
00153 && !( painter->renderHints() & QPainter::Antialiasing ) )
00154 {
00155 int k = 0;
00156
00157 for ( int i = k + 1; i < pointCount; i++ )
00158 {
00159 const QPointF &p1 = points[i-1];
00160 const QPointF &p2 = points[i];
00161
00162 const bool isBad = ( qAbs( p2.y() - p1.y() ) <= 1 )
00163 && qAbs( p2.x() - p1.x() ) <= 1;
00164
00165 if ( isBad || ( i - k >= splitSize ) )
00166 {
00167 painter->drawPolyline( points + k, i - k + 1 );
00168 k = i;
00169 }
00170 }
00171
00172 painter->drawPolyline( points + k, pointCount - k );
00173 }
00174 else
00175 {
00176 for ( int i = 0; i < pointCount; i += splitSize )
00177 {
00178 const int n = qMin( splitSize + 1, pointCount - i );
00179 painter->drawPolyline( points + i, n );
00180 }
00181 }
00182 }
00183 else
00184 {
00185 painter->drawPolyline( points, pointCount );
00186 }
00187 }
00188
00189 static inline QSize qwtScreenResolution()
00190 {
00191 static QSize screenResolution;
00192 if ( !screenResolution.isValid() )
00193 {
00194 QDesktopWidget *desktop = QApplication::desktop();
00195 if ( desktop )
00196 {
00197 screenResolution.setWidth( desktop->logicalDpiX() );
00198 screenResolution.setHeight( desktop->logicalDpiY() );
00199 }
00200 }
00201
00202 return screenResolution;
00203 }
00204
00205 static inline void qwtUnscaleFont( QPainter *painter )
00206 {
00207 if ( painter->font().pixelSize() >= 0 )
00208 return;
00209
00210 const QSize screenResolution = qwtScreenResolution();
00211
00212 const QPaintDevice *pd = painter->device();
00213 if ( pd->logicalDpiX() != screenResolution.width() ||
00214 pd->logicalDpiY() != screenResolution.height() )
00215 {
00216 QFont pixelFont( painter->font(), QApplication::desktop() );
00217 pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() );
00218
00219 painter->setFont( pixelFont );
00220 }
00221 }
00222
00230 bool QwtPainter::isX11GraphicsSystem()
00231 {
00232 #if QT_VERSION < 0x050000
00233 static int onX11 = -1;
00234 if ( onX11 < 0 )
00235 {
00236 QPixmap pm( 1, 1 );
00237 QPainter painter( &pm );
00238
00239 onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0;
00240 }
00241
00242 return onX11 == 1;
00243 #else
00244
00245
00246 return false;
00247 #endif
00248 }
00249
00264 bool QwtPainter::isAligning( QPainter *painter )
00265 {
00266 if ( painter && painter->isActive() )
00267 {
00268 switch ( painter->paintEngine()->type() )
00269 {
00270 case QPaintEngine::Pdf:
00271 case QPaintEngine::SVG:
00272 return false;
00273
00274 default:;
00275 }
00276
00277 const QTransform tr = painter->transform();
00278 if ( tr.isRotating() || tr.isScaling() )
00279 {
00280
00281 return false;
00282 }
00283 }
00284
00285 return true;
00286 }
00287
00299 void QwtPainter::setRoundingAlignment( bool enable )
00300 {
00301 d_roundingAlignment = enable;
00302 }
00303
00319 void QwtPainter::setPolylineSplitting( bool enable )
00320 {
00321 d_polylineSplitting = enable;
00322 }
00323
00325 void QwtPainter::drawPath( QPainter *painter, const QPainterPath &path )
00326 {
00327 painter->drawPath( path );
00328 }
00329
00331 void QwtPainter::drawRect( QPainter *painter, double x, double y, double w, double h )
00332 {
00333 drawRect( painter, QRectF( x, y, w, h ) );
00334 }
00335
00337 void QwtPainter::drawRect( QPainter *painter, const QRectF &rect )
00338 {
00339 const QRectF r = rect;
00340
00341 QRectF clipRect;
00342 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00343
00344 if ( deviceClipping )
00345 {
00346 if ( !clipRect.intersects( r ) )
00347 return;
00348
00349 if ( !clipRect.contains( r ) )
00350 {
00351 fillRect( painter, r & clipRect, painter->brush() );
00352
00353 painter->save();
00354 painter->setBrush( Qt::NoBrush );
00355 drawPolyline( painter, QPolygonF( r ) );
00356 painter->restore();
00357
00358 return;
00359 }
00360 }
00361
00362 painter->drawRect( r );
00363 }
00364
00366 void QwtPainter::fillRect( QPainter *painter,
00367 const QRectF &rect, const QBrush &brush )
00368 {
00369 if ( !rect.isValid() )
00370 return;
00371
00372 QRectF clipRect;
00373 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00374
00375
00376
00377
00378
00379
00380
00381 if ( deviceClipping )
00382 clipRect &= painter->window();
00383 else
00384 clipRect = painter->window();
00385
00386 if ( painter->hasClipping() )
00387 clipRect &= painter->clipRegion().boundingRect();
00388
00389 QRectF r = rect;
00390 if ( deviceClipping )
00391 r = r.intersected( clipRect );
00392
00393 if ( r.isValid() )
00394 painter->fillRect( r, brush );
00395 }
00396
00398 void QwtPainter::drawPie( QPainter *painter, const QRectF &rect,
00399 int a, int alen )
00400 {
00401 QRectF clipRect;
00402 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00403 if ( deviceClipping && !clipRect.contains( rect ) )
00404 return;
00405
00406 painter->drawPie( rect, a, alen );
00407 }
00408
00410 void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect )
00411 {
00412 QRectF clipRect;
00413 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00414
00415 if ( deviceClipping && !clipRect.contains( rect ) )
00416 return;
00417
00418 painter->drawEllipse( rect );
00419 }
00420
00422 void QwtPainter::drawText( QPainter *painter, double x, double y,
00423 const QString &text )
00424 {
00425 drawText( painter, QPointF( x, y ), text );
00426 }
00427
00429 void QwtPainter::drawText( QPainter *painter, const QPointF &pos,
00430 const QString &text )
00431 {
00432 QRectF clipRect;
00433 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00434
00435 if ( deviceClipping && !clipRect.contains( pos ) )
00436 return;
00437
00438
00439 painter->save();
00440 qwtUnscaleFont( painter );
00441 painter->drawText( pos, text );
00442 painter->restore();
00443 }
00444
00446 void QwtPainter::drawText( QPainter *painter,
00447 double x, double y, double w, double h,
00448 int flags, const QString &text )
00449 {
00450 drawText( painter, QRectF( x, y, w, h ), flags, text );
00451 }
00452
00454 void QwtPainter::drawText( QPainter *painter, const QRectF &rect,
00455 int flags, const QString &text )
00456 {
00457 painter->save();
00458 qwtUnscaleFont( painter );
00459 painter->drawText( rect, flags, text );
00460 painter->restore();
00461 }
00462
00463 #ifndef QT_NO_RICHTEXT
00464
00473 void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect,
00474 int flags, const QTextDocument &text )
00475 {
00476 QTextDocument *txt = text.clone();
00477
00478 painter->save();
00479
00480 QRectF unscaledRect = rect;
00481
00482 if ( painter->font().pixelSize() < 0 )
00483 {
00484 const QSize res = qwtScreenResolution();
00485
00486 const QPaintDevice *pd = painter->device();
00487 if ( pd->logicalDpiX() != res.width() ||
00488 pd->logicalDpiY() != res.height() )
00489 {
00490 QTransform transform;
00491 transform.scale( res.width() / double( pd->logicalDpiX() ),
00492 res.height() / double( pd->logicalDpiY() ));
00493
00494 painter->setWorldTransform( transform, true );
00495 unscaledRect = transform.inverted().mapRect(rect);
00496 }
00497 }
00498
00499 txt->setDefaultFont( painter->font() );
00500 txt->setPageSize( QSizeF( unscaledRect.width(), QWIDGETSIZE_MAX ) );
00501
00502 QAbstractTextDocumentLayout* layout = txt->documentLayout();
00503
00504 const double height = layout->documentSize().height();
00505 double y = unscaledRect.y();
00506 if ( flags & Qt::AlignBottom )
00507 y += ( unscaledRect.height() - height );
00508 else if ( flags & Qt::AlignVCenter )
00509 y += ( unscaledRect.height() - height ) / 2;
00510
00511 QAbstractTextDocumentLayout::PaintContext context;
00512 context.palette.setColor( QPalette::Text, painter->pen().color() );
00513
00514 painter->translate( unscaledRect.x(), y );
00515 layout->draw( painter, context );
00516
00517 painter->restore();
00518 delete txt;
00519 }
00520
00521 #endif // !QT_NO_RICHTEXT
00522
00523
00525 void QwtPainter::drawLine( QPainter *painter,
00526 const QPointF &p1, const QPointF &p2 )
00527 {
00528 QRectF clipRect;
00529 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00530
00531 if ( deviceClipping &&
00532 !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) )
00533 {
00534 QPolygonF polygon;
00535 polygon += p1;
00536 polygon += p2;
00537 drawPolyline( painter, polygon );
00538 return;
00539 }
00540
00541 painter->drawLine( p1, p2 );
00542 }
00543
00545 void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon )
00546 {
00547 QRectF clipRect;
00548 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00549
00550 if ( deviceClipping )
00551 {
00552 painter->drawPolygon(
00553 QwtClipper::clippedPolygonF( clipRect, polygon, true ) );
00554 }
00555 else
00556 {
00557 painter->drawPolygon( polygon );
00558 }
00559 }
00560
00562 void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon )
00563 {
00564 QRectF clipRect;
00565 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00566
00567 if ( deviceClipping )
00568 {
00569 const QPolygonF cpa = QwtClipper::clippedPolygonF( clipRect, polygon );
00570
00571 qwtDrawPolyline<QPointF>( painter,
00572 cpa.constData(), cpa.size(), d_polylineSplitting );
00573 }
00574 else
00575 {
00576 qwtDrawPolyline<QPointF>( painter,
00577 polygon.constData(), polygon.size(), d_polylineSplitting );
00578 }
00579 }
00580
00582 void QwtPainter::drawPolyline( QPainter *painter,
00583 const QPointF *points, int pointCount )
00584 {
00585 QRectF clipRect;
00586 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00587
00588 if ( deviceClipping )
00589 {
00590 QPolygonF polygon( pointCount );
00591 ::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) );
00592
00593 QwtClipper::clipPolygonF( clipRect, polygon );
00594 qwtDrawPolyline<QPointF>( painter,
00595 polygon.constData(), polygon.size(), d_polylineSplitting );
00596 }
00597 else
00598 {
00599 qwtDrawPolyline<QPointF>( painter, points, pointCount, d_polylineSplitting );
00600 }
00601 }
00602
00604 void QwtPainter::drawPolygon( QPainter *painter, const QPolygon &polygon )
00605 {
00606 QRectF clipRect;
00607 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00608
00609 if ( deviceClipping )
00610 {
00611 painter->drawPolygon(
00612 QwtClipper::clippedPolygon( clipRect, polygon, true ) );
00613 }
00614 else
00615 {
00616 painter->drawPolygon( polygon );
00617 }
00618 }
00619
00621 void QwtPainter::drawPolyline( QPainter *painter, const QPolygon &polygon )
00622 {
00623 QRectF clipRect;
00624 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00625
00626 if ( deviceClipping )
00627 {
00628 const QPolygon cpa = QwtClipper::clippedPolygon( clipRect, polygon );
00629
00630 qwtDrawPolyline<QPoint>( painter,
00631 cpa.constData(), cpa.size(), d_polylineSplitting );
00632 }
00633 else
00634 {
00635 qwtDrawPolyline<QPoint>( painter,
00636 polygon.constData(), polygon.size(), d_polylineSplitting );
00637 }
00638 }
00639
00641 void QwtPainter::drawPolyline( QPainter *painter,
00642 const QPoint *points, int pointCount )
00643 {
00644 QRectF clipRect;
00645 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00646
00647 if ( deviceClipping )
00648 {
00649 QPolygon polygon( pointCount );
00650 ::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) );
00651
00652 QwtClipper::clipPolygon( clipRect, polygon );
00653 qwtDrawPolyline<QPoint>( painter,
00654 polygon.constData(), polygon.size(), d_polylineSplitting );
00655 }
00656 else
00657 {
00658 qwtDrawPolyline<QPoint>( painter, points, pointCount, d_polylineSplitting );
00659 }
00660 }
00661
00663 void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos )
00664 {
00665 QRectF clipRect;
00666 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00667
00668 if ( deviceClipping && !clipRect.contains( pos ) )
00669 return;
00670
00671 painter->drawPoint( pos );
00672 }
00673
00675 void QwtPainter::drawPoint( QPainter *painter, const QPoint &pos )
00676 {
00677 QRectF clipRect;
00678 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00679
00680 if ( deviceClipping )
00681 {
00682 const int minX = qCeil( clipRect.left() );
00683 const int maxX = qFloor( clipRect.right() );
00684 const int minY = qCeil( clipRect.top() );
00685 const int maxY = qFloor( clipRect.bottom() );
00686
00687 if ( pos.x() < minX || pos.x() > maxX
00688 || pos.y() < minY || pos.y() > maxY )
00689 {
00690 return;
00691 }
00692 }
00693
00694 painter->drawPoint( pos );
00695 }
00696
00698 void QwtPainter::drawPoints( QPainter *painter,
00699 const QPoint *points, int pointCount )
00700 {
00701 QRectF clipRect;
00702 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00703
00704 if ( deviceClipping )
00705 {
00706 const int minX = qCeil( clipRect.left() );
00707 const int maxX = qFloor( clipRect.right() );
00708 const int minY = qCeil( clipRect.top() );
00709 const int maxY = qFloor( clipRect.bottom() );
00710
00711 const QRect r( minX, minY, maxX - minX, maxY - minY );
00712
00713 QPolygon clippedPolygon( pointCount );
00714 QPoint *clippedData = clippedPolygon.data();
00715
00716 int numClippedPoints = 0;
00717 for ( int i = 0; i < pointCount; i++ )
00718 {
00719 if ( r.contains( points[i] ) )
00720 clippedData[ numClippedPoints++ ] = points[i];
00721 }
00722 painter->drawPoints( clippedData, numClippedPoints );
00723 }
00724 else
00725 {
00726 painter->drawPoints( points, pointCount );
00727 }
00728 }
00729
00731 void QwtPainter::drawPoints( QPainter *painter,
00732 const QPointF *points, int pointCount )
00733 {
00734 QRectF clipRect;
00735 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00736
00737 if ( deviceClipping )
00738 {
00739 QPolygonF clippedPolygon( pointCount );
00740 QPointF *clippedData = clippedPolygon.data();
00741
00742 int numClippedPoints = 0;
00743 for ( int i = 0; i < pointCount; i++ )
00744 {
00745 if ( clipRect.contains( points[i] ) )
00746 clippedData[ numClippedPoints++ ] = points[i];
00747 }
00748 painter->drawPoints( clippedData, numClippedPoints );
00749 }
00750 else
00751 {
00752 painter->drawPoints( points, pointCount );
00753 }
00754 }
00755
00757 void QwtPainter::drawImage( QPainter *painter,
00758 const QRectF &rect, const QImage &image )
00759 {
00760 const QRect alignedRect = rect.toAlignedRect();
00761
00762 if ( alignedRect != rect )
00763 {
00764 const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00765
00766 painter->save();
00767 painter->setClipRect( clipRect, Qt::IntersectClip );
00768 painter->drawImage( alignedRect, image );
00769 painter->restore();
00770 }
00771 else
00772 {
00773 painter->drawImage( alignedRect, image );
00774 }
00775 }
00776
00778 void QwtPainter::drawPixmap( QPainter *painter,
00779 const QRectF &rect, const QPixmap &pixmap )
00780 {
00781 const QRect alignedRect = rect.toAlignedRect();
00782
00783 if ( alignedRect != rect )
00784 {
00785 const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00786
00787 painter->save();
00788 painter->setClipRect( clipRect, Qt::IntersectClip );
00789 painter->drawPixmap( alignedRect, pixmap );
00790 painter->restore();
00791 }
00792 else
00793 {
00794 painter->drawPixmap( alignedRect, pixmap );
00795 }
00796 }
00797
00799 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget )
00800 {
00801 drawFocusRect( painter, widget, widget->rect() );
00802 }
00803
00805 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget,
00806 const QRect &rect )
00807 {
00808 QStyleOptionFocusRect opt;
00809 opt.init( widget );
00810 opt.rect = rect;
00811 opt.state |= QStyle::State_HasFocus;
00812 opt.backgroundColor = widget->palette().color( widget->backgroundRole() );
00813
00814 widget->style()->drawPrimitive(
00815 QStyle::PE_FrameFocusRect, &opt, painter, widget );
00816 }
00817
00829 void QwtPainter::drawRoundFrame( QPainter *painter,
00830 const QRectF &rect, const QPalette &palette,
00831 int lineWidth, int frameStyle )
00832 {
00833 enum Style
00834 {
00835 Plain,
00836 Sunken,
00837 Raised
00838 };
00839
00840 Style style = Plain;
00841 if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
00842 style = Sunken;
00843 else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
00844 style = Raised;
00845
00846 const double lw2 = 0.5 * lineWidth;
00847 QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
00848
00849 QBrush brush;
00850
00851 if ( style != Plain )
00852 {
00853 QColor c1 = palette.color( QPalette::Light );
00854 QColor c2 = palette.color( QPalette::Dark );
00855
00856 if ( style == Sunken )
00857 qSwap( c1, c2 );
00858
00859 QLinearGradient gradient( r.topLeft(), r.bottomRight() );
00860 gradient.setColorAt( 0.0, c1 );
00861 #if 0
00862 gradient.setColorAt( 0.3, c1 );
00863 gradient.setColorAt( 0.7, c2 );
00864 #endif
00865 gradient.setColorAt( 1.0, c2 );
00866
00867 brush = QBrush( gradient );
00868 }
00869 else
00870 {
00871 brush = palette.brush( QPalette::WindowText );
00872 }
00873
00874 painter->save();
00875
00876 painter->setPen( QPen( brush, lineWidth ) );
00877 painter->setBrush( Qt::NoBrush );
00878
00879 painter->drawEllipse( r );
00880
00881 painter->restore();
00882 }
00883
00895 void QwtPainter::drawFrame( QPainter *painter, const QRectF &rect,
00896 const QPalette &palette, QPalette::ColorRole foregroundRole,
00897 int frameWidth, int midLineWidth, int frameStyle )
00898 {
00899 if ( frameWidth <= 0 || rect.isEmpty() )
00900 return;
00901
00902 const int shadow = frameStyle & QFrame::Shadow_Mask;
00903
00904 painter->save();
00905
00906 if ( shadow == QFrame::Plain )
00907 {
00908 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00909 const QRectF innerRect = outerRect.adjusted(
00910 frameWidth, frameWidth, -frameWidth, -frameWidth );
00911
00912 QPainterPath path;
00913 path.addRect( outerRect );
00914 path.addRect( innerRect );
00915
00916 painter->setPen( Qt::NoPen );
00917 painter->setBrush( palette.color( foregroundRole ) );
00918
00919 painter->drawPath( path );
00920 }
00921 else
00922 {
00923 const int shape = frameStyle & QFrame::Shape_Mask;
00924
00925 if ( shape == QFrame::Box )
00926 {
00927 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00928 const QRectF midRect1 = outerRect.adjusted(
00929 frameWidth, frameWidth, -frameWidth, -frameWidth );
00930 const QRectF midRect2 = midRect1.adjusted(
00931 midLineWidth, midLineWidth, -midLineWidth, -midLineWidth );
00932
00933 const QRectF innerRect = midRect2.adjusted(
00934 frameWidth, frameWidth, -frameWidth, -frameWidth );
00935
00936 QPainterPath path1;
00937 path1.moveTo( outerRect.bottomLeft() );
00938 path1.lineTo( outerRect.topLeft() );
00939 path1.lineTo( outerRect.topRight() );
00940 path1.lineTo( midRect1.topRight() );
00941 path1.lineTo( midRect1.topLeft() );
00942 path1.lineTo( midRect1.bottomLeft() );
00943
00944 QPainterPath path2;
00945 path2.moveTo( outerRect.bottomLeft() );
00946 path2.lineTo( outerRect.bottomRight() );
00947 path2.lineTo( outerRect.topRight() );
00948 path2.lineTo( midRect1.topRight() );
00949 path2.lineTo( midRect1.bottomRight() );
00950 path2.lineTo( midRect1.bottomLeft() );
00951
00952 QPainterPath path3;
00953 path3.moveTo( midRect2.bottomLeft() );
00954 path3.lineTo( midRect2.topLeft() );
00955 path3.lineTo( midRect2.topRight() );
00956 path3.lineTo( innerRect.topRight() );
00957 path3.lineTo( innerRect.topLeft() );
00958 path3.lineTo( innerRect.bottomLeft() );
00959
00960 QPainterPath path4;
00961 path4.moveTo( midRect2.bottomLeft() );
00962 path4.lineTo( midRect2.bottomRight() );
00963 path4.lineTo( midRect2.topRight() );
00964 path4.lineTo( innerRect.topRight() );
00965 path4.lineTo( innerRect.bottomRight() );
00966 path4.lineTo( innerRect.bottomLeft() );
00967
00968 QPainterPath path5;
00969 path5.addRect( midRect1 );
00970 path5.addRect( midRect2 );
00971
00972 painter->setPen( Qt::NoPen );
00973
00974 QBrush brush1 = palette.dark().color();
00975 QBrush brush2 = palette.light().color();
00976
00977 if ( shadow == QFrame::Raised )
00978 qSwap( brush1, brush2 );
00979
00980 painter->setBrush( brush1 );
00981 painter->drawPath( path1 );
00982 painter->drawPath( path4 );
00983
00984 painter->setBrush( brush2 );
00985 painter->drawPath( path2 );
00986 painter->drawPath( path3 );
00987
00988 painter->setBrush( palette.mid() );
00989 painter->drawPath( path5 );
00990 }
00991 #if 0
00992
00993
00994
00995
00996 else if ( shape == QFrame::WinPanel )
00997 {
00998 painter->setRenderHint( QPainter::NonCosmeticDefaultPen, true );
00999 qDrawWinPanel ( painter, rect.toRect(), palette,
01000 frameStyle & QFrame::Sunken );
01001 }
01002 else if ( shape == QFrame::StyledPanel )
01003 {
01004 }
01005 #endif
01006 else
01007 {
01008 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
01009 const QRectF innerRect = outerRect.adjusted(
01010 frameWidth - 1.0, frameWidth - 1.0,
01011 -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) );
01012
01013 QPainterPath path1;
01014 path1.moveTo( outerRect.bottomLeft() );
01015 path1.lineTo( outerRect.topLeft() );
01016 path1.lineTo( outerRect.topRight() );
01017 path1.lineTo( innerRect.topRight() );
01018 path1.lineTo( innerRect.topLeft() );
01019 path1.lineTo( innerRect.bottomLeft() );
01020
01021
01022 QPainterPath path2;
01023 path2.moveTo( outerRect.bottomLeft() );
01024 path2.lineTo( outerRect.bottomRight() );
01025 path2.lineTo( outerRect.topRight() );
01026 path2.lineTo( innerRect.topRight() );
01027 path2.lineTo( innerRect.bottomRight() );
01028 path2.lineTo( innerRect.bottomLeft() );
01029
01030 painter->setPen( Qt::NoPen );
01031
01032 QBrush brush1 = palette.dark().color();
01033 QBrush brush2 = palette.light().color();
01034
01035 if ( shadow == QFrame::Raised )
01036 qSwap( brush1, brush2 );
01037
01038 painter->setBrush( brush1 );
01039 painter->drawPath( path1 );
01040
01041 painter->setBrush( brush2 );
01042 painter->drawPath( path2 );
01043 }
01044
01045 }
01046
01047 painter->restore();
01048 }
01049
01064 void QwtPainter::drawRoundedFrame( QPainter *painter,
01065 const QRectF &rect, double xRadius, double yRadius,
01066 const QPalette &palette, int lineWidth, int frameStyle )
01067 {
01068 painter->save();
01069 painter->setRenderHint( QPainter::Antialiasing, true );
01070 painter->setBrush( Qt::NoBrush );
01071
01072 double lw2 = lineWidth * 0.5;
01073 QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
01074
01075 QPainterPath path;
01076 path.addRoundedRect( r, xRadius, yRadius );
01077
01078 enum Style
01079 {
01080 Plain,
01081 Sunken,
01082 Raised
01083 };
01084
01085 Style style = Plain;
01086 if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
01087 style = Sunken;
01088 else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
01089 style = Raised;
01090
01091 if ( style != Plain && path.elementCount() == 17 )
01092 {
01093
01094 QPainterPath pathList[8];
01095
01096 for ( int i = 0; i < 4; i++ )
01097 {
01098 const int j = i * 4 + 1;
01099
01100 pathList[ 2 * i ].moveTo(
01101 path.elementAt(j - 1).x, path.elementAt( j - 1 ).y
01102 );
01103
01104 pathList[ 2 * i ].cubicTo(
01105 path.elementAt(j + 0).x, path.elementAt(j + 0).y,
01106 path.elementAt(j + 1).x, path.elementAt(j + 1).y,
01107 path.elementAt(j + 2).x, path.elementAt(j + 2).y );
01108
01109 pathList[ 2 * i + 1 ].moveTo(
01110 path.elementAt(j + 2).x, path.elementAt(j + 2).y
01111 );
01112 pathList[ 2 * i + 1 ].lineTo(
01113 path.elementAt(j + 3).x, path.elementAt(j + 3).y
01114 );
01115 }
01116
01117 QColor c1( palette.color( QPalette::Dark ) );
01118 QColor c2( palette.color( QPalette::Light ) );
01119
01120 if ( style == Raised )
01121 qSwap( c1, c2 );
01122
01123 for ( int i = 0; i < 4; i++ )
01124 {
01125 QRectF r = pathList[2 * i].controlPointRect();
01126
01127 QPen arcPen;
01128 arcPen.setCapStyle( Qt::FlatCap );
01129 arcPen.setWidth( lineWidth );
01130
01131 QPen linePen;
01132 linePen.setCapStyle( Qt::FlatCap );
01133 linePen.setWidth( lineWidth );
01134
01135 switch( i )
01136 {
01137 case 0:
01138 {
01139 arcPen.setColor( c1 );
01140 linePen.setColor( c1 );
01141 break;
01142 }
01143 case 1:
01144 {
01145 QLinearGradient gradient;
01146 gradient.setStart( r.topLeft() );
01147 gradient.setFinalStop( r.bottomRight() );
01148 gradient.setColorAt( 0.0, c1 );
01149 gradient.setColorAt( 1.0, c2 );
01150
01151 arcPen.setBrush( gradient );
01152 linePen.setColor( c2 );
01153 break;
01154 }
01155 case 2:
01156 {
01157 arcPen.setColor( c2 );
01158 linePen.setColor( c2 );
01159 break;
01160 }
01161 case 3:
01162 {
01163 QLinearGradient gradient;
01164
01165 gradient.setStart( r.bottomRight() );
01166 gradient.setFinalStop( r.topLeft() );
01167 gradient.setColorAt( 0.0, c2 );
01168 gradient.setColorAt( 1.0, c1 );
01169
01170 arcPen.setBrush( gradient );
01171 linePen.setColor( c1 );
01172 break;
01173 }
01174 }
01175
01176
01177 painter->setPen( arcPen );
01178 painter->drawPath( pathList[ 2 * i] );
01179
01180 painter->setPen( linePen );
01181 painter->drawPath( pathList[ 2 * i + 1] );
01182 }
01183 }
01184 else
01185 {
01186 QPen pen( palette.color( QPalette::WindowText ), lineWidth );
01187 painter->setPen( pen );
01188 painter->drawPath( path );
01189 }
01190
01191 painter->restore();
01192 }
01193
01204 void QwtPainter::drawColorBar( QPainter *painter,
01205 const QwtColorMap &colorMap, const QwtInterval &interval,
01206 const QwtScaleMap &scaleMap, Qt::Orientation orientation,
01207 const QRectF &rect )
01208 {
01209 QVector<QRgb> colorTable;
01210 if ( colorMap.format() == QwtColorMap::Indexed )
01211 colorTable = colorMap.colorTable256();
01212
01213 QColor c;
01214
01215 const QRect devRect = rect.toAlignedRect();
01216
01217
01218
01219
01220
01221
01222 QPixmap pixmap( devRect.size() );
01223 pixmap.fill( Qt::transparent );
01224
01225 QPainter pmPainter( &pixmap );
01226 pmPainter.translate( -devRect.x(), -devRect.y() );
01227
01228 if ( orientation == Qt::Horizontal )
01229 {
01230 QwtScaleMap sMap = scaleMap;
01231 sMap.setPaintInterval( rect.left(), rect.right() );
01232
01233 for ( int x = devRect.left(); x <= devRect.right(); x++ )
01234 {
01235 const double value = sMap.invTransform( x );
01236
01237 if ( colorMap.format() == QwtColorMap::RGB )
01238 c.setRgba( colorMap.rgb( interval, value ) );
01239 else
01240 c = colorTable[colorMap.colorIndex( 256, interval, value )];
01241
01242 pmPainter.setPen( c );
01243 pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() );
01244 }
01245 }
01246 else
01247 {
01248 QwtScaleMap sMap = scaleMap;
01249 sMap.setPaintInterval( rect.bottom(), rect.top() );
01250
01251 for ( int y = devRect.top(); y <= devRect.bottom(); y++ )
01252 {
01253 const double value = sMap.invTransform( y );
01254
01255 if ( colorMap.format() == QwtColorMap::RGB )
01256 c.setRgba( colorMap.rgb( interval, value ) );
01257 else
01258 c = colorTable[colorMap.colorIndex( 256, interval, value )];
01259
01260 pmPainter.setPen( c );
01261 pmPainter.drawLine( devRect.left(), y, devRect.right(), y );
01262 }
01263 }
01264 pmPainter.end();
01265
01266 drawPixmap( painter, rect, pixmap );
01267 }
01268
01269 static inline void qwtFillRect( const QWidget *widget, QPainter *painter,
01270 const QRect &rect, const QBrush &brush)
01271 {
01272 if ( brush.style() == Qt::TexturePattern )
01273 {
01274 painter->save();
01275
01276 painter->setClipRect( rect );
01277 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
01278
01279 painter->restore();
01280 }
01281 else if ( brush.gradient() )
01282 {
01283 painter->save();
01284
01285 painter->setClipRect( rect );
01286 painter->fillRect(0, 0, widget->width(),
01287 widget->height(), brush);
01288
01289 painter->restore();
01290 }
01291 else
01292 {
01293 painter->fillRect(rect, brush);
01294 }
01295 }
01296
01310 void QwtPainter::fillPixmap( const QWidget *widget,
01311 QPixmap &pixmap, const QPoint &offset )
01312 {
01313 const QRect rect( offset, pixmap.size() );
01314
01315 QPainter painter( &pixmap );
01316 painter.translate( -offset );
01317
01318 const QBrush autoFillBrush =
01319 widget->palette().brush( widget->backgroundRole() );
01320
01321 if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) )
01322 {
01323 const QBrush bg = widget->palette().brush( QPalette::Window );
01324 qwtFillRect( widget, &painter, rect, bg);
01325 }
01326
01327 if ( widget->autoFillBackground() )
01328 qwtFillRect( widget, &painter, rect, autoFillBrush);
01329
01330 if ( widget->testAttribute(Qt::WA_StyledBackground) )
01331 {
01332 painter.setClipRegion( rect );
01333
01334 QStyleOption opt;
01335 opt.initFrom( widget );
01336 widget->style()->drawPrimitive( QStyle::PE_Widget,
01337 &opt, &painter, widget );
01338 }
01339 }
01340
01350 void QwtPainter::drawBackgound( QPainter *painter,
01351 const QRectF &rect, const QWidget *widget )
01352 {
01353 if ( widget->testAttribute( Qt::WA_StyledBackground ) )
01354 {
01355 QStyleOption opt;
01356 opt.initFrom( widget );
01357 opt.rect = rect.toAlignedRect();
01358
01359 widget->style()->drawPrimitive(
01360 QStyle::PE_Widget, &opt, painter, widget);
01361 }
01362 else
01363 {
01364 const QBrush brush =
01365 widget->palette().brush( widget->backgroundRole() );
01366
01367 painter->fillRect( rect, brush );
01368 }
01369 }
01370
01375 qreal QwtPainter::devicePixelRatio( const QPaintDevice *paintDevice )
01376 {
01377 qreal pixelRatio = 0.0;
01378
01379 #if QT_VERSION >= 0x050100
01380 if ( paintDevice )
01381 {
01382 #if QT_VERSION >= 0x050600
01383 pixelRatio = paintDevice->devicePixelRatioF();
01384 #else
01385 pixelRatio = paintDevice->devicePixelRatio();
01386 #endif
01387 }
01388 #else
01389 Q_UNUSED( paintDevice )
01390 #endif
01391
01392 #if QT_VERSION >= 0x050000
01393 if ( pixelRatio == 0.0 && qApp )
01394 pixelRatio = qApp->devicePixelRatio();
01395 #endif
01396
01397 if ( pixelRatio == 0.0 )
01398 pixelRatio = 1.0;
01399
01400 return pixelRatio;
01401 }
01402
01409 QPixmap QwtPainter::backingStore( QWidget *widget, const QSize &size )
01410 {
01411 QPixmap pm;
01412
01413 #if QT_VERSION >= 0x050000
01414 const qreal pixelRatio = QwtPainter::devicePixelRatio( widget );
01415
01416 pm = QPixmap( size * pixelRatio );
01417 pm.setDevicePixelRatio( pixelRatio );
01418 #else
01419 pm = QPixmap( size );
01420 #endif
01421
01422 #ifdef Q_WS_X11
01423 if ( widget && isX11GraphicsSystem() )
01424 {
01425 if ( pm.x11Info().screen() != widget->x11Info().screen() )
01426 pm.x11SetScreen( widget->x11Info().screen() );
01427 }
01428 #else
01429 Q_UNUSED( widget )
01430 #endif
01431
01432 return pm;
01433 }
01434