| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 | 
							- /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
 
-  * Qwt Widget Library
 
-  * Copyright (C) 1997   Josef Wilgen
 
-  * Copyright (C) 2002   Uwe Rathmann
 
-  *
 
-  * This library is free software; you can redistribute it and/or
 
-  * modify it under the terms of the Qwt License, Version 1.0
 
-  *****************************************************************************/
 
- #include "qwt_painter.h"
 
- #include "qwt_math.h"
 
- #include "qwt_clipper.h"
 
- #include "qwt_color_map.h"
 
- #include "qwt_scale_map.h"
 
- #include <qwindowdefs.h>
 
- #include <qwidget.h>
 
- #include <qrect.h>
 
- #include <qpainter.h>
 
- #include <qpalette.h>
 
- #include <qpaintdevice.h>
 
- #include <qpixmap.h>
 
- #include <qstyle.h>
 
- #include <qtextdocument.h>
 
- #include <qabstracttextdocumentlayout.h>
 
- #include <qstyleoption.h>
 
- #include <qpaintengine.h>
 
- #include <qapplication.h>
 
- #include <qdesktopwidget.h>
 
- bool QwtPainter::d_polylineSplitting = true;
 
- bool QwtPainter::d_roundingAlignment = true;
 
- static inline bool isClippingNeeded( const QPainter *painter, QRectF &clipRect )
 
- {
 
-     bool doClipping = false;
 
-     const QPaintEngine *pe = painter->paintEngine();
 
-     if ( pe && pe->type() == QPaintEngine::SVG )
 
-     {
 
-         // The SVG paint engine ignores any clipping,
 
-         if ( painter->hasClipping() )
 
-         {
 
-             doClipping = true;
 
-             clipRect = painter->clipRegion().boundingRect();
 
-         }
 
-     }
 
-     return doClipping;
 
- }
 
- static inline void drawPolyline( QPainter *painter,
 
-     const QPointF *points, int pointCount, bool polylineSplitting )
 
- {
 
-     bool doSplit = false;
 
-     if ( polylineSplitting )
 
-     {
 
-         const QPaintEngine *pe = painter->paintEngine();
 
-         if ( pe && pe->type() == QPaintEngine::Raster )
 
-         {
 
-             /*
 
-                 The raster paint engine seems to use some algo with O(n*n).
 
-                 ( Qt 4.3 is better than Qt 4.2, but remains unacceptable)
 
-                 To work around this problem, we have to split the polygon into
 
-                 smaller pieces.
 
-              */
 
-             doSplit = true;
 
-         }
 
-     }
 
-     if ( doSplit )
 
-     {
 
-         const int splitSize = 20;
 
-         for ( int i = 0; i < pointCount; i += splitSize )
 
-         {
 
-             const int n = qMin( splitSize + 1, pointCount - i );
 
-             painter->drawPolyline( points + i, n );
 
-         }
 
-     }
 
-     else
 
-         painter->drawPolyline( points, pointCount );
 
- }
 
- static inline void unscaleFont( QPainter *painter )
 
- {
 
-     if ( painter->font().pixelSize() >= 0 )
 
-         return;
 
-     static QSize screenResolution;
 
-     if ( !screenResolution.isValid() )
 
-     {
 
-         QDesktopWidget *desktop = QApplication::desktop();
 
-         if ( desktop )
 
-         {
 
-             screenResolution.setWidth( desktop->logicalDpiX() );
 
-             screenResolution.setHeight( desktop->logicalDpiY() );
 
-         }
 
-     }
 
-     const QPaintDevice *pd = painter->device();
 
-     if ( pd->logicalDpiX() != screenResolution.width() ||
 
-         pd->logicalDpiY() != screenResolution.height() )
 
-     {
 
-         QFont pixelFont( painter->font(), QApplication::desktop() );
 
-         pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() );
 
-         painter->setFont( pixelFont );
 
-     }
 
- }
 
- /*!
 
-   Check if the painter is using a paint engine, that aligns
 
-   coordinates to integers. Today these are all paint engines
 
-   beside QPaintEngine::Pdf and QPaintEngine::SVG.
 
-   \param  painter Painter
 
-   \return true, when the paint engine is aligning
 
-   \sa setRoundingAlignment()
 
- */
 
- bool QwtPainter::isAligning( QPainter *painter )
 
- {
 
-     if ( painter && painter->isActive() )
 
-     {
 
-         switch ( painter->paintEngine()->type() )
 
-         {
 
-             case QPaintEngine::Pdf:
 
-             case QPaintEngine::SVG:
 
-                 return false;
 
-             default:;
 
-         }
 
-     }
 
-     return true;
 
- }
 
- /*!
 
-   Enable whether coordinates should be rounded, before they are painted
 
-   to a paint engine that floors to integer values. For other paint engines
 
-   this ( Pdf, SVG ), this flag has no effect.
 
-   QwtPainter stores this flag only, the rounding itsself is done in 
 
-   the painting code ( f.e the plot items ).
 
-   The default setting is true. 
 
-   \sa roundingAlignment(), isAligning()
 
- */
 
- void QwtPainter::setRoundingAlignment( bool enable )
 
- {
 
-     d_roundingAlignment = enable;
 
- }
 
- /*!
 
-   \brief En/Disable line splitting for the raster paint engine
 
-   The raster paint engine paints polylines of many points
 
-   much faster when they are splitted in smaller chunks.
 
-   \sa polylineSplitting()
 
- */
 
- void QwtPainter::setPolylineSplitting( bool enable )
 
- {
 
-     d_polylineSplitting = enable;
 
- }
 
- //! Wrapper for QPainter::drawRect()
 
- void QwtPainter::drawRect( QPainter *painter, double x, double y, double w, double h )
 
- {
 
-     drawRect( painter, QRectF( x, y, w, h ) );
 
- }
 
- //! Wrapper for QPainter::drawRect()
 
- void QwtPainter::drawRect( QPainter *painter, const QRectF &rect )
 
- {
 
-     const QRectF r = rect;
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping )
 
-     {
 
-         if ( !clipRect.intersects( r ) )
 
-             return;
 
-         if ( !clipRect.contains( r ) )
 
-         {
 
-             fillRect( painter, r & clipRect, painter->brush() );
 
-             painter->save();
 
-             painter->setBrush( Qt::NoBrush );
 
-             drawPolyline( painter, QPolygonF( r ) );
 
-             painter->restore();
 
-             return;
 
-         }
 
-     }
 
-     painter->drawRect( r );
 
- }
 
- //! Wrapper for QPainter::fillRect()
 
- void QwtPainter::fillRect( QPainter *painter,
 
-     const QRectF &rect, const QBrush &brush )
 
- {
 
-     if ( !rect.isValid() )
 
-         return;
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     /*
 
-       Performance of Qt4 is horrible for non trivial brushs. Without
 
-       clipping expect minutes or hours for repainting large rects
 
-       (might result from zooming)
 
-     */
 
-     if ( deviceClipping )
 
-         clipRect &= painter->window();
 
-     else
 
-         clipRect = painter->window();
 
-     if ( painter->hasClipping() )
 
-         clipRect &= painter->clipRegion().boundingRect();
 
-     QRectF r = rect;
 
-     if ( deviceClipping )
 
-         r = r.intersect( clipRect );
 
-     if ( r.isValid() )
 
-         painter->fillRect( r, brush );
 
- }
 
- //! Wrapper for QPainter::drawPie()
 
- void QwtPainter::drawPie( QPainter *painter, const QRectF &rect,
 
-     int a, int alen )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping && !clipRect.contains( rect ) )
 
-         return;
 
-     painter->drawPie( rect, a, alen );
 
- }
 
- //! Wrapper for QPainter::drawEllipse()
 
- void QwtPainter::drawEllipse( QPainter *painter, const QRectF &rect )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping && !clipRect.contains( rect ) )
 
-         return;
 
-     painter->drawEllipse( rect );
 
- }
 
- //! Wrapper for QPainter::drawText()
 
- void QwtPainter::drawText( QPainter *painter, double x, double y,
 
-         const QString &text )
 
- {
 
-     drawText( painter, QPointF( x, y ), text );
 
- }
 
- //! Wrapper for QPainter::drawText()
 
- void QwtPainter::drawText( QPainter *painter, const QPointF &pos,
 
-         const QString &text )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping && !clipRect.contains( pos ) )
 
-         return;
 
-     painter->save();
 
-     unscaleFont( painter );
 
-     painter->drawText( pos, text );
 
-     painter->restore();
 
- }
 
- //! Wrapper for QPainter::drawText()
 
- void QwtPainter::drawText( QPainter *painter,
 
-     double x, double y, double w, double h,
 
-     int flags, const QString &text )
 
- {
 
-     drawText( painter, QRectF( x, y, w, h ), flags, text );
 
- }
 
- //! Wrapper for QPainter::drawText()
 
- void QwtPainter::drawText( QPainter *painter, const QRectF &rect,
 
-         int flags, const QString &text )
 
- {
 
-     painter->save();
 
-     unscaleFont( painter );
 
-     painter->drawText( rect, flags, text );
 
-     painter->restore();
 
- }
 
- #ifndef QT_NO_RICHTEXT
 
- /*!
 
-   Draw a text document into a rectangle
 
-   \param painter Painter
 
-   \param rect Traget rectangle
 
-   \param flags Alignments/Text flags, see QPainter::drawText()
 
-   \param text Text document
 
- */
 
- void QwtPainter::drawSimpleRichText( QPainter *painter, const QRectF &rect,
 
-     int flags, const QTextDocument &text )
 
- {
 
-     QTextDocument *txt = text.clone();
 
-     painter->save();
 
-     painter->setFont( txt->defaultFont() );
 
-     unscaleFont( painter );
 
-     txt->setDefaultFont( painter->font() );
 
-     txt->setPageSize( QSizeF( rect.width(), QWIDGETSIZE_MAX ) );
 
-     QAbstractTextDocumentLayout* layout = txt->documentLayout();
 
-     const double height = layout->documentSize().height();
 
-     double y = rect.y();
 
-     if ( flags & Qt::AlignBottom )
 
-         y += ( rect.height() - height );
 
-     else if ( flags & Qt::AlignVCenter )
 
-         y += ( rect.height() - height ) / 2;
 
-     QAbstractTextDocumentLayout::PaintContext context;
 
-     context.palette.setColor( QPalette::Text, painter->pen().color() );
 
-     painter->translate( rect.x(), y );
 
-     layout->draw( painter, context );
 
-     painter->restore();
 
-     delete txt;
 
- }
 
- #endif // !QT_NO_RICHTEXT
 
- //! Wrapper for QPainter::drawLine()
 
- void QwtPainter::drawLine( QPainter *painter,
 
-     const QPointF &p1, const QPointF &p2 )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping &&
 
-         !( clipRect.contains( p1 ) && clipRect.contains( p2 ) ) )
 
-     {
 
-         QPolygonF polygon;
 
-         polygon += p1;
 
-         polygon += p2;
 
-         drawPolyline( painter, polygon );
 
-         return;
 
-     }
 
-     painter->drawLine( p1, p2 );
 
- }
 
- //! Wrapper for QPainter::drawPolygon()
 
- void QwtPainter::drawPolygon( QPainter *painter, const QPolygonF &polygon )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     QPolygonF cpa = polygon;
 
-     if ( deviceClipping )
 
-         cpa = QwtClipper::clipPolygonF( clipRect, polygon );
 
-     painter->drawPolygon( cpa );
 
- }
 
- //! Wrapper for QPainter::drawPolyline()
 
- void QwtPainter::drawPolyline( QPainter *painter, const QPolygonF &polygon )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     QPolygonF cpa = polygon;
 
-     if ( deviceClipping )
 
-         cpa = QwtClipper::clipPolygonF( clipRect, cpa );
 
-     ::drawPolyline( painter,
 
-         cpa.constData(), cpa.size(), d_polylineSplitting );
 
- }
 
- //! Wrapper for QPainter::drawPolyline()
 
- void QwtPainter::drawPolyline( QPainter *painter,
 
-     const QPointF *points, int pointCount )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping )
 
-     {
 
-         QPolygonF polygon( pointCount );
 
-         qMemCopy( polygon.data(), points, pointCount * sizeof( QPointF ) );
 
-         polygon = QwtClipper::clipPolygonF( clipRect, polygon );
 
-         ::drawPolyline( painter,
 
-             polygon.constData(), polygon.size(), d_polylineSplitting );
 
-     }
 
-     else
 
-         ::drawPolyline( painter, points, pointCount, d_polylineSplitting );
 
- }
 
- //! Wrapper for QPainter::drawPoint()
 
- void QwtPainter::drawPoint( QPainter *painter, const QPointF &pos )
 
- {
 
-     QRectF clipRect;
 
-     const bool deviceClipping = isClippingNeeded( painter, clipRect );
 
-     if ( deviceClipping && !clipRect.contains( pos ) )
 
-         return;
 
-     painter->drawPoint( pos );
 
- }
 
- //! Wrapper for QPainter::drawImage()
 
- void QwtPainter::drawImage( QPainter *painter,
 
-     const QRectF &rect, const QImage &image )
 
- {
 
-     const QRect alignedRect = rect.toAlignedRect();
 
-     if ( alignedRect != rect )
 
-     {
 
-         const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
 
-         painter->save();
 
-         painter->setClipRect( clipRect, Qt::IntersectClip );
 
-         painter->drawImage( alignedRect, image );
 
-         painter->restore();
 
-     }
 
-     else
 
-     {
 
-         painter->drawImage( alignedRect, image );
 
-     }
 
- }
 
- //! Wrapper for QPainter::drawPixmap()
 
- void QwtPainter::drawPixmap( QPainter *painter,
 
-     const QRectF &rect, const QPixmap &pixmap )
 
- {
 
-     const QRect alignedRect = rect.toAlignedRect();
 
-     if ( alignedRect != rect )
 
-     {
 
-         const QRectF clipRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
 
-         painter->save();
 
-         painter->setClipRect( clipRect, Qt::IntersectClip );
 
-         painter->drawPixmap( alignedRect, pixmap );
 
-         painter->restore();
 
-     }
 
-     else
 
-     {
 
-         painter->drawPixmap( alignedRect, pixmap );
 
-     }
 
- }
 
- /*! 
 
-    Draw a arc with a linear gradient
 
-    \note This method needs to be replaced by using QGradient
 
- */
 
- void QwtPainter::drawColoredArc( QPainter *painter, const QRect &rect,
 
-     int peak, int arc, int interval, const QColor &c1, const QColor &c2 )
 
- {
 
-     int h1, s1, v1;
 
-     int h2, s2, v2;
 
-     c1.getHsv( &h1, &s1, &v1 );
 
-     c2.getHsv( &h2, &s2, &v2 );
 
-     arc /= 2;
 
-     for ( int angle = -arc; angle < arc; angle += interval )
 
-     {
 
-         double ratio;
 
-         if ( angle >= 0 )
 
-             ratio = 1.0 - angle / double( arc );
 
-         else
 
-             ratio = 1.0 + angle / double( arc );
 
-         QColor c;
 
-         c.setHsv( h1 + qRound( ratio * ( h2 - h1 ) ),
 
-             s1 + qRound( ratio * ( s2 - s1 ) ),
 
-             v1 + qRound( ratio * ( v2 - v1 ) ) );
 
-         painter->setPen( QPen( c, painter->pen().width() ) );
 
-         painter->drawArc( rect, ( peak + angle ) * 16, interval * 16 );
 
-     }
 
- }
 
- //! Draw a focus rectangle on a widget using its style.
 
- void QwtPainter::drawFocusRect( QPainter *painter, QWidget *widget )
 
- {
 
-     drawFocusRect( painter, widget, widget->rect() );
 
- }
 
- //! Draw a focus rectangle on a widget using its style.
 
- void QwtPainter::drawFocusRect( QPainter *painter, QWidget *widget,
 
-     const QRect &rect )
 
- {
 
-     QStyleOptionFocusRect opt;
 
-     opt.init( widget );
 
-     opt.rect = rect;
 
-     opt.state |= QStyle::State_HasFocus;
 
-     widget->style()->drawPrimitive( QStyle::PE_FrameFocusRect,
 
-         &opt, painter, widget );
 
- }
 
- //! Draw a round frame
 
- void QwtPainter::drawRoundFrame( QPainter *painter, const QRect &rect,
 
-     int width, const QPalette &palette, bool sunken )
 
- {
 
-     QColor c0 = palette.color( QPalette::Mid );
 
-     QColor c1, c2;
 
-     if ( sunken )
 
-     {
 
-         c1 = palette.color( QPalette::Dark );
 
-         c2 = palette.color( QPalette::Light );
 
-     }
 
-     else
 
-     {
 
-         c1 = palette.color( QPalette::Light );
 
-         c2 = palette.color( QPalette::Dark );
 
-     }
 
-     painter->setPen( QPen( c0, width ) );
 
-     painter->drawArc( rect, 0, 360 * 16 ); // full
 
-     const int peak = 150;
 
-     const int interval = 2;
 
-     if ( c0 != c1 )
 
-         drawColoredArc( painter, rect, peak, 160, interval, c0, c1 );
 
-     if ( c0 != c2 )
 
-         drawColoredArc( painter, rect, peak + 180, 120, interval, c0, c2 );
 
- }
 
- /*!
 
-   Draw a color bar into a rectangle
 
-   \param painter Painter
 
-   \param colorMap Color map
 
-   \param interval Value range
 
-   \param scaleMap Scale map
 
-   \param orientation Orientation
 
-   \param rect Traget rectangle
 
- */
 
- void QwtPainter::drawColorBar( QPainter *painter,
 
-         const QwtColorMap &colorMap, const QwtInterval &interval,
 
-         const QwtScaleMap &scaleMap, Qt::Orientation orientation,
 
-         const QRectF &rect )
 
- {
 
-     QVector<QRgb> colorTable;
 
-     if ( colorMap.format() == QwtColorMap::Indexed )
 
-         colorTable = colorMap.colorTable( interval );
 
-     QColor c;
 
-     const QRect devRect = rect.toAlignedRect();
 
-     /*
 
-       We paint to a pixmap first to have something scalable for printing
 
-       ( f.e. in a Pdf document )
 
-      */
 
-     QPixmap pixmap( devRect.size() );
 
-     QPainter pmPainter( &pixmap );
 
-     pmPainter.translate( -devRect.x(), -devRect.y() );
 
-     if ( orientation == Qt::Horizontal )
 
-     {
 
-         QwtScaleMap sMap = scaleMap;
 
-         sMap.setPaintInterval( rect.left(), rect.right() );
 
-         for ( int x = devRect.left(); x <= devRect.right(); x++ )
 
-         {
 
-             const double value = sMap.invTransform( x );
 
-             if ( colorMap.format() == QwtColorMap::RGB )
 
-                 c.setRgb( colorMap.rgb( interval, value ) );
 
-             else
 
-                 c = colorTable[colorMap.colorIndex( interval, value )];
 
-             pmPainter.setPen( c );
 
-             pmPainter.drawLine( x, devRect.top(), x, devRect.bottom() );
 
-         }
 
-     }
 
-     else // Vertical
 
-     {
 
-         QwtScaleMap sMap = scaleMap;
 
-         sMap.setPaintInterval( rect.bottom(), rect.top() );
 
-         for ( int y = devRect.top(); y <= devRect.bottom(); y++ )
 
-         {
 
-             const double value = sMap.invTransform( y );
 
-             if ( colorMap.format() == QwtColorMap::RGB )
 
-                 c.setRgb( colorMap.rgb( interval, value ) );
 
-             else
 
-                 c = colorTable[colorMap.colorIndex( interval, value )];
 
-             pmPainter.setPen( c );
 
-             pmPainter.drawLine( devRect.left(), y, devRect.right(), y );
 
-         }
 
-     }
 
-     pmPainter.end();
 
-     drawPixmap( painter, rect, pixmap );
 
- }
 
 
  |