mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	* require qwt >=6.2 (and fallback to internal 6.3 if system's qwt doesn't suffice) * debian doesn't have qwt for Qt6 and won't have it for trixie
		
			
				
	
	
		
			1540 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1540 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/******************************************************************************
 | 
						||
 * 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 <qwidget.h>
 | 
						||
#include <qframe.h>
 | 
						||
#include <qrect.h>
 | 
						||
#include <qpainter.h>
 | 
						||
#include <qpalette.h>
 | 
						||
#include <qpaintdevice.h>
 | 
						||
#include <qpainterpath.h>
 | 
						||
#include <qpixmap.h>
 | 
						||
#include <qstyle.h>
 | 
						||
#include <qtextdocument.h>
 | 
						||
#include <qabstracttextdocumentlayout.h>
 | 
						||
#include <qstyleoption.h>
 | 
						||
#include <qpaintengine.h>
 | 
						||
#include <qapplication.h>
 | 
						||
 | 
						||
#if QT_VERSION >= 0x060000
 | 
						||
#include <qscreen.h>
 | 
						||
#else
 | 
						||
#include <qdesktopwidget.h>
 | 
						||
#endif
 | 
						||
 | 
						||
#if QT_VERSION < 0x050000
 | 
						||
 | 
						||
#ifdef Q_WS_X11
 | 
						||
#include <qx11info_x11.h>
 | 
						||
#endif
 | 
						||
 | 
						||
#endif
 | 
						||
 | 
						||
#include <cstring>
 | 
						||
 | 
						||
bool QwtPainter::m_polylineSplitting = true;
 | 
						||
bool QwtPainter::m_roundingAlignment = true;
 | 
						||
 | 
						||
static inline bool qwtIsRasterPaintEngineBuggy()
 | 
						||
{
 | 
						||
#if 0
 | 
						||
    static int isBuggy = -1;
 | 
						||
    if ( isBuggy < 0 )
 | 
						||
    {
 | 
						||
        // auto detect bug of the raster paint engine,
 | 
						||
        // fixed with: https://codereview.qt-project.org/#/c/99456/
 | 
						||
 | 
						||
        QImage image( 2, 3, QImage::Format_ARGB32 );
 | 
						||
        image.fill( 0u );
 | 
						||
 | 
						||
        QPolygonF p;
 | 
						||
        p += QPointF(0, 1);
 | 
						||
        p += QPointF(0, 0);
 | 
						||
        p += QPointF(1, 0 );
 | 
						||
        p += QPointF(1, 2 );
 | 
						||
 | 
						||
        QPainter painter( &image );
 | 
						||
        painter.drawPolyline( p );
 | 
						||
        painter.end();
 | 
						||
 | 
						||
        isBuggy = ( image.pixel( 1, 1 ) == 0 ) ? 1 : 0;
 | 
						||
    }
 | 
						||
 | 
						||
    return isBuggy == 1;
 | 
						||
#endif
 | 
						||
 | 
						||
#if QT_VERSION < 0x050000
 | 
						||
    return true;
 | 
						||
#elif QT_VERSION < 0x050100
 | 
						||
    return false;
 | 
						||
#elif QT_VERSION < 0x050400
 | 
						||
    return true;
 | 
						||
#else
 | 
						||
    return false;
 | 
						||
#endif
 | 
						||
}
 | 
						||
 | 
						||
static inline bool qwtIsClippingNeeded(
 | 
						||
    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;
 | 
						||
}
 | 
						||
 | 
						||
template< class T >
 | 
						||
static inline void qwtDrawPolyline( QPainter* painter,
 | 
						||
    const T* points, int pointCount, bool polylineSplitting )
 | 
						||
{
 | 
						||
    bool doSplit = false;
 | 
						||
    if ( polylineSplitting )
 | 
						||
    {
 | 
						||
        const QPaintEngine* pe = painter->paintEngine();
 | 
						||
        if ( pe && pe->type() == QPaintEngine::Raster )
 | 
						||
        {
 | 
						||
            /*
 | 
						||
               Raster paint engine is much faster when splitting
 | 
						||
               the polygon, but of course we might see some issues where
 | 
						||
               the pieces are joining
 | 
						||
             */
 | 
						||
            doSplit = true;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    if ( doSplit )
 | 
						||
    {
 | 
						||
        QPen pen = painter->pen();
 | 
						||
 | 
						||
        const int splitSize = 6;
 | 
						||
 | 
						||
        if ( pen.width() <= 1 && pen.isSolid() && qwtIsRasterPaintEngineBuggy()
 | 
						||
            && !( painter->renderHints() & QPainter::Antialiasing ) )
 | 
						||
        {
 | 
						||
            int k = 0;
 | 
						||
 | 
						||
            for ( int i = k + 1; i < pointCount; i++ )
 | 
						||
            {
 | 
						||
                const QPointF& p1 = points[i - 1];
 | 
						||
                const QPointF& p2 = points[i];
 | 
						||
 | 
						||
                const bool isBad = ( qAbs( p2.y() - p1.y() ) <= 1 )
 | 
						||
                    && qAbs( p2.x() - p1.x() ) <= 1;
 | 
						||
 | 
						||
                if ( isBad || ( i - k >= splitSize ) )
 | 
						||
                {
 | 
						||
                    painter->drawPolyline( points + k, i - k + 1 );
 | 
						||
                    k = i;
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            painter->drawPolyline( points + k, pointCount - k );
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            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 QSize qwtScreenResolution()
 | 
						||
{
 | 
						||
    static QSize screenResolution;
 | 
						||
    if ( !screenResolution.isValid() )
 | 
						||
    {
 | 
						||
        /*
 | 
						||
            We might have screens with different resolutions. TODO ...
 | 
						||
         */
 | 
						||
#if QT_VERSION >= 0x060000
 | 
						||
        QScreen* screen = QGuiApplication::primaryScreen();
 | 
						||
        if ( screen )
 | 
						||
        {
 | 
						||
            screenResolution.setWidth( screen->logicalDotsPerInchX() );
 | 
						||
            screenResolution.setHeight( screen->logicalDotsPerInchY() );
 | 
						||
        }
 | 
						||
#else
 | 
						||
        QDesktopWidget* desktop = QApplication::desktop();
 | 
						||
        if ( desktop )
 | 
						||
        {
 | 
						||
            screenResolution.setWidth( desktop->logicalDpiX() );
 | 
						||
            screenResolution.setHeight( desktop->logicalDpiY() );
 | 
						||
        }
 | 
						||
#endif
 | 
						||
    }
 | 
						||
 | 
						||
    return screenResolution;
 | 
						||
}
 | 
						||
 | 
						||
static inline void qwtUnscaleFont( QPainter* painter )
 | 
						||
{
 | 
						||
    if ( painter->font().pixelSize() >= 0 )
 | 
						||
        return;
 | 
						||
 | 
						||
    const QSize screenResolution = qwtScreenResolution();
 | 
						||
 | 
						||
    const QPaintDevice* pd = painter->device();
 | 
						||
    if ( pd->logicalDpiX() != screenResolution.width() ||
 | 
						||
        pd->logicalDpiY() != screenResolution.height() )
 | 
						||
    {
 | 
						||
        QFont pixelFont = QwtPainter::scaledFont( painter->font() );
 | 
						||
        pixelFont.setPixelSize( QFontInfo( pixelFont ).pixelSize() );
 | 
						||
 | 
						||
        painter->setFont( pixelFont );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Check is the application is running with the X11 graphics system
 | 
						||
   that has some special capabilities that can be used for incremental
 | 
						||
   painting to a widget.
 | 
						||
 | 
						||
   \return True, when the graphics system is X11
 | 
						||
 */
 | 
						||
bool QwtPainter::isX11GraphicsSystem()
 | 
						||
{
 | 
						||
    /*
 | 
						||
        The X11 paint engine has been removed with Qt 5.0, but
 | 
						||
        reintroduced with Qt 5.10. It can be enabled with
 | 
						||
        "export QT_XCB_NATIVE_PAINTING=1".
 | 
						||
     */
 | 
						||
 | 
						||
    static int onX11 = -1;
 | 
						||
    if ( onX11 < 0 )
 | 
						||
    {
 | 
						||
        QPixmap pm( 1, 1 );
 | 
						||
        QPainter painter( &pm );
 | 
						||
 | 
						||
        onX11 = ( painter.paintEngine()->type() == QPaintEngine::X11 ) ? 1 : 0;
 | 
						||
    }
 | 
						||
 | 
						||
    return onX11 == 1;
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   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.
 | 
						||
 | 
						||
   If we have an integer based paint engine it is also
 | 
						||
   checked if the painter has a transformation matrix,
 | 
						||
   that rotates or scales.
 | 
						||
 | 
						||
   \param  painter Painter
 | 
						||
   \return true, when the painter is aligning
 | 
						||
 | 
						||
   \sa setRoundingAlignment()
 | 
						||
 */
 | 
						||
bool QwtPainter::isAligning( const QPainter* painter )
 | 
						||
{
 | 
						||
    if ( painter && painter->isActive() )
 | 
						||
    {
 | 
						||
        const QPaintEngine::Type type =
 | 
						||
            painter->paintEngine()->type();
 | 
						||
 | 
						||
        if ( type >= QPaintEngine::User )
 | 
						||
        {
 | 
						||
            // we have no idea - better don't align
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
 | 
						||
        switch ( type )
 | 
						||
        {
 | 
						||
            case QPaintEngine::Pdf:
 | 
						||
            case QPaintEngine::SVG:
 | 
						||
#if 0
 | 
						||
            case QPaintEngine::MacPrinter:
 | 
						||
#endif
 | 
						||
                return false;
 | 
						||
 | 
						||
            default:
 | 
						||
                break;
 | 
						||
        }
 | 
						||
 | 
						||
        const QTransform& tr = painter->transform();
 | 
						||
        if ( tr.isRotating() || tr.isScaling() )
 | 
						||
        {
 | 
						||
            // we might have to check translations too
 | 
						||
            return false;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    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
 | 
						||
   ( PDF, SVG ) this flag has no effect.
 | 
						||
   QwtPainter stores this flag only, the rounding itself is done in
 | 
						||
   the painting code ( f.e the plot items ).
 | 
						||
 | 
						||
   The default setting is true.
 | 
						||
 | 
						||
   \sa roundingAlignment(), isAligning()
 | 
						||
 */
 | 
						||
void QwtPainter::setRoundingAlignment( bool enable )
 | 
						||
{
 | 
						||
    m_roundingAlignment = enable;
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   \brief En/Disable line splitting for the raster paint engine
 | 
						||
 | 
						||
   In some Qt versions the raster paint engine paints polylines of many points
 | 
						||
   much faster when they are split in smaller chunks: f.e all supported Qt versions
 | 
						||
   >= Qt 5.0 when drawing an antialiased polyline with a pen width >=2.
 | 
						||
 | 
						||
   Also the raster paint engine has a nasty bug in many versions ( Qt 4.8 - ... )
 | 
						||
   for short lines ( https://codereview.qt-project.org/#/c/99456 ), that is worked
 | 
						||
   around in this mode.
 | 
						||
 | 
						||
   The default setting is true.
 | 
						||
 | 
						||
   \sa polylineSplitting()
 | 
						||
 */
 | 
						||
void QwtPainter::setPolylineSplitting( bool enable )
 | 
						||
{
 | 
						||
    m_polylineSplitting = enable;
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPath()
 | 
						||
void QwtPainter::drawPath( QPainter* painter, const QPainterPath& path )
 | 
						||
{
 | 
						||
    painter->drawPath( path );
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawRect()
 | 
						||
void QwtPainter::drawRect( QPainter* painter, qreal x, qreal y, qreal w, qreal 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 = qwtIsClippingNeeded( 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 = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    /*
 | 
						||
       Performance of Qt4 is horrible for a non trivial brush. Without
 | 
						||
       clipping expect minutes or hours for repainting large rectangles
 | 
						||
       (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.intersected( 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 = qwtIsClippingNeeded( 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 = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping && !clipRect.contains( rect ) )
 | 
						||
        return;
 | 
						||
 | 
						||
    painter->drawEllipse( rect );
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawText()
 | 
						||
void QwtPainter::drawText( QPainter* painter,
 | 
						||
    qreal x, qreal 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 = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping && !clipRect.contains( pos ) )
 | 
						||
        return;
 | 
						||
 | 
						||
 | 
						||
    painter->save();
 | 
						||
    qwtUnscaleFont( painter );
 | 
						||
    painter->drawText( pos, text );
 | 
						||
    painter->restore();
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawText()
 | 
						||
void QwtPainter::drawText( QPainter* painter,
 | 
						||
    qreal x, qreal y, qreal w, qreal 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();
 | 
						||
    qwtUnscaleFont( painter );
 | 
						||
    painter->drawText( rect, flags, text );
 | 
						||
    painter->restore();
 | 
						||
}
 | 
						||
 | 
						||
#ifndef QT_NO_RICHTEXT
 | 
						||
 | 
						||
/*!
 | 
						||
   Draw a text document into a rectangle
 | 
						||
 | 
						||
   \param painter Painter
 | 
						||
   \param rect Target 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();
 | 
						||
 | 
						||
    QRectF unscaledRect = rect;
 | 
						||
 | 
						||
    if ( painter->font().pixelSize() < 0 )
 | 
						||
    {
 | 
						||
        const QSize res = qwtScreenResolution();
 | 
						||
 | 
						||
        const QPaintDevice* pd = painter->device();
 | 
						||
        if ( pd->logicalDpiX() != res.width() ||
 | 
						||
            pd->logicalDpiY() != res.height() )
 | 
						||
        {
 | 
						||
            QTransform transform;
 | 
						||
            transform.scale( res.width() / qreal( pd->logicalDpiX() ),
 | 
						||
                res.height() / qreal( pd->logicalDpiY() ) );
 | 
						||
 | 
						||
            painter->setWorldTransform( transform, true );
 | 
						||
            unscaledRect = transform.inverted().mapRect(rect);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    txt->setDefaultFont( painter->font() );
 | 
						||
    txt->setPageSize( QSizeF( unscaledRect.width(), QWIDGETSIZE_MAX ) );
 | 
						||
 | 
						||
    QAbstractTextDocumentLayout* layout = txt->documentLayout();
 | 
						||
 | 
						||
    const qreal height = layout->documentSize().height();
 | 
						||
    qreal y = unscaledRect.y();
 | 
						||
    if ( flags & Qt::AlignBottom )
 | 
						||
        y += ( unscaledRect.height() - height );
 | 
						||
    else if ( flags & Qt::AlignVCenter )
 | 
						||
        y += ( unscaledRect.height() - height ) / 2;
 | 
						||
 | 
						||
    QAbstractTextDocumentLayout::PaintContext context;
 | 
						||
    context.palette.setColor( QPalette::Text, painter->pen().color() );
 | 
						||
 | 
						||
    painter->translate( unscaledRect.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 = qwtIsClippingNeeded( 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 = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        painter->drawPolygon(
 | 
						||
            QwtClipper::clippedPolygonF( clipRect, polygon, true ) );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        painter->drawPolygon( polygon );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPolyline()
 | 
						||
void QwtPainter::drawPolyline( QPainter* painter, const QPolygonF& polygon )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        const QPolygonF cpa = QwtClipper::clippedPolygonF( clipRect, polygon );
 | 
						||
 | 
						||
        qwtDrawPolyline< QPointF >( painter,
 | 
						||
            cpa.constData(), cpa.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        qwtDrawPolyline< QPointF >( painter,
 | 
						||
            polygon.constData(), polygon.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPolyline()
 | 
						||
void QwtPainter::drawPolyline( QPainter* painter,
 | 
						||
    const QPointF* points, int pointCount )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        QPolygonF polygon( pointCount );
 | 
						||
        std::memcpy( polygon.data(), points, pointCount * sizeof( QPointF ) );
 | 
						||
 | 
						||
        QwtClipper::clipPolygonF( clipRect, polygon );
 | 
						||
        qwtDrawPolyline< QPointF >( painter,
 | 
						||
            polygon.constData(), polygon.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        qwtDrawPolyline< QPointF >( painter, points, pointCount, m_polylineSplitting );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPolygon()
 | 
						||
void QwtPainter::drawPolygon( QPainter* painter, const QPolygon& polygon )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        painter->drawPolygon(
 | 
						||
            QwtClipper::clippedPolygon( clipRect, polygon, true ) );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        painter->drawPolygon( polygon );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPolyline()
 | 
						||
void QwtPainter::drawPolyline( QPainter* painter, const QPolygon& polygon )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        const QPolygon cpa = QwtClipper::clippedPolygon( clipRect, polygon );
 | 
						||
 | 
						||
        qwtDrawPolyline< QPoint >( painter,
 | 
						||
            cpa.constData(), cpa.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        qwtDrawPolyline< QPoint >( painter,
 | 
						||
            polygon.constData(), polygon.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPolyline()
 | 
						||
void QwtPainter::drawPolyline( QPainter* painter,
 | 
						||
    const QPoint* points, int pointCount )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        QPolygon polygon( pointCount );
 | 
						||
        std::memcpy( polygon.data(), points, pointCount * sizeof( QPoint ) );
 | 
						||
 | 
						||
        QwtClipper::clipPolygon( clipRect, polygon );
 | 
						||
        qwtDrawPolyline< QPoint >( painter,
 | 
						||
            polygon.constData(), polygon.size(), m_polylineSplitting );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        qwtDrawPolyline< QPoint >( painter, points, pointCount, m_polylineSplitting );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPoint()
 | 
						||
void QwtPainter::drawPoint( QPainter* painter, const QPointF& pos )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping && !clipRect.contains( pos ) )
 | 
						||
        return;
 | 
						||
 | 
						||
    painter->drawPoint( pos );
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPoint()
 | 
						||
void QwtPainter::drawPoint( QPainter* painter, const QPoint& pos )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        const int minX = qwtCeil( clipRect.left() );
 | 
						||
        const int maxX = qwtFloor( clipRect.right() );
 | 
						||
        const int minY = qwtCeil( clipRect.top() );
 | 
						||
        const int maxY = qwtFloor( clipRect.bottom() );
 | 
						||
 | 
						||
        if ( pos.x() < minX || pos.x() > maxX
 | 
						||
            || pos.y() < minY || pos.y() > maxY )
 | 
						||
        {
 | 
						||
            return;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    painter->drawPoint( pos );
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPoints()
 | 
						||
void QwtPainter::drawPoints( QPainter* painter,
 | 
						||
    const QPoint* points, int pointCount )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        const int minX = qwtCeil( clipRect.left() );
 | 
						||
        const int maxX = qwtFloor( clipRect.right() );
 | 
						||
        const int minY = qwtCeil( clipRect.top() );
 | 
						||
        const int maxY = qwtFloor( clipRect.bottom() );
 | 
						||
 | 
						||
        const QRect r( minX, minY, maxX - minX, maxY - minY );
 | 
						||
 | 
						||
        QPolygon clippedPolygon( pointCount );
 | 
						||
        QPoint* clippedData = clippedPolygon.data();
 | 
						||
 | 
						||
        int numClippedPoints = 0;
 | 
						||
        for ( int i = 0; i < pointCount; i++ )
 | 
						||
        {
 | 
						||
            if ( r.contains( points[i] ) )
 | 
						||
                clippedData[ numClippedPoints++ ] = points[i];
 | 
						||
        }
 | 
						||
        painter->drawPoints( clippedData, numClippedPoints );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        painter->drawPoints( points, pointCount );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! Wrapper for QPainter::drawPoints()
 | 
						||
void QwtPainter::drawPoints( QPainter* painter,
 | 
						||
    const QPointF* points, int pointCount )
 | 
						||
{
 | 
						||
    QRectF clipRect;
 | 
						||
    const bool deviceClipping = qwtIsClippingNeeded( painter, clipRect );
 | 
						||
 | 
						||
    if ( deviceClipping )
 | 
						||
    {
 | 
						||
        QPolygonF clippedPolygon( pointCount );
 | 
						||
        QPointF* clippedData = clippedPolygon.data();
 | 
						||
 | 
						||
        int numClippedPoints = 0;
 | 
						||
        for ( int i = 0; i < pointCount; i++ )
 | 
						||
        {
 | 
						||
            if ( clipRect.contains( points[i] ) )
 | 
						||
                clippedData[ numClippedPoints++ ] = points[i];
 | 
						||
        }
 | 
						||
        painter->drawPoints( clippedData, numClippedPoints );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        painter->drawPoints( points, pointCount );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
//! 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 focus rectangle on a widget using its style.
 | 
						||
void QwtPainter::drawFocusRect( QPainter* painter, const QWidget* widget )
 | 
						||
{
 | 
						||
    drawFocusRect( painter, widget, widget->rect() );
 | 
						||
}
 | 
						||
 | 
						||
//! Draw a focus rectangle on a widget using its style.
 | 
						||
void QwtPainter::drawFocusRect( QPainter* painter, const QWidget* widget,
 | 
						||
    const QRect& rect )
 | 
						||
{
 | 
						||
    QStyleOptionFocusRect opt;
 | 
						||
    opt.initFrom( widget );
 | 
						||
    opt.rect = rect;
 | 
						||
    opt.state |= QStyle::State_HasFocus;
 | 
						||
    opt.backgroundColor = widget->palette().color( widget->backgroundRole() );
 | 
						||
 | 
						||
    widget->style()->drawPrimitive(
 | 
						||
        QStyle::PE_FrameFocusRect, &opt, painter, widget );
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Draw a round frame
 | 
						||
 | 
						||
   \param painter Painter
 | 
						||
   \param rect Frame rectangle
 | 
						||
   \param palette QPalette::WindowText is used for plain borders
 | 
						||
                 QPalette::Dark and QPalette::Light for raised
 | 
						||
                 or sunken borders
 | 
						||
   \param lineWidth Line width
 | 
						||
   \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow
 | 
						||
 */
 | 
						||
void QwtPainter::drawRoundFrame( QPainter* painter,
 | 
						||
    const QRectF& rect, const QPalette& palette,
 | 
						||
    int lineWidth, int frameStyle )
 | 
						||
{
 | 
						||
    enum Style
 | 
						||
    {
 | 
						||
        Plain,
 | 
						||
        Sunken,
 | 
						||
        Raised
 | 
						||
    };
 | 
						||
 | 
						||
    Style style = Plain;
 | 
						||
    if ( (frameStyle& QFrame::Sunken) == QFrame::Sunken )
 | 
						||
        style = Sunken;
 | 
						||
    else if ( (frameStyle& QFrame::Raised) == QFrame::Raised )
 | 
						||
        style = Raised;
 | 
						||
 | 
						||
    const qreal lw2 = 0.5 * lineWidth;
 | 
						||
    QRectF r = rect.adjusted( lw2, lw2, -lw2, -lw2 );
 | 
						||
 | 
						||
    QBrush brush;
 | 
						||
 | 
						||
    if ( style != Plain )
 | 
						||
    {
 | 
						||
        QColor c1 = palette.color( QPalette::Light );
 | 
						||
        QColor c2 = palette.color( QPalette::Dark );
 | 
						||
 | 
						||
        if ( style == Sunken )
 | 
						||
            qSwap( c1, c2 );
 | 
						||
 | 
						||
        QLinearGradient gradient( r.topLeft(), r.bottomRight() );
 | 
						||
        gradient.setColorAt( 0.0, c1 );
 | 
						||
#if 0
 | 
						||
        gradient.setColorAt( 0.3, c1 );
 | 
						||
        gradient.setColorAt( 0.7, c2 );
 | 
						||
#endif
 | 
						||
        gradient.setColorAt( 1.0, c2 );
 | 
						||
 | 
						||
        brush = QBrush( gradient );
 | 
						||
    }
 | 
						||
    else // Plain
 | 
						||
    {
 | 
						||
        brush = palette.brush( QPalette::WindowText );
 | 
						||
    }
 | 
						||
 | 
						||
    painter->save();
 | 
						||
 | 
						||
    painter->setPen( QPen( brush, lineWidth ) );
 | 
						||
    painter->setBrush( Qt::NoBrush );
 | 
						||
 | 
						||
    painter->drawEllipse( r );
 | 
						||
 | 
						||
    painter->restore();
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Draw a rectangular frame
 | 
						||
 | 
						||
   \param painter Painter
 | 
						||
   \param rect Frame rectangle
 | 
						||
   \param palette Palette
 | 
						||
   \param foregroundRole Foreground role used for QFrame::Plain
 | 
						||
   \param frameWidth Frame width
 | 
						||
   \param midLineWidth Used for QFrame::Box
 | 
						||
   \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow
 | 
						||
 */
 | 
						||
void QwtPainter::drawFrame( QPainter* painter, const QRectF& rect,
 | 
						||
    const QPalette& palette, QPalette::ColorRole foregroundRole,
 | 
						||
    int frameWidth, int midLineWidth, int frameStyle )
 | 
						||
{
 | 
						||
    if ( frameWidth <= 0 || rect.isEmpty() )
 | 
						||
        return;
 | 
						||
 | 
						||
    const int shadow = frameStyle & QFrame::Shadow_Mask;
 | 
						||
 | 
						||
    painter->save();
 | 
						||
 | 
						||
    if ( shadow == QFrame::Plain )
 | 
						||
    {
 | 
						||
        const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
 | 
						||
        const QRectF innerRect = outerRect.adjusted(
 | 
						||
            frameWidth, frameWidth, -frameWidth, -frameWidth );
 | 
						||
 | 
						||
        QPainterPath path;
 | 
						||
        path.addRect( outerRect );
 | 
						||
        path.addRect( innerRect );
 | 
						||
 | 
						||
        painter->setPen( Qt::NoPen );
 | 
						||
        painter->setBrush( palette.color( foregroundRole ) );
 | 
						||
 | 
						||
        painter->drawPath( path );
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        const int shape = frameStyle & QFrame::Shape_Mask;
 | 
						||
 | 
						||
        if ( shape == QFrame::Box )
 | 
						||
        {
 | 
						||
            const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
 | 
						||
            const QRectF midRect1 = outerRect.adjusted(
 | 
						||
                frameWidth, frameWidth, -frameWidth, -frameWidth );
 | 
						||
            const QRectF midRect2 = midRect1.adjusted(
 | 
						||
                midLineWidth, midLineWidth, -midLineWidth, -midLineWidth );
 | 
						||
 | 
						||
            const QRectF innerRect = midRect2.adjusted(
 | 
						||
                frameWidth, frameWidth, -frameWidth, -frameWidth );
 | 
						||
 | 
						||
            QPainterPath path1;
 | 
						||
            path1.moveTo( outerRect.bottomLeft() );
 | 
						||
            path1.lineTo( outerRect.topLeft() );
 | 
						||
            path1.lineTo( outerRect.topRight() );
 | 
						||
            path1.lineTo( midRect1.topRight() );
 | 
						||
            path1.lineTo( midRect1.topLeft() );
 | 
						||
            path1.lineTo( midRect1.bottomLeft() );
 | 
						||
 | 
						||
            QPainterPath path2;
 | 
						||
            path2.moveTo( outerRect.bottomLeft() );
 | 
						||
            path2.lineTo( outerRect.bottomRight() );
 | 
						||
            path2.lineTo( outerRect.topRight() );
 | 
						||
            path2.lineTo( midRect1.topRight() );
 | 
						||
            path2.lineTo( midRect1.bottomRight() );
 | 
						||
            path2.lineTo( midRect1.bottomLeft() );
 | 
						||
 | 
						||
            QPainterPath path3;
 | 
						||
            path3.moveTo( midRect2.bottomLeft() );
 | 
						||
            path3.lineTo( midRect2.topLeft() );
 | 
						||
            path3.lineTo( midRect2.topRight() );
 | 
						||
            path3.lineTo( innerRect.topRight() );
 | 
						||
            path3.lineTo( innerRect.topLeft() );
 | 
						||
            path3.lineTo( innerRect.bottomLeft() );
 | 
						||
 | 
						||
            QPainterPath path4;
 | 
						||
            path4.moveTo( midRect2.bottomLeft() );
 | 
						||
            path4.lineTo( midRect2.bottomRight() );
 | 
						||
            path4.lineTo( midRect2.topRight() );
 | 
						||
            path4.lineTo( innerRect.topRight() );
 | 
						||
            path4.lineTo( innerRect.bottomRight() );
 | 
						||
            path4.lineTo( innerRect.bottomLeft() );
 | 
						||
 | 
						||
            QPainterPath path5;
 | 
						||
            path5.addRect( midRect1 );
 | 
						||
            path5.addRect( midRect2 );
 | 
						||
 | 
						||
            painter->setPen( Qt::NoPen );
 | 
						||
 | 
						||
            QBrush brush1 = palette.dark().color();
 | 
						||
            QBrush brush2 = palette.light().color();
 | 
						||
 | 
						||
            if ( shadow == QFrame::Raised )
 | 
						||
                qSwap( brush1, brush2 );
 | 
						||
 | 
						||
            painter->setBrush( brush1 );
 | 
						||
            painter->drawPath( path1 );
 | 
						||
            painter->drawPath( path4 );
 | 
						||
 | 
						||
            painter->setBrush( brush2 );
 | 
						||
            painter->drawPath( path2 );
 | 
						||
            painter->drawPath( path3 );
 | 
						||
 | 
						||
            painter->setBrush( palette.mid() );
 | 
						||
            painter->drawPath( path5 );
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            const QRectF outerRect = rect.adjusted( 0.0, 0.0, -1.0, -1.0 );
 | 
						||
            const QRectF innerRect = outerRect.adjusted(
 | 
						||
                frameWidth - 1.0, frameWidth - 1.0,
 | 
						||
                -( frameWidth - 1.0 ), -( frameWidth - 1.0 ) );
 | 
						||
 | 
						||
            QPainterPath path1;
 | 
						||
            path1.moveTo( outerRect.bottomLeft() );
 | 
						||
            path1.lineTo( outerRect.topLeft() );
 | 
						||
            path1.lineTo( outerRect.topRight() );
 | 
						||
            path1.lineTo( innerRect.topRight() );
 | 
						||
            path1.lineTo( innerRect.topLeft() );
 | 
						||
            path1.lineTo( innerRect.bottomLeft() );
 | 
						||
 | 
						||
 | 
						||
            QPainterPath path2;
 | 
						||
            path2.moveTo( outerRect.bottomLeft() );
 | 
						||
            path2.lineTo( outerRect.bottomRight() );
 | 
						||
            path2.lineTo( outerRect.topRight() );
 | 
						||
            path2.lineTo( innerRect.topRight() );
 | 
						||
            path2.lineTo( innerRect.bottomRight() );
 | 
						||
            path2.lineTo( innerRect.bottomLeft() );
 | 
						||
 | 
						||
            painter->setPen( Qt::NoPen );
 | 
						||
 | 
						||
            QBrush brush1 = palette.dark().color();
 | 
						||
            QBrush brush2 = palette.light().color();
 | 
						||
 | 
						||
            if ( shadow == QFrame::Raised )
 | 
						||
                qSwap( brush1, brush2 );
 | 
						||
 | 
						||
            painter->setBrush( brush1 );
 | 
						||
            painter->drawPath( path1 );
 | 
						||
 | 
						||
            painter->setBrush( brush2 );
 | 
						||
            painter->drawPath( path2 );
 | 
						||
        }
 | 
						||
 | 
						||
    }
 | 
						||
 | 
						||
    painter->restore();
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Draw a rectangular frame with rounded borders
 | 
						||
 | 
						||
   \param painter Painter
 | 
						||
   \param rect Frame rectangle
 | 
						||
   \param xRadius x-radius of the ellipses defining the corners
 | 
						||
   \param yRadius y-radius of the ellipses defining the corners
 | 
						||
   \param palette QPalette::WindowText is used for plain borders
 | 
						||
                 QPalette::Dark and QPalette::Light for raised
 | 
						||
                 or sunken borders
 | 
						||
   \param lineWidth Line width
 | 
						||
   \param frameStyle bitwise OR´ed value of QFrame::Shape and QFrame::Shadow
 | 
						||
 */
 | 
						||
 | 
						||
void QwtPainter::drawRoundedFrame( QPainter* painter,
 | 
						||
    const QRectF& rect, qreal xRadius, qreal yRadius,
 | 
						||
    const QPalette& palette, int lineWidth, int frameStyle )
 | 
						||
{
 | 
						||
    painter->save();
 | 
						||
    painter->setRenderHint( QPainter::Antialiasing, true );
 | 
						||
    painter->setBrush( Qt::NoBrush );
 | 
						||
 | 
						||
    qreal lw2 = lineWidth * 0.5;
 | 
						||
    QRectF innerRect = rect.adjusted( lw2, lw2, -lw2, -lw2 );
 | 
						||
 | 
						||
    QPainterPath path;
 | 
						||
    path.addRoundedRect( innerRect, xRadius, yRadius );
 | 
						||
 | 
						||
    enum Style
 | 
						||
    {
 | 
						||
        Plain,
 | 
						||
        Sunken,
 | 
						||
        Raised
 | 
						||
    };
 | 
						||
 | 
						||
    Style style = Plain;
 | 
						||
    if ( (frameStyle& QFrame::Sunken) == QFrame::Sunken )
 | 
						||
        style = Sunken;
 | 
						||
    else if ( (frameStyle& QFrame::Raised) == QFrame::Raised )
 | 
						||
        style = Raised;
 | 
						||
 | 
						||
    if ( style != Plain && path.elementCount() == 17 )
 | 
						||
    {
 | 
						||
        // move + 4 * ( cubicTo + lineTo )
 | 
						||
        QPainterPath pathList[8];
 | 
						||
 | 
						||
        for ( int i = 0; i < 4; i++ )
 | 
						||
        {
 | 
						||
            const int j = i * 4 + 1;
 | 
						||
 | 
						||
            pathList[ 2 * i ].moveTo(
 | 
						||
                path.elementAt(j - 1).x, path.elementAt( j - 1 ).y
 | 
						||
                );
 | 
						||
 | 
						||
            pathList[ 2 * i ].cubicTo(
 | 
						||
                path.elementAt(j + 0).x, path.elementAt(j + 0).y,
 | 
						||
                path.elementAt(j + 1).x, path.elementAt(j + 1).y,
 | 
						||
                path.elementAt(j + 2).x, path.elementAt(j + 2).y );
 | 
						||
 | 
						||
            pathList[ 2 * i + 1 ].moveTo(
 | 
						||
                path.elementAt(j + 2).x, path.elementAt(j + 2).y
 | 
						||
                );
 | 
						||
            pathList[ 2 * i + 1 ].lineTo(
 | 
						||
                path.elementAt(j + 3).x, path.elementAt(j + 3).y
 | 
						||
                );
 | 
						||
        }
 | 
						||
 | 
						||
        QColor c1( palette.color( QPalette::Dark ) );
 | 
						||
        QColor c2( palette.color( QPalette::Light ) );
 | 
						||
 | 
						||
        if ( style == Raised )
 | 
						||
            qSwap( c1, c2 );
 | 
						||
 | 
						||
        for ( int i = 0; i < 4; i++ )
 | 
						||
        {
 | 
						||
            const QRectF r = pathList[2 * i].controlPointRect();
 | 
						||
 | 
						||
            QPen arcPen;
 | 
						||
            arcPen.setCapStyle( Qt::FlatCap );
 | 
						||
            arcPen.setWidth( lineWidth );
 | 
						||
 | 
						||
            QPen linePen;
 | 
						||
            linePen.setCapStyle( Qt::FlatCap );
 | 
						||
            linePen.setWidth( lineWidth );
 | 
						||
 | 
						||
            switch( i )
 | 
						||
            {
 | 
						||
                case 0:
 | 
						||
                {
 | 
						||
                    arcPen.setColor( c1 );
 | 
						||
                    linePen.setColor( c1 );
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
                case 1:
 | 
						||
                {
 | 
						||
                    QLinearGradient gradient;
 | 
						||
                    gradient.setStart( r.topLeft() );
 | 
						||
                    gradient.setFinalStop( r.bottomRight() );
 | 
						||
                    gradient.setColorAt( 0.0, c1 );
 | 
						||
                    gradient.setColorAt( 1.0, c2 );
 | 
						||
 | 
						||
                    arcPen.setBrush( gradient );
 | 
						||
                    linePen.setColor( c2 );
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
                case 2:
 | 
						||
                {
 | 
						||
                    arcPen.setColor( c2 );
 | 
						||
                    linePen.setColor( c2 );
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
                case 3:
 | 
						||
                {
 | 
						||
                    QLinearGradient gradient;
 | 
						||
 | 
						||
                    gradient.setStart( r.bottomRight() );
 | 
						||
                    gradient.setFinalStop( r.topLeft() );
 | 
						||
                    gradient.setColorAt( 0.0, c2 );
 | 
						||
                    gradient.setColorAt( 1.0, c1 );
 | 
						||
 | 
						||
                    arcPen.setBrush( gradient );
 | 
						||
                    linePen.setColor( c1 );
 | 
						||
                    break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            painter->setPen( arcPen );
 | 
						||
            painter->drawPath( pathList[ 2 * i] );
 | 
						||
 | 
						||
            painter->setPen( linePen );
 | 
						||
            painter->drawPath( pathList[ 2 * i + 1] );
 | 
						||
        }
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        QPen pen( palette.color( QPalette::WindowText ), lineWidth );
 | 
						||
        painter->setPen( pen );
 | 
						||
        painter->drawPath( path );
 | 
						||
    }
 | 
						||
 | 
						||
    painter->restore();
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   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 Target 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.colorTable256();
 | 
						||
 | 
						||
    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() );
 | 
						||
    pixmap.fill( Qt::transparent );
 | 
						||
 | 
						||
    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.setRgba( colorMap.rgb( interval, value ) );
 | 
						||
            else
 | 
						||
                c = colorTable[colorMap.colorIndex( 256, 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.setRgba( colorMap.rgb( interval, value ) );
 | 
						||
            else
 | 
						||
                c = colorTable[colorMap.colorIndex( 256, interval, value )];
 | 
						||
 | 
						||
            pmPainter.setPen( c );
 | 
						||
            pmPainter.drawLine( devRect.left(), y, devRect.right(), y );
 | 
						||
        }
 | 
						||
    }
 | 
						||
    pmPainter.end();
 | 
						||
 | 
						||
    drawPixmap( painter, rect, pixmap );
 | 
						||
}
 | 
						||
 | 
						||
static inline void qwtFillRect( const QWidget* widget, QPainter* painter,
 | 
						||
    const QRect& rect, const QBrush& brush)
 | 
						||
{
 | 
						||
    if ( brush.style() == Qt::TexturePattern )
 | 
						||
    {
 | 
						||
        painter->save();
 | 
						||
 | 
						||
        painter->setClipRect( rect );
 | 
						||
        painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft() );
 | 
						||
 | 
						||
        painter->restore();
 | 
						||
    }
 | 
						||
    else if ( brush.gradient() )
 | 
						||
    {
 | 
						||
        painter->save();
 | 
						||
 | 
						||
        painter->setClipRect( rect );
 | 
						||
        painter->fillRect(0, 0, widget->width(),
 | 
						||
            widget->height(), brush);
 | 
						||
 | 
						||
        painter->restore();
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        painter->fillRect(rect, brush);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Fill a pixmap with the content of a widget
 | 
						||
 | 
						||
   In Qt >= 5.0 QPixmap::fill() is a nop, in Qt 4.x it is buggy
 | 
						||
   for backgrounds with gradients. Thus fillPixmap() offers
 | 
						||
   an alternative implementation.
 | 
						||
 | 
						||
   \param widget Widget
 | 
						||
   \param pixmap Pixmap to be filled
 | 
						||
   \param offset Offset
 | 
						||
 | 
						||
   \sa QPixmap::fill()
 | 
						||
 */
 | 
						||
void QwtPainter::fillPixmap( const QWidget* widget,
 | 
						||
    QPixmap& pixmap, const QPoint& offset )
 | 
						||
{
 | 
						||
    const QRect rect( offset, pixmap.size() );
 | 
						||
 | 
						||
    QPainter painter( &pixmap );
 | 
						||
    painter.translate( -offset );
 | 
						||
 | 
						||
    const QBrush autoFillBrush =
 | 
						||
        widget->palette().brush( widget->backgroundRole() );
 | 
						||
 | 
						||
    if ( !( widget->autoFillBackground() && autoFillBrush.isOpaque() ) )
 | 
						||
    {
 | 
						||
        const QBrush bg = widget->palette().brush( QPalette::Window );
 | 
						||
        qwtFillRect( widget, &painter, rect, bg);
 | 
						||
    }
 | 
						||
 | 
						||
    if ( widget->autoFillBackground() )
 | 
						||
        qwtFillRect( widget, &painter, rect, autoFillBrush);
 | 
						||
 | 
						||
    if ( widget->testAttribute(Qt::WA_StyledBackground) )
 | 
						||
    {
 | 
						||
        painter.setClipRegion( rect );
 | 
						||
 | 
						||
        QStyleOption opt;
 | 
						||
        opt.initFrom( widget );
 | 
						||
        widget->style()->drawPrimitive( QStyle::PE_Widget,
 | 
						||
            &opt, &painter, widget );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Fill rect with the background of a widget
 | 
						||
 | 
						||
   \param painter Painter
 | 
						||
   \param rect Rectangle to be filled
 | 
						||
   \param widget Widget
 | 
						||
 | 
						||
   \sa QStyle::PE_Widget, QWidget::backgroundRole()
 | 
						||
 */
 | 
						||
void QwtPainter::drawBackgound( QPainter* painter,
 | 
						||
    const QRectF& rect, const QWidget* widget )
 | 
						||
{
 | 
						||
    if ( widget->testAttribute( Qt::WA_StyledBackground ) )
 | 
						||
    {
 | 
						||
        QStyleOption opt;
 | 
						||
        opt.initFrom( widget );
 | 
						||
        opt.rect = rect.toAlignedRect();
 | 
						||
 | 
						||
        widget->style()->drawPrimitive(
 | 
						||
            QStyle::PE_Widget, &opt, painter, widget);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        const QBrush brush =
 | 
						||
            widget->palette().brush( widget->backgroundRole() );
 | 
						||
 | 
						||
        painter->fillRect( rect, brush );
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Distance appropriate for drawing a subsequent character after text.
 | 
						||
 | 
						||
   \param fontMetrics Font metrics
 | 
						||
   \param text Text
 | 
						||
   \return horizontal advance in pixels
 | 
						||
 */
 | 
						||
int QwtPainter::horizontalAdvance(
 | 
						||
    const QFontMetrics& fontMetrics, const QString& text )
 | 
						||
{
 | 
						||
#if QT_VERSION >= 0x050b00
 | 
						||
    return fontMetrics.horizontalAdvance( text );
 | 
						||
#else
 | 
						||
    return fontMetrics.width( text );
 | 
						||
#endif
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Distance appropriate for drawing a subsequent character after text.
 | 
						||
 | 
						||
   \param fontMetrics Font metrics
 | 
						||
   \param text Text
 | 
						||
   \return horizontal advance in pixels
 | 
						||
 */
 | 
						||
qreal QwtPainter::horizontalAdvance(
 | 
						||
    const QFontMetricsF& fontMetrics, const QString& text )
 | 
						||
{
 | 
						||
#if QT_VERSION >= 0x050b00
 | 
						||
    return fontMetrics.horizontalAdvance( text );
 | 
						||
#else
 | 
						||
    return fontMetrics.width( text );
 | 
						||
#endif
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Distance appropriate for drawing a subsequent character after ch.
 | 
						||
 | 
						||
   \param fontMetrics Font metrics
 | 
						||
   \param ch Character
 | 
						||
   \return horizontal advance in pixels
 | 
						||
 */
 | 
						||
int QwtPainter::horizontalAdvance(
 | 
						||
    const QFontMetrics& fontMetrics, QChar ch )
 | 
						||
{
 | 
						||
#if QT_VERSION >= 0x050b00
 | 
						||
    return fontMetrics.horizontalAdvance( ch );
 | 
						||
#else
 | 
						||
    return fontMetrics.width( ch );
 | 
						||
#endif
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Distance appropriate for drawing a subsequent character after ch.
 | 
						||
 | 
						||
   \param fontMetrics Font metrics
 | 
						||
   \param ch Character
 | 
						||
   \return horizontal advance in pixels
 | 
						||
 */
 | 
						||
qreal QwtPainter::horizontalAdvance(
 | 
						||
    const QFontMetricsF& fontMetrics, QChar ch )
 | 
						||
{
 | 
						||
#if QT_VERSION >= 0x050b00
 | 
						||
    return fontMetrics.horizontalAdvance( ch );
 | 
						||
#else
 | 
						||
    return fontMetrics.width( ch );
 | 
						||
#endif
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   Adjust the DPI value of font according to the DPI value of the paint device
 | 
						||
 | 
						||
   \param font Unscaled font
 | 
						||
   \param paintDevice Paint device providing a DPI value. If paintDevice == null
 | 
						||
                     the DPI value of the primary screen will be used
 | 
						||
 | 
						||
   \return Font being adjusted to the DPI value of the paint device
 | 
						||
 */
 | 
						||
QFont QwtPainter::scaledFont( const QFont& font, const QPaintDevice* paintDevice )
 | 
						||
{
 | 
						||
    if ( paintDevice == NULL )
 | 
						||
    {
 | 
						||
#if QT_VERSION < 0x060000
 | 
						||
        paintDevice = QApplication::desktop();
 | 
						||
#else
 | 
						||
        class PaintDevice : public QPaintDevice
 | 
						||
        {
 | 
						||
            virtual QPaintEngine* paintEngine() const QWT_OVERRIDE
 | 
						||
            {
 | 
						||
                return NULL;
 | 
						||
            }
 | 
						||
 | 
						||
            virtual int metric( PaintDeviceMetric metric ) const QWT_OVERRIDE
 | 
						||
            {
 | 
						||
                if ( metric == PdmDpiY )
 | 
						||
                {
 | 
						||
                    QScreen* screen = QGuiApplication::primaryScreen();
 | 
						||
                    if ( screen )
 | 
						||
                    {
 | 
						||
                        return screen->logicalDotsPerInchY();
 | 
						||
                    }
 | 
						||
                }
 | 
						||
 | 
						||
                return QPaintDevice::metric( metric );
 | 
						||
            }
 | 
						||
        };
 | 
						||
 | 
						||
        static PaintDevice dummyPaintDevice;
 | 
						||
        paintDevice = &dummyPaintDevice;
 | 
						||
#endif
 | 
						||
    }
 | 
						||
 | 
						||
    return QFont( font, const_cast< QPaintDevice* >( paintDevice ) );
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   \return Pixel ratio for a paint device
 | 
						||
   \param paintDevice Paint device
 | 
						||
 */
 | 
						||
qreal QwtPainter::devicePixelRatio( const QPaintDevice* paintDevice )
 | 
						||
{
 | 
						||
    qreal pixelRatio = 0.0;
 | 
						||
 | 
						||
#if QT_VERSION >= 0x050100
 | 
						||
    if ( paintDevice )
 | 
						||
    {
 | 
						||
#if QT_VERSION >= 0x050600
 | 
						||
        pixelRatio = paintDevice->devicePixelRatioF();
 | 
						||
#else
 | 
						||
        pixelRatio = paintDevice->devicePixelRatio();
 | 
						||
#endif
 | 
						||
    }
 | 
						||
#else
 | 
						||
    Q_UNUSED( paintDevice )
 | 
						||
#endif
 | 
						||
 | 
						||
#if QT_VERSION >= 0x050000
 | 
						||
    if ( pixelRatio == 0.0 && qApp )
 | 
						||
        pixelRatio = qApp->devicePixelRatio();
 | 
						||
#endif
 | 
						||
 | 
						||
    if ( pixelRatio == 0.0 )
 | 
						||
        pixelRatio = 1.0;
 | 
						||
 | 
						||
    return pixelRatio;
 | 
						||
}
 | 
						||
 | 
						||
/*!
 | 
						||
   \return A pixmap that can be used as backing store
 | 
						||
 | 
						||
   \param widget Widget, for which the backingstore is intended
 | 
						||
   \param size Size of the pixmap
 | 
						||
 */
 | 
						||
QPixmap QwtPainter::backingStore( QWidget* widget, const QSize& size )
 | 
						||
{
 | 
						||
    QPixmap pm;
 | 
						||
 | 
						||
#if QT_VERSION >= 0x050000
 | 
						||
    const qreal pixelRatio = QwtPainter::devicePixelRatio( widget );
 | 
						||
 | 
						||
    pm = QPixmap( size * pixelRatio );
 | 
						||
    pm.setDevicePixelRatio( pixelRatio );
 | 
						||
#else
 | 
						||
    pm = QPixmap( size );
 | 
						||
#endif
 | 
						||
 | 
						||
#ifdef Q_WS_X11
 | 
						||
    if ( widget && isX11GraphicsSystem() )
 | 
						||
    {
 | 
						||
        if ( pm.x11Info().screen() != widget->x11Info().screen() )
 | 
						||
            pm.x11SetScreen( widget->x11Info().screen() );
 | 
						||
    }
 | 
						||
#else
 | 
						||
    Q_UNUSED( widget )
 | 
						||
#endif
 | 
						||
 | 
						||
    return pm;
 | 
						||
}
 |