10#include "qwt_plot_abstract_canvas.h" 
   12#include "qwt_painter.h" 
   13#include "qwt_null_paintdevice.h" 
   17#include <qpainterpath.h> 
   19#include <qstyleoption.h> 
   26        explicit QwtStyleSheetRecorder( 
const QSize& size )
 
   31        virtual void updateState( 
const QPaintEngineState& state ) QWT_OVERRIDE
 
   33            if ( state.state() & QPaintEngine::DirtyPen )
 
   37            if ( state.state() & QPaintEngine::DirtyBrush )
 
   39                m_brush = state.brush();
 
   41            if ( state.state() & QPaintEngine::DirtyBrushOrigin )
 
   43                m_origin = state.brushOrigin();
 
   47        virtual void drawRects(
const QRectF* rects, 
int count ) QWT_OVERRIDE
 
   49            for ( 
int i = 0; i < count; i++ )
 
   50                border.rectList += rects[i];
 
   53        virtual void drawRects(
const QRect* rects, 
int count ) QWT_OVERRIDE
 
   55            for ( 
int i = 0; i < count; i++ )
 
   56                border.rectList += rects[i];
 
   59        virtual void drawPath( 
const QPainterPath& path ) QWT_OVERRIDE
 
   61            const QRectF rect( QPointF( 0.0, 0.0 ), m_size );
 
   62            if ( path.controlPointRect().contains( rect.center() ) )
 
   64                setCornerRects( path );
 
   65                alignCornerRects( rect );
 
   67                background.path = path;
 
   68                background.brush = m_brush;
 
   69                background.origin = m_origin;
 
   73                border.pathList += path;
 
   77        void setCornerRects( 
const QPainterPath& path )
 
   79            QPointF pos( 0.0, 0.0 );
 
   81            for ( 
int i = 0; i < path.elementCount(); i++ )
 
   83                QPainterPath::Element el = path.elementAt(i);
 
   86                    case QPainterPath::MoveToElement:
 
   87                    case QPainterPath::LineToElement:
 
   93                    case QPainterPath::CurveToElement:
 
   95                        QRectF r( pos, QPointF( el.x, el.y ) );
 
   96                        clipRects += r.normalized();
 
  103                    case QPainterPath::CurveToDataElement:
 
  105                        if ( clipRects.size() > 0 )
 
  107                            QRectF r = clipRects.last();
 
  109                                qwtMinF( r.left(), el.x ),
 
  110                                qwtMinF( r.top(), el.y ),
 
  111                                qwtMaxF( r.right(), el.x ),
 
  112                                qwtMaxF( r.bottom(), el.y )
 
  114                            clipRects.last() = r.normalized();
 
  123        virtual QSize sizeMetrics() const QWT_OVERRIDE
 
  129        void alignCornerRects( 
const QRectF& rect )
 
  131            for ( 
int i = 0; i < clipRects.size(); i++ )
 
  133                QRectF& r = clipRects[i];
 
  134                if ( r.center().x() < rect.center().x() )
 
  135                    r.setLeft( rect.left() );
 
  137                    r.setRight( rect.right() );
 
  139                if ( r.center().y() < rect.center().y() )
 
  140                    r.setTop( rect.top() );
 
  142                    r.setBottom( rect.bottom() );
 
  173static void qwtUpdateContentsRect( 
int fw, QWidget* canvas )
 
  175    canvas->setContentsMargins( fw, fw, fw, fw );
 
  178static void qwtFillRegion( QPainter* painter, 
const QRegion& region )
 
  180#if QT_VERSION >= 0x050800 
  181    for ( QRegion::const_iterator it = region.cbegin();
 
  182        it != region.cend(); ++it )
 
  184        painter->drawRect( *it );
 
  187    painter->drawRects( region.rects() );
 
  191static void qwtDrawBackground( QPainter* painter, QWidget* canvas )
 
  195    QPainterPath borderClip;
 
  197    ( void )QMetaObject::invokeMethod(
 
  198        canvas, 
"borderPath", Qt::DirectConnection,
 
  199        Q_RETURN_ARG( QPainterPath, borderClip ), Q_ARG( QRect, canvas->rect() ) );
 
  201    if ( !borderClip.isEmpty() )
 
  202        painter->setClipPath( borderClip, Qt::IntersectClip );
 
  204    const QBrush& brush = canvas->palette().brush( canvas->backgroundRole() );
 
  206    if ( brush.style() == Qt::TexturePattern )
 
  208        QPixmap pm( canvas->size() );
 
  210        painter->drawPixmap( 0, 0, pm );
 
  212    else if ( brush.gradient() )
 
  214        const bool fillClipRegion =
 
  215            brush.gradient()->coordinateMode() != QGradient::ObjectBoundingMode;
 
  217        painter->setPen( Qt::NoPen );
 
  218        painter->setBrush( brush );
 
  220        if ( fillClipRegion )
 
  221            qwtFillRegion( painter, painter->clipRegion() );
 
  223            painter->drawRect( canvas->rect() );
 
  227        painter->setPen( Qt::NoPen );
 
  228        painter->setBrush( brush );
 
  229        qwtFillRegion( painter, painter->clipRegion() );
 
  235static inline void qwtDrawStyledBackground(
 
  236    QWidget* w, QPainter* painter )
 
  240    w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
 
  243static QWidget* qwtBackgroundWidget( QWidget* w )
 
  245    if ( w->parentWidget() == NULL )
 
  248    if ( w->autoFillBackground() )
 
  250        const QBrush brush = w->palette().brush( w->backgroundRole() );
 
  251        if ( brush.color().alpha() > 0 )
 
  255    if ( w->testAttribute( Qt::WA_StyledBackground ) )
 
  257        QImage image( 1, 1, QImage::Format_ARGB32 );
 
  258        image.fill( Qt::transparent );
 
  260        QPainter painter( &image );
 
  261        painter.translate( -w->rect().center() );
 
  262        qwtDrawStyledBackground( w, &painter );
 
  265        if ( qAlpha( image.pixel( 0, 0 ) ) != 0 )
 
  269    return qwtBackgroundWidget( w->parentWidget() );
 
  272static void qwtFillBackground( QPainter* painter,
 
  275    if ( fillRects.isEmpty() )
 
  279    if ( painter->hasClipping() )
 
  280        clipRegion = painter->transform().map( painter->clipRegion() );
 
  282        clipRegion = widget->contentsRect();
 
  287    QWidget* bgWidget = qwtBackgroundWidget( widget->parentWidget() );
 
  289    for ( 
int i = 0; i < fillRects.size(); i++ )
 
  291        const QRect rect = fillRects[i].toAlignedRect();
 
  292        if ( clipRegion.intersects( rect ) )
 
  294            QPixmap pm( rect.size() );
 
  296            painter->drawPixmap( rect, pm );
 
  301static void qwtFillBackground( QPainter* painter, QWidget* canvas )
 
  305    if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
 
  307        QwtStyleSheetRecorder recorder( canvas->size() );
 
  309        QPainter p( &recorder );
 
  310        qwtDrawStyledBackground( canvas, &p );
 
  313        if ( recorder.background.brush.isOpaque() )
 
  314            rects = recorder.clipRects;
 
  316            rects += canvas->rect();
 
  320        const double borderRadius = canvas->property( 
"borderRadius" ).toDouble();
 
  321        if ( borderRadius > 0.0 )
 
  323            QSizeF sz( borderRadius, borderRadius );
 
  325            const QRectF r = canvas->rect();
 
  326            rects += QRectF( r.topLeft(), sz );
 
  327            rects += QRectF( r.topRight() - QPointF( borderRadius, 0 ), sz );
 
  328            rects += QRectF( r.bottomRight() - QPointF( borderRadius, borderRadius ), sz );
 
  329            rects += QRectF( r.bottomLeft() - QPointF( 0, borderRadius ), sz );
 
  333    qwtFillBackground( painter, canvas, rects);
 
  336static inline void qwtRevertPath( QPainterPath& path )
 
  338    if ( path.elementCount() == 4 )
 
  340        QPainterPath::Element el0 = path.elementAt(0);
 
  341        QPainterPath::Element el3 = path.elementAt(3);
 
  343        path.setElementPositionAt( 0, el3.x, el3.y );
 
  344        path.setElementPositionAt( 3, el0.x, el0.y );
 
  348static QPainterPath qwtCombinePathList( 
const QRectF& rect,
 
  351    if ( pathList.isEmpty() )
 
  352        return QPainterPath();
 
  354    QPainterPath ordered[8]; 
 
  356    for ( 
int i = 0; i < pathList.size(); i++ )
 
  359        QPainterPath subPath = pathList[i];
 
  361        const QRectF br = pathList[i].controlPointRect();
 
  362        if ( br.center().x() < rect.center().x() )
 
  364            if ( br.center().y() < rect.center().y() )
 
  366                if ( qAbs( br.top() - rect.top() ) <
 
  367                    qAbs( br.left() - rect.left() ) )
 
  378                if ( qAbs( br.bottom() - rect.bottom() ) <
 
  379                    qAbs( br.left() - rect.left() ) )
 
  389            if ( subPath.currentPosition().y() > br.center().y() )
 
  390                qwtRevertPath( subPath );
 
  394            if ( br.center().y() < rect.center().y() )
 
  396                if ( qAbs( br.top() - rect.top() ) <
 
  397                    qAbs( br.right() - rect.right() ) )
 
  408                if ( qAbs( br.bottom() - rect.bottom() ) <
 
  409                    qAbs( br.right() - rect.right() ) )
 
  418            if ( subPath.currentPosition().y() < br.center().y() )
 
  419                qwtRevertPath( subPath );
 
  421        ordered[index] = subPath;
 
  424    for ( 
int i = 0; i < 4; i++ )
 
  426        if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() )
 
  429            return QPainterPath();
 
  434    const QPolygonF corners( rect );
 
  439    for ( 
int i = 0; i < 4; i++ )
 
  441        if ( ordered[2 * i].isEmpty() )
 
  443            path.lineTo( corners[i] );
 
  447            path.connectPath( ordered[2 * i] );
 
  448            path.connectPath( ordered[2 * i + 1] );
 
  455    return path.simplified();
 
  461static QPainterPath qwtBorderPath( 
const QWidget* canvas, 
const QRect& rect )
 
  463    if ( canvas->testAttribute(Qt::WA_StyledBackground ) )
 
  465        QwtStyleSheetRecorder recorder( rect.size() );
 
  467        QPainter painter( &recorder );
 
  470        opt.initFrom( canvas );
 
  472        canvas->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, canvas );
 
  476        if ( !recorder.background.path.isEmpty() )
 
  477            return recorder.background.path;
 
  479        if ( !recorder.border.rectList.isEmpty() )
 
  480            return qwtCombinePathList( rect, recorder.border.pathList );
 
  484        const double borderRadius = canvas->property( 
"borderRadius" ).toDouble();
 
  486        if ( borderRadius > 0.0 )
 
  488            double fw2 = canvas->property( 
"frameWidth" ).toInt() * 0.5;
 
  489            QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
 
  492            path.addRoundedRect( r, borderRadius, borderRadius );
 
  497    return QPainterPath();
 
  500class QwtPlotAbstractCanvas::PrivateData
 
  507        styleSheet.hasBorder = 
false;
 
  516        QPainterPath borderPath;
 
  519        struct StyleSheetBackground
 
  527    QWidget* canvasWidget;
 
  536    m_data = 
new PrivateData;
 
 
  554    return qobject_cast< QwtPlot* >( m_data->canvasWidget->parent() );
 
 
  560    return qobject_cast< const QwtPlot* >( m_data->canvasWidget->parent() );
 
 
  580    return m_data->focusIndicator;
 
 
  589    const int margin = 1;
 
  591    QRect focusRect = m_data->canvasWidget->contentsRect();
 
  592    focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
 
  593        focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
 
 
  606    m_data->borderRadius = qwtMaxF( 0.0, radius );
 
 
  615    return m_data->borderRadius;
 
 
  632    if ( m_data->borderRadius > 0 )
 
  634        const int frameWidth = w->property( 
"frameWidth" ).toInt();
 
  635        if ( frameWidth > 0 )
 
  637            const int frameShape = w->property( 
"frameShape" ).toInt();
 
  638            const int frameShadow = w->property( 
"frameShadow" ).toInt();
 
  640            const QRectF frameRect = w->property( 
"frameRect" ).toRect();
 
  643                m_data->borderRadius, m_data->borderRadius,
 
  644                w->palette(), frameWidth, frameShape | frameShadow );
 
  649        const int frameShape = w->property( 
"frameShape" ).toInt();
 
  650        const int frameShadow = w->property( 
"frameShadow" ).toInt();
 
  652#if QT_VERSION < 0x050000 
  653        QStyleOptionFrameV3 opt;
 
  655        QStyleOptionFrame opt;
 
  659        opt.frameShape = QFrame::Shape( 
int( opt.frameShape ) | frameShape );
 
  666            case QFrame::StyledPanel:
 
  669                opt.lineWidth = w->property( 
"lineWidth" ).toInt();
 
  670                opt.midLineWidth = w->property( 
"midLineWidth" ).toInt();
 
  675                opt.lineWidth = w->property( 
"frameWidth" ).toInt();
 
  680        if ( frameShadow == QFrame::Sunken )
 
  681            opt.state |= QStyle::State_Sunken;
 
  682        else if ( frameShadow == QFrame::Raised )
 
  683            opt.state |= QStyle::State_Raised;
 
  685        w->style()->drawControl(QStyle::CE_ShapedFrame, &opt, painter, w );
 
 
  708    if ( w->autoFillBackground() )
 
  710        const QRect canvasRect = w->rect();
 
  714        painter->setPen( Qt::NoPen );
 
  715        painter->setBrush( w->palette().brush( w->backgroundRole() ) );
 
  717        const QRect frameRect = w->property( 
"frameRect" ).toRect();
 
  718        if ( 
borderRadius() > 0.0 && ( canvasRect == frameRect ) )
 
  720            const int frameWidth = w->property( 
"frameWidth" ).toInt();
 
  721            if ( frameWidth > 0 )
 
  724                painter->drawRect( canvasRect );
 
  728                painter->setRenderHint( QPainter::Antialiasing, 
true );
 
  734            painter->drawRect( canvasRect );
 
 
  748    if ( hackStyledBackground )
 
  762        if ( !m_data->styleSheet.hasBorder ||
 
  763            m_data->styleSheet.borderPath.isEmpty() )
 
  766            hackStyledBackground = 
false;
 
  772    if ( hackStyledBackground )
 
  777        painter->setPen( Qt::NoPen );
 
  778        painter->setBrush( m_data->styleSheet.background.brush );
 
  779        painter->setBrushOrigin( m_data->styleSheet.background.origin );
 
  780        painter->setClipPath( m_data->styleSheet.borderPath );
 
  781        painter->drawRect( w->contentsRect() );
 
  788        QStyleOptionFrame opt;
 
  790        w->style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, w);
 
  796        w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w );
 
 
  809    if ( !m_data->styleSheet.borderPath.isEmpty() )
 
  811        painter->setClipPath(
 
  812            m_data->styleSheet.borderPath, Qt::IntersectClip );
 
  818            const QRect frameRect = w->property( 
"frameRect" ).toRect();
 
  823            painter->setClipRect( w->contentsRect(), Qt::IntersectClip );
 
  827    QwtPlot* 
plot = qobject_cast< QwtPlot* >( w->parent() );
 
 
  839    if ( !w->testAttribute( Qt::WA_StyledBackground ) )
 
  842    QwtStyleSheetRecorder recorder( w->size() );
 
  844    QPainter painter( &recorder );
 
  848    w->style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, w);
 
  852    m_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
 
  853    m_data->styleSheet.cornerRects = recorder.clipRects;
 
  855    if ( recorder.background.path.isEmpty() )
 
  857        if ( !recorder.border.rectList.isEmpty() )
 
  859            m_data->styleSheet.borderPath =
 
  860                qwtCombinePathList( w->rect(), recorder.border.pathList );
 
  865        m_data->styleSheet.borderPath = recorder.background.path;
 
  866        m_data->styleSheet.background.brush = recorder.background.brush;
 
  867        m_data->styleSheet.background.origin = recorder.background.origin;
 
 
  874    return m_data->canvasWidget;
 
 
  880    return m_data->canvasWidget;
 
 
  883class QwtPlotAbstractGLCanvas::PrivateData
 
  887        frameStyle( QFrame::Panel | QFrame::Sunken),
 
  907    m_data = 
new PrivateData;
 
 
  929    if ( 
bool( m_data->paintAttributes & attribute ) == on )
 
  934        m_data->paintAttributes |= attribute;
 
  938        m_data->paintAttributes &= ~attribute;
 
 
  954    return m_data->paintAttributes & attribute;
 
 
  967    if ( style != m_data->frameStyle )
 
  969        m_data->frameStyle = style;
 
 
  982    return m_data->frameStyle;
 
 
  993    setFrameStyle( ( m_data->frameStyle & QFrame::Shape_Mask ) | shadow );
 
 
 1002    return (QFrame::Shadow) ( m_data->frameStyle & QFrame::Shadow_Mask );
 
 
 1013    setFrameStyle( ( m_data->frameStyle & QFrame::Shadow_Mask ) | shape );
 
 
 1022    return (QFrame::Shape) ( m_data->frameStyle & QFrame::Shape_Mask );
 
 
 1035    width = qMax( width, 0 );
 
 1036    if ( width != m_data->lineWidth )
 
 1038        m_data->lineWidth = qMax( width, 0 );
 
 
 1050    return m_data->lineWidth;
 
 
 1063    width = qMax( width, 0 );
 
 1064    if ( width != m_data->midLineWidth )
 
 1066        m_data->midLineWidth = width;
 
 
 1078    return m_data->midLineWidth;
 
 
 1086    return ( 
frameStyle() != QFrame::NoFrame ) ? m_data->lineWidth : 0;
 
 
 1099        w->repaint( w->contentsRect() );
 
 1101        w->update( w->contentsRect() );
 
 
 1108    return canvasWidget()->contentsRect().adjusted( -fw, -fw, fw, fw );
 
 
 1114#if FIX_GL_TRANSLATION 
 1115    if ( painter->paintEngine()->type() == QPaintEngine::OpenGL2 )
 
 1118        painter->translate( 1, 1 );
 
 1122    if ( 
canvasWidget()->testAttribute( Qt::WA_StyledBackground ) )
 
 
A null paint device doing nothing.
static void drawRoundedFrame(QPainter *, const QRectF &, qreal xRadius, qreal yRadius, const QPalette &, int lineWidth, int frameStyle)
static void drawFocusRect(QPainter *, const QWidget *)
Draw a focus rectangle on a widget using its style.
static void fillPixmap(const QWidget *, QPixmap &, const QPoint &offset=QPoint())
Base class for all type of plot canvases.
void fillBackground(QPainter *)
Helper function for the derived plot canvas.
QwtPlot * plot()
Return parent plot widget.
virtual void drawBackground(QPainter *)
Helper function for the derived plot canvas.
void drawUnstyled(QPainter *)
Helper function for the derived plot canvas.
void setFocusIndicator(FocusIndicator)
virtual ~QwtPlotAbstractCanvas()
Destructor.
FocusIndicator focusIndicator() const
void updateStyleSheetInfo()
Update the cached information about the current style sheet.
double borderRadius() const
QPainterPath canvasBorderPath(const QRect &rect) const
virtual void drawBorder(QPainter *)
QwtPlotAbstractCanvas(QWidget *canvasWidget)
Constructor.
void drawCanvas(QPainter *)
Draw the plot to the canvas.
void drawStyled(QPainter *, bool)
Helper function for the derived plot canvas.
virtual void drawFocusIndicator(QPainter *)
void setBorderRadius(double)
FocusIndicator
Focus indicator The default setting is NoFocusIndicator.
@ NoFocusIndicator
Don't paint a focus indicator.
QwtPlotAbstractGLCanvas(QWidget *canvasWidget)
Constructor.
bool testPaintAttribute(PaintAttribute) const
void setPaintAttribute(PaintAttribute, bool on=true)
Changing the paint attributes.
QFrame::Shadow frameShadow() const
void setMidLineWidth(int)
virtual void invalidateBackingStore()=0
Invalidate the internal backing store.
PaintAttribute
Paint attributes.
@ BackingStore
Paint double buffered reusing the content of the pixmap buffer when possible.
void setFrameShape(QFrame::Shape)
QFrame::Shape frameShape() const
virtual ~QwtPlotAbstractGLCanvas()
Destructor.
void setFrameShadow(QFrame::Shadow)
QFlags< PaintAttribute > PaintAttributes
Paint attributes.
void setFrameStyle(int style)
void draw(QPainter *)
Helper function for the derived plot canvas.
virtual void drawCanvas(QPainter *)