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 QPolygonF cpa = polygon;
00551 if ( deviceClipping )
00552 cpa = QwtClipper::clipPolygonF( clipRect, polygon );
00553
00554 painter->drawPolygon( cpa );
00555 }
00556
00558 void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon )
00559 {
00560 QRectF clipRect;
00561 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00562
00563 QPolygonF cpa = polygon;
00564 if ( deviceClipping )
00565 cpa = QwtClipper::clipPolygonF( clipRect, cpa );
00566
00567 qwtDrawPolyline<QPointF>( painter,
00568 cpa.constData(), cpa.size(), d_polylineSplitting );
00569 }
00570
00572 void QwtPainter::drawPolyline( QPainter *painter,
00573 const QPointF *points, int pointCount )
00574 {
00575 QRectF clipRect;
00576 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00577
00578 if ( deviceClipping )
00579 {
00580 QPolygonF polygon( pointCount );
00581 ::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) );
00582
00583 polygon = QwtClipper::clipPolygonF( clipRect, polygon );
00584 qwtDrawPolyline<QPointF>( painter,
00585 polygon.constData(), polygon.size(), d_polylineSplitting );
00586 }
00587 else
00588 {
00589 qwtDrawPolyline<QPointF>( painter, points, pointCount, d_polylineSplitting );
00590 }
00591 }
00592
00594 void QwtPainter::drawPolygon( QPainter *painter, const QPolygon &polygon )
00595 {
00596 QRectF clipRect;
00597 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00598
00599 QPolygon cpa = polygon;
00600 if ( deviceClipping )
00601 cpa = QwtClipper::clipPolygon( clipRect, polygon );
00602
00603 painter->drawPolygon( cpa );
00604 }
00605
00607 void QwtPainter::drawPolyline( QPainter *painter, const QPolygon &polygon )
00608 {
00609 QRectF clipRect;
00610 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00611
00612 QPolygon cpa = polygon;
00613 if ( deviceClipping )
00614 cpa = QwtClipper::clipPolygon( clipRect, cpa );
00615
00616 qwtDrawPolyline<QPoint>( painter,
00617 cpa.constData(), cpa.size(), d_polylineSplitting );
00618 }
00619
00621 void QwtPainter::drawPolyline( QPainter *painter,
00622 const QPoint *points, int pointCount )
00623 {
00624 QRectF clipRect;
00625 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00626
00627 if ( deviceClipping )
00628 {
00629 QPolygon polygon( pointCount );
00630 ::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) );
00631
00632 polygon = QwtClipper::clipPolygon( clipRect, polygon );
00633 qwtDrawPolyline<QPoint>( painter,
00634 polygon.constData(), polygon.size(), d_polylineSplitting );
00635 }
00636 else
00637 qwtDrawPolyline<QPoint>( painter, points, pointCount, d_polylineSplitting );
00638 }
00639
00641 void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos )
00642 {
00643 QRectF clipRect;
00644 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00645
00646 if ( deviceClipping && !clipRect.contains( pos ) )
00647 return;
00648
00649 painter->drawPoint( pos );
00650 }
00651
00653 void QwtPainter::drawPoint( QPainter *painter, const QPoint &pos )
00654 {
00655 QRectF clipRect;
00656 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00657
00658 if ( deviceClipping )
00659 {
00660 const int minX = qCeil( clipRect.left() );
00661 const int maxX = qFloor( clipRect.right() );
00662 const int minY = qCeil( clipRect.top() );
00663 const int maxY = qFloor( clipRect.bottom() );
00664
00665 if ( pos.x() < minX || pos.x() > maxX
00666 || pos.y() < minY || pos.y() > maxY )
00667 {
00668 return;
00669 }
00670 }
00671
00672 painter->drawPoint( pos );
00673 }
00674
00676 void QwtPainter::drawPoints( QPainter *painter,
00677 const QPoint *points, int pointCount )
00678 {
00679 QRectF clipRect;
00680 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00681
00682 if ( deviceClipping )
00683 {
00684 const int minX = qCeil( clipRect.left() );
00685 const int maxX = qFloor( clipRect.right() );
00686 const int minY = qCeil( clipRect.top() );
00687 const int maxY = qFloor( clipRect.bottom() );
00688
00689 const QRect r( minX, minY, maxX - minX, maxY - minY );
00690
00691 QPolygon clippedPolygon( pointCount );
00692 QPoint *clippedData = clippedPolygon.data();
00693
00694 int numClippedPoints = 0;
00695 for ( int i = 0; i < pointCount; i++ )
00696 {
00697 if ( r.contains( points[i] ) )
00698 clippedData[ numClippedPoints++ ] = points[i];
00699 }
00700 painter->drawPoints( clippedData, numClippedPoints );
00701 }
00702 else
00703 {
00704 painter->drawPoints( points, pointCount );
00705 }
00706 }
00707
00709 void QwtPainter::drawPoints( QPainter *painter,
00710 const QPointF *points, int pointCount )
00711 {
00712 QRectF clipRect;
00713 const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
00714
00715 if ( deviceClipping )
00716 {
00717 QPolygonF clippedPolygon( pointCount );
00718 QPointF *clippedData = clippedPolygon.data();
00719
00720 int numClippedPoints = 0;
00721 for ( int i = 0; i < pointCount; i++ )
00722 {
00723 if ( clipRect.contains( points[i] ) )
00724 clippedData[ numClippedPoints++ ] = points[i];
00725 }
00726 painter->drawPoints( clippedData, numClippedPoints );
00727 }
00728 else
00729 {
00730 painter->drawPoints( points, pointCount );
00731 }
00732 }
00733
00735 void QwtPainter::drawImage( QPainter *painter,
00736 const QRectF &rect, const QImage &image )
00737 {
00738 const QRect alignedRect = rect.toAlignedRect();
00739
00740 if ( alignedRect != rect )
00741 {
00742 const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00743
00744 painter->save();
00745 painter->setClipRect( clipRect, Qt::IntersectClip );
00746 painter->drawImage( alignedRect, image );
00747 painter->restore();
00748 }
00749 else
00750 {
00751 painter->drawImage( alignedRect, image );
00752 }
00753 }
00754
00756 void QwtPainter::drawPixmap( QPainter *painter,
00757 const QRectF &rect, const QPixmap &pixmap )
00758 {
00759 const QRect alignedRect = rect.toAlignedRect();
00760
00761 if ( alignedRect != rect )
00762 {
00763 const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00764
00765 painter->save();
00766 painter->setClipRect( clipRect, Qt::IntersectClip );
00767 painter->drawPixmap( alignedRect, pixmap );
00768 painter->restore();
00769 }
00770 else
00771 {
00772 painter->drawPixmap( alignedRect, pixmap );
00773 }
00774 }
00775
00777 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget )
00778 {
00779 drawFocusRect( painter, widget, widget->rect() );
00780 }
00781
00783 void QwtPainter::drawFocusRect( QPainter *painter, const QWidget *widget,
00784 const QRect &rect )
00785 {
00786 QStyleOptionFocusRect opt;
00787 opt.init( widget );
00788 opt.rect = rect;
00789 opt.state |= QStyle::State_HasFocus;
00790 opt.backgroundColor = widget->palette().color( widget->backgroundRole() );
00791
00792 widget->style()->drawPrimitive(
00793 QStyle::PE_FrameFocusRect, &opt, painter, widget );
00794 }
00795
00807 void QwtPainter::drawRoundFrame( QPainter *painter,
00808 const QRectF &rect, const QPalette &palette,
00809 int lineWidth, int frameStyle )
00810 {
00811 enum Style
00812 {
00813 Plain,
00814 Sunken,
00815 Raised
00816 };
00817
00818 Style style = Plain;
00819 if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
00820 style = Sunken;
00821 else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
00822 style = Raised;
00823
00824 const double lw2 = 0.5 * lineWidth;
00825 QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
00826
00827 QBrush brush;
00828
00829 if ( style != Plain )
00830 {
00831 QColor c1 = palette.color( QPalette::Light );
00832 QColor c2 = palette.color( QPalette::Dark );
00833
00834 if ( style == Sunken )
00835 qSwap( c1, c2 );
00836
00837 QLinearGradient gradient( r.topLeft(), r.bottomRight() );
00838 gradient.setColorAt( 0.0, c1 );
00839 #if 0
00840 gradient.setColorAt( 0.3, c1 );
00841 gradient.setColorAt( 0.7, c2 );
00842 #endif
00843 gradient.setColorAt( 1.0, c2 );
00844
00845 brush = QBrush( gradient );
00846 }
00847 else
00848 {
00849 brush = palette.brush( QPalette::WindowText );
00850 }
00851
00852 painter->save();
00853
00854 painter->setPen( QPen( brush, lineWidth ) );
00855 painter->setBrush( Qt::NoBrush );
00856
00857 painter->drawEllipse( r );
00858
00859 painter->restore();
00860 }
00861
00873 void QwtPainter::drawFrame( QPainter *painter, const QRectF &rect,
00874 const QPalette &palette, QPalette::ColorRole foregroundRole,
00875 int frameWidth, int midLineWidth, int frameStyle )
00876 {
00877 if ( frameWidth <= 0 || rect.isEmpty() )
00878 return;
00879
00880 const int shadow = frameStyle & QFrame::Shadow_Mask;
00881
00882 painter->save();
00883
00884 if ( shadow == QFrame::Plain )
00885 {
00886 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00887 const QRectF innerRect = outerRect.adjusted(
00888 frameWidth, frameWidth, -frameWidth, -frameWidth );
00889
00890 QPainterPath path;
00891 path.addRect( outerRect );
00892 path.addRect( innerRect );
00893
00894 painter->setPen( Qt::NoPen );
00895 painter->setBrush( palette.color( foregroundRole ) );
00896
00897 painter->drawPath( path );
00898 }
00899 else
00900 {
00901 const int shape = frameStyle & QFrame::Shape_Mask;
00902
00903 if ( shape == QFrame::Box )
00904 {
00905 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00906 const QRectF midRect1 = outerRect.adjusted(
00907 frameWidth, frameWidth, -frameWidth, -frameWidth );
00908 const QRectF midRect2 = midRect1.adjusted(
00909 midLineWidth, midLineWidth, -midLineWidth, -midLineWidth );
00910
00911 const QRectF innerRect = midRect2.adjusted(
00912 frameWidth, frameWidth, -frameWidth, -frameWidth );
00913
00914 QPainterPath path1;
00915 path1.moveTo( outerRect.bottomLeft() );
00916 path1.lineTo( outerRect.topLeft() );
00917 path1.lineTo( outerRect.topRight() );
00918 path1.lineTo( midRect1.topRight() );
00919 path1.lineTo( midRect1.topLeft() );
00920 path1.lineTo( midRect1.bottomLeft() );
00921
00922 QPainterPath path2;
00923 path2.moveTo( outerRect.bottomLeft() );
00924 path2.lineTo( outerRect.bottomRight() );
00925 path2.lineTo( outerRect.topRight() );
00926 path2.lineTo( midRect1.topRight() );
00927 path2.lineTo( midRect1.bottomRight() );
00928 path2.lineTo( midRect1.bottomLeft() );
00929
00930 QPainterPath path3;
00931 path3.moveTo( midRect2.bottomLeft() );
00932 path3.lineTo( midRect2.topLeft() );
00933 path3.lineTo( midRect2.topRight() );
00934 path3.lineTo( innerRect.topRight() );
00935 path3.lineTo( innerRect.topLeft() );
00936 path3.lineTo( innerRect.bottomLeft() );
00937
00938 QPainterPath path4;
00939 path4.moveTo( midRect2.bottomLeft() );
00940 path4.lineTo( midRect2.bottomRight() );
00941 path4.lineTo( midRect2.topRight() );
00942 path4.lineTo( innerRect.topRight() );
00943 path4.lineTo( innerRect.bottomRight() );
00944 path4.lineTo( innerRect.bottomLeft() );
00945
00946 QPainterPath path5;
00947 path5.addRect( midRect1 );
00948 path5.addRect( midRect2 );
00949
00950 painter->setPen( Qt::NoPen );
00951
00952 QBrush brush1 = palette.dark().color();
00953 QBrush brush2 = palette.light().color();
00954
00955 if ( shadow == QFrame::Raised )
00956 qSwap( brush1, brush2 );
00957
00958 painter->setBrush( brush1 );
00959 painter->drawPath( path1 );
00960 painter->drawPath( path4 );
00961
00962 painter->setBrush( brush2 );
00963 painter->drawPath( path2 );
00964 painter->drawPath( path3 );
00965
00966 painter->setBrush( palette.mid() );
00967 painter->drawPath( path5 );
00968 }
00969 #if 0
00970
00971
00972
00973
00974 else if ( shape == QFrame::WinPanel )
00975 {
00976 painter->setRenderHint( QPainter::NonCosmeticDefaultPen, true );
00977 qDrawWinPanel ( painter, rect.toRect(), palette,
00978 frameStyle & QFrame::Sunken );
00979 }
00980 else if ( shape == QFrame::StyledPanel )
00981 {
00982 }
00983 #endif
00984 else
00985 {
00986 const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
00987 const QRectF innerRect = outerRect.adjusted(
00988 frameWidth - 1.0, frameWidth - 1.0,
00989 -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) );
00990
00991 QPainterPath path1;
00992 path1.moveTo( outerRect.bottomLeft() );
00993 path1.lineTo( outerRect.topLeft() );
00994 path1.lineTo( outerRect.topRight() );
00995 path1.lineTo( innerRect.topRight() );
00996 path1.lineTo( innerRect.topLeft() );
00997 path1.lineTo( innerRect.bottomLeft() );
00998
00999
01000 QPainterPath path2;
01001 path2.moveTo( outerRect.bottomLeft() );
01002 path2.lineTo( outerRect.bottomRight() );
01003 path2.lineTo( outerRect.topRight() );
01004 path2.lineTo( innerRect.topRight() );
01005 path2.lineTo( innerRect.bottomRight() );
01006 path2.lineTo( innerRect.bottomLeft() );
01007
01008 painter->setPen( Qt::NoPen );
01009
01010 QBrush brush1 = palette.dark().color();
01011 QBrush brush2 = palette.light().color();
01012
01013 if ( shadow == QFrame::Raised )
01014 qSwap( brush1, brush2 );
01015
01016 painter->setBrush( brush1 );
01017 painter->drawPath( path1 );
01018
01019 painter->setBrush( brush2 );
01020 painter->drawPath( path2 );
01021 }
01022
01023 }
01024
01025 painter->restore();
01026 }
01027
01042 void QwtPainter::drawRoundedFrame( QPainter *painter,
01043 const QRectF &rect, double xRadius, double yRadius,
01044 const QPalette &palette, int lineWidth, int frameStyle )
01045 {
01046 painter->save();
01047 painter->setRenderHint( QPainter::Antialiasing, true );
01048 painter->setBrush( Qt::NoBrush );
01049
01050 double lw2 = lineWidth * 0.5;
01051 QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
01052
01053 QPainterPath path;
01054 path.addRoundedRect( r, xRadius, yRadius );
01055
01056 enum Style
01057 {
01058 Plain,
01059 Sunken,
01060 Raised
01061 };
01062
01063 Style style = Plain;
01064 if ( (frameStyle & QFrame::Sunken) == QFrame::Sunken )
01065 style = Sunken;
01066 else if ( (frameStyle & QFrame::Raised) == QFrame::Raised )
01067 style = Raised;
01068
01069 if ( style != Plain && path.elementCount() == 17 )
01070 {
01071
01072 QPainterPath pathList[8];
01073
01074 for ( int i = 0; i < 4; i++ )
01075 {
01076 const int j = i * 4 + 1;
01077
01078 pathList[ 2 * i ].moveTo(
01079 path.elementAt(j - 1).x, path.elementAt( j - 1 ).y
01080 );
01081
01082 pathList[ 2 * i ].cubicTo(
01083 path.elementAt(j + 0).x, path.elementAt(j + 0).y,
01084 path.elementAt(j + 1).x, path.elementAt(j + 1).y,
01085 path.elementAt(j + 2).x, path.elementAt(j + 2).y );
01086
01087 pathList[ 2 * i + 1 ].moveTo(
01088 path.elementAt(j + 2).x, path.elementAt(j + 2).y
01089 );
01090 pathList[ 2 * i + 1 ].lineTo(
01091 path.elementAt(j + 3).x, path.elementAt(j + 3).y
01092 );
01093 }
01094
01095 QColor c1( palette.color( QPalette::Dark ) );
01096 QColor c2( palette.color( QPalette::Light ) );
01097
01098 if ( style == Raised )
01099 qSwap( c1, c2 );
01100
01101 for ( int i = 0; i < 4; i++ )
01102 {
01103 QRectF r = pathList[2 * i].controlPointRect();
01104
01105 QPen arcPen;
01106 arcPen.setCapStyle( Qt::FlatCap );
01107 arcPen.setWidth( lineWidth );
01108
01109 QPen linePen;
01110 linePen.setCapStyle( Qt::FlatCap );
01111 linePen.setWidth( lineWidth );
01112
01113 switch( i )
01114 {
01115 case 0:
01116 {
01117 arcPen.setColor( c1 );
01118 linePen.setColor( c1 );
01119 break;
01120 }
01121 case 1:
01122 {
01123 QLinearGradient gradient;
01124 gradient.setStart( r.topLeft() );
01125 gradient.setFinalStop( r.bottomRight() );
01126 gradient.setColorAt( 0.0, c1 );
01127 gradient.setColorAt( 1.0, c2 );
01128
01129 arcPen.setBrush( gradient );
01130 linePen.setColor( c2 );
01131 break;
01132 }
01133 case 2:
01134 {
01135 arcPen.setColor( c2 );
01136 linePen.setColor( c2 );
01137 break;
01138 }
01139 case 3:
01140 {
01141 QLinearGradient gradient;
01142
01143 gradient.setStart( r.bottomRight() );
01144 gradient.setFinalStop( r.topLeft() );
01145 gradient.setColorAt( 0.0, c2 );
01146 gradient.setColorAt( 1.0, c1 );
01147
01148 arcPen.setBrush( gradient );
01149 linePen.setColor( c1 );
01150 break;
01151 }
01152 }
01153
01154
01155 painter->setPen( arcPen );
01156 painter->drawPath( pathList[ 2 * i] );
01157
01158 painter->setPen( linePen );
01159 painter->drawPath( pathList[ 2 * i + 1] );
01160 }
01161 }
01162 else
01163 {
01164 QPen pen( palette.color( QPalette::WindowText ), lineWidth );
01165 painter->setPen( pen );
01166 painter->drawPath( path );
01167 }
01168
01169 painter->restore();
01170 }
01171
01182 void QwtPainter::drawColorBar( QPainter *painter,
01183 const QwtColorMap &colorMap, const QwtInterval &interval,
01184 const QwtScaleMap &scaleMap, Qt::Orientation orientation,
01185 const QRectF &rect )
01186 {
01187 QVector<QRgb> colorTable;
01188 if ( colorMap.format() == QwtColorMap::Indexed )
01189 colorTable = colorMap.colorTable256();
01190
01191 QColor c;
01192
01193 const QRect devRect = rect.toAlignedRect();
01194
01195
01196
01197
01198
01199
01200 QPixmap pixmap( devRect.size() );
01201 pixmap.fill( Qt::transparent );
01202
01203 QPainter pmPainter( &pixmap );
01204 pmPainter.translate( -devRect.x(), -devRect.y() );
01205
01206 if ( orientation == Qt::Horizontal )
01207 {
01208 QwtScaleMap sMap = scaleMap;
01209 sMap.setPaintInterval( rect.left(), rect.right() );
01210
01211 for ( int x = devRect.left(); x <= devRect.right(); x++ )
01212 {
01213 const double value = sMap.invTransform( x );
01214
01215 if ( colorMap.format() == QwtColorMap::RGB )
01216 c.setRgba( colorMap.rgb( interval, value ) );
01217 else
01218 c = colorTable[colorMap.colorIndex( 256, interval, value )];
01219
01220 pmPainter.setPen( c );
01221 pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() );
01222 }
01223 }
01224 else
01225 {
01226 QwtScaleMap sMap = scaleMap;
01227 sMap.setPaintInterval( rect.bottom(), rect.top() );
01228
01229 for ( int y = devRect.top(); y <= devRect.bottom(); y++ )
01230 {
01231 const double value = sMap.invTransform( y );
01232
01233 if ( colorMap.format() == QwtColorMap::RGB )
01234 c.setRgba( colorMap.rgb( interval, value ) );
01235 else
01236 c = colorTable[colorMap.colorIndex( 256, interval, value )];
01237
01238 pmPainter.setPen( c );
01239 pmPainter.drawLine( devRect.left(), y, devRect.right(), y );
01240 }
01241 }
01242 pmPainter.end();
01243
01244 drawPixmap( painter, rect, pixmap );
01245 }
01246
01247 static inline void qwtFillRect( const QWidget *widget, QPainter *painter,
01248 const QRect &rect, const QBrush &brush)
01249 {
01250 if ( brush.style() == Qt::TexturePattern )
01251 {
01252 painter->save();
01253
01254 painter->setClipRect( rect );
01255 painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
01256
01257 painter->restore();
01258 }
01259 else if ( brush.gradient() )
01260 {
01261 painter->save();
01262
01263 painter->setClipRect( rect );
01264 painter->fillRect(0, 0, widget->width(),
01265 widget->height(), brush);
01266
01267 painter->restore();
01268 }
01269 else
01270 {
01271 painter->fillRect(rect, brush);
01272 }
01273 }
01274
01288 void QwtPainter::fillPixmap( const QWidget *widget,
01289 QPixmap &pixmap, const QPoint &offset )
01290 {
01291 const QRect rect( offset, pixmap.size() );
01292
01293 QPainter painter( &pixmap );
01294 painter.translate( -offset );
01295
01296 const QBrush autoFillBrush =
01297 widget->palette().brush( widget->backgroundRole() );
01298
01299 if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) )
01300 {
01301 const QBrush bg = widget->palette().brush( QPalette::Window );
01302 qwtFillRect( widget, &painter, rect, bg);
01303 }
01304
01305 if ( widget->autoFillBackground() )
01306 qwtFillRect( widget, &painter, rect, autoFillBrush);
01307
01308 if ( widget->testAttribute(Qt::WA_StyledBackground) )
01309 {
01310 painter.setClipRegion( rect );
01311
01312 QStyleOption opt;
01313 opt.initFrom( widget );
01314 widget->style()->drawPrimitive( QStyle::PE_Widget,
01315 &opt, &painter, widget );
01316 }
01317 }
01318
01328 void QwtPainter::drawBackgound( QPainter *painter,
01329 const QRectF &rect, const QWidget *widget )
01330 {
01331 if ( widget->testAttribute( Qt::WA_StyledBackground ) )
01332 {
01333 QStyleOption opt;
01334 opt.initFrom( widget );
01335 opt.rect = rect.toAlignedRect();
01336
01337 widget->style()->drawPrimitive(
01338 QStyle::PE_Widget, &opt, painter, widget);
01339 }
01340 else
01341 {
01342 const QBrush brush =
01343 widget->palette().brush( widget->backgroundRole() );
01344
01345 painter->fillRect( rect, brush );
01346 }
01347 }
01348
01353 qreal QwtPainter::devicePixelRatio( const QPaintDevice *paintDevice )
01354 {
01355 qreal pixelRatio = 0.0;
01356
01357 #if QT_VERSION >= 0x050100
01358 if ( paintDevice )
01359 {
01360 #if QT_VERSION >= 0x050600
01361 pixelRatio = paintDevice->devicePixelRatioF();
01362 #else
01363 pixelRatio = paintDevice->devicePixelRatio();
01364 #endif
01365 }
01366 #else
01367 Q_UNUSED( paintDevice )
01368 #endif
01369
01370 #if QT_VERSION >= 0x050000
01371 if ( pixelRatio == 0.0 && qApp )
01372 pixelRatio = qApp->devicePixelRatio();
01373 #endif
01374
01375 if ( pixelRatio == 0.0 )
01376 pixelRatio = 1.0;
01377
01378 return pixelRatio;
01379 }
01380
01387 QPixmap QwtPainter::backingStore( QWidget *widget, const QSize &size )
01388 {
01389 QPixmap pm;
01390
01391 #if QT_VERSION >= 0x050000
01392 const qreal pixelRatio = QwtPainter::devicePixelRatio( widget );
01393
01394 pm = QPixmap( size * pixelRatio );
01395 pm.setDevicePixelRatio( pixelRatio );
01396 #else
01397 pm = QPixmap( size );
01398 #endif
01399
01400 #ifdef Q_WS_X11
01401 if ( widget && isX11GraphicsSystem() )
01402 {
01403 if ( pm.x11Info().screen() != widget->x11Info().screen() )
01404 pm.x11SetScreen( widget->x11Info().screen() );
01405 }
01406 #else
01407 Q_UNUSED( widget )
01408 #endif
01409
01410 return pm;
01411 }
01412