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();
 
  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() );
 
  173 static void qwtUpdateContentsRect( 
int fw, QWidget* canvas )
 
  175     canvas->setContentsMargins( fw, fw, fw, fw );
 
  178 static 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() );
 
  191 static 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() );
 
  235 static inline void qwtDrawStyledBackground(
 
  236     QWidget* w, QPainter* painter )
 
  240     w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
 
  243 static 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() );
 
  272 static 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 );
 
  301 static 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);
 
  336 static 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 );
 
  348 static 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();
 
  461 static 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();
 
  500 class QwtPlotAbstractCanvas::PrivateData
 
  507         styleSheet.hasBorder = 
false;
 
  516         QPainterPath borderPath;
 
  519         struct StyleSheetBackground
 
  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;
 
  883 class QwtPlotAbstractGLCanvas::PrivateData
 
  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.
virtual void drawPath(const QPainterPath &)
See QPaintEngine::drawPath()
virtual void drawRects(const QRect *, int)
See QPaintEngine::drawRects()
virtual void updateState(const QPaintEngineState &)
See QPaintEngine::updateState()
virtual QSize sizeMetrics() const =0
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 *)