7
7
* modify it under the terms of the Qwt License, Version 1.0
8
8
*****************************************************************************/
10
#include "qwt_plot_canvas.h"
11
#include "qwt_painter.h"
12
#include "qwt_null_paintdevice.h"
12
15
#include <qpainter.h>
13
16
#include <qstyle.h>
14
#if QT_VERSION >= 0x040000
15
17
#include <qstyleoption.h>
16
18
#include <qpaintengine.h>
18
22
#include <qx11info_x11.h>
22
#include "qwt_painter.h"
25
#include "qwt_paint_buffer.h"
26
#include "qwt_plot_canvas.h"
25
class QwtStyleSheetRecorder: public QwtNullPaintDevice
28
QwtStyleSheetRecorder( const QSize &size ):
29
QwtNullPaintDevice( QPaintEngine::AllFeatures )
34
virtual void updateState( const QPaintEngineState &state )
36
if ( state.state() & QPaintEngine::DirtyPen )
40
if ( state.state() & QPaintEngine::DirtyBrush )
42
d_brush = state.brush();
44
if ( state.state() & QPaintEngine::DirtyBrushOrigin )
46
d_origin = state.brushOrigin();
50
virtual void drawRects(const QRectF *rects, int count )
52
for ( int i = 0; i < count; i++ )
53
border.rectList += rects[i];
56
virtual void drawPath( const QPainterPath &path )
58
const QRectF rect( QPointF( 0.0, 0.0 ) , size() );
59
if ( path.controlPointRect().contains( rect.center() ) )
61
setCornerRects( path );
62
alignCornerRects( rect );
64
background.path = path;
65
background.brush = d_brush;
66
background.origin = d_origin;
70
border.pathList += path;
74
void setCornerRects( const QPainterPath &path )
76
QPointF pos( 0.0, 0.0 );
78
for ( int i = 0; i < path.elementCount(); i++ )
80
QPainterPath::Element el = path.elementAt(i);
83
case QPainterPath::MoveToElement:
84
case QPainterPath::LineToElement:
90
case QPainterPath::CurveToElement:
92
QRectF r( pos, QPointF( el.x, el.y ) );
93
clipRects += r.normalized();
100
case QPainterPath::CurveToDataElement:
102
if ( clipRects.size() > 0 )
104
QRectF r = clipRects.last();
106
qMin( r.left(), el.x ),
107
qMin( r.top(), el.y ),
108
qMax( r.right(), el.x ),
109
qMax( r.bottom(), el.y )
111
clipRects.last() = r.normalized();
120
void alignCornerRects( const QRectF &rect )
122
for ( int i = 0; i < clipRects.size(); i++ )
124
QRectF &r = clipRects[i];
125
if ( r.center().x() < rect.center().x() )
126
r.setLeft( rect.left() );
128
r.setRight( rect.right() );
130
if ( r.center().y() < rect.center().y() )
131
r.setTop( rect.top() );
133
r.setBottom( rect.bottom() );
139
QVector<QRectF> clipRects;
143
QList<QPainterPath> pathList;
144
QList<QRectF> rectList;
161
static void qwtDrawBackground( QPainter *painter, QWidget *widget )
163
const QBrush &brush =
164
widget->palette().brush( widget->backgroundRole() );
166
if ( brush.style() == Qt::TexturePattern )
168
QPixmap pm( widget->size() );
169
pm.fill( widget, 0, 0 );
170
painter->drawPixmap( 0, 0, pm );
172
else if ( brush.gradient() )
174
QVector<QRect> rects;
176
if ( brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode )
178
rects += widget->rect();
182
rects = painter->clipRegion().rects();
186
bool useRaster = false;
188
if ( painter->paintEngine()->type() == QPaintEngine::X11 )
190
// Qt 4.7.1: gradients on X11 are broken ( subrects +
191
// QGradient::StretchToDeviceMode ) and horrible slow.
192
// As workaround we have to use the raster paintengine.
193
// Even if the QImage -> QPixmap translation is slow
194
// it is three times faster, than using X11 directly
201
QImage::Format format = QImage::Format_RGB32;
203
const QGradientStops stops = brush.gradient()->stops();
204
for ( int i = 0; i < stops.size(); i++ )
206
if ( stops[i].second.alpha() != 255 )
208
// don't use Format_ARGB32_Premultiplied. It's
209
// recommended by the Qt docs, but QPainter::drawImage()
210
// is horrible slow on X11.
212
format = QImage::Format_ARGB32;
217
QImage image( widget->size(), format );
219
QPainter p( &image );
220
p.setPen( Qt::NoPen );
223
p.drawRects( rects );
227
painter->drawImage( 0, 0, image );
233
painter->setPen( Qt::NoPen );
234
painter->setBrush( brush );
236
painter->drawRects( rects );
245
painter->setPen( Qt::NoPen );
246
painter->setBrush( brush );
248
painter->drawRects( painter->clipRegion().rects() );
254
static inline void qwtRevertPath( QPainterPath &path )
256
if ( path.elementCount() == 4 )
258
QPainterPath::Element &el0 =
259
const_cast<QPainterPath::Element &>( path.elementAt(0) );
260
QPainterPath::Element &el2 =
261
const_cast<QPainterPath::Element &>( path.elementAt(3) );
263
qSwap( el0.x, el2.x );
264
qSwap( el0.y, el2.y );
268
static QPainterPath qwtCombinePathList( const QRectF &rect,
269
const QList<QPainterPath> &pathList )
271
if ( pathList.isEmpty() )
272
return QPainterPath();
274
QPainterPath ordered[8]; // starting top left
276
for ( int i = 0; i < pathList.size(); i++ )
279
QPainterPath subPath = pathList[i];
281
const QRectF br = pathList[i].controlPointRect();
282
if ( br.center().x() < rect.center().x() )
284
if ( br.center().y() < rect.center().y() )
286
if ( qAbs( br.top() - rect.top() ) <
287
qAbs( br.left() - rect.left() ) )
298
if ( qAbs( br.bottom() - rect.bottom() ) <
299
qAbs( br.left() - rect.left() ) )
309
if ( subPath.currentPosition().y() > br.center().y() )
310
qwtRevertPath( subPath );
314
if ( br.center().y() < rect.center().y() )
316
if ( qAbs( br.top() - rect.top() ) <
317
qAbs( br.right() - rect.right() ) )
328
if ( qAbs( br.bottom() - rect.bottom() ) <
329
qAbs( br.right() - rect.right() ) )
338
if ( subPath.currentPosition().y() < br.center().y() )
339
qwtRevertPath( subPath );
341
ordered[index] = subPath;
344
for ( int i = 0; i < 4; i++ )
346
if ( ordered[ 2 * i].isEmpty() != ordered[2 * i + 1].isEmpty() )
348
// we don't accept incomplete rounded borders
349
return QPainterPath();
354
const QPolygonF corners( rect );
357
//path.moveTo( rect.topLeft() );
359
for ( int i = 0; i < 4; i++ )
361
if ( ordered[2 * i].isEmpty() )
363
path.lineTo( corners[i] );
367
path.connectPath( ordered[2 * i] );
368
path.connectPath( ordered[2 * i + 1] );
375
return path.simplified();
381
static inline void qwtDrawStyledBackground(
382
QWidget *w, QPainter *painter )
386
w->style()->drawPrimitive( QStyle::PE_Widget, &opt, painter, w);
389
static QWidget *qwtBackgroundWidget( QWidget *w )
391
if ( w->parentWidget() == NULL )
394
if ( w->autoFillBackground() )
396
const QBrush brush = w->palette().brush( w->backgroundRole() );
397
if ( brush.color().alpha() > 0 )
401
if ( w->testAttribute( Qt::WA_StyledBackground ) )
403
QImage image( 1, 1, QImage::Format_ARGB32 );
404
image.fill( Qt::transparent );
406
QPainter painter( &image );
407
painter.translate( -w->rect().center() );
408
qwtDrawStyledBackground( w, &painter );
411
if ( qAlpha( image.pixel( 0, 0 ) ) != 0 )
415
return qwtBackgroundWidget( w->parentWidget() );
418
static void qwtFillBackground( QPainter *painter,
419
QWidget *widget, const QVector<QRectF> &fillRects )
421
if ( fillRects.isEmpty() )
425
if ( painter->hasClipping() )
426
clipRegion = painter->transform().map( painter->clipRegion() );
428
clipRegion = widget->contentsRect();
430
// Try to find out which widget fills
431
// the unfilled areas of the styled background
433
QWidget *bgWidget = qwtBackgroundWidget( widget->parentWidget() );
435
for ( int i = 0; i < fillRects.size(); i++ )
437
const QRect rect = fillRects[i].toAlignedRect();
438
if ( clipRegion.intersects( rect ) )
440
QPixmap pm( rect.size() );
441
pm.fill( bgWidget, widget->mapTo( bgWidget, rect.topLeft() ) );
442
painter->drawPixmap( rect, pm );
447
static void qwtFillBackground( QPainter *painter, QwtPlotCanvas *canvas )
449
QVector<QRectF> rects;
451
if ( canvas->testAttribute( Qt::WA_StyledBackground ) )
453
QwtStyleSheetRecorder recorder( canvas->size() );
455
QPainter p( &recorder );
456
qwtDrawStyledBackground( canvas, &p );
459
if ( recorder.background.brush.isOpaque() )
460
rects = recorder.clipRects;
462
rects += canvas->rect();
466
const QRectF r = canvas->rect();
467
const double radius = canvas->borderRadius();
470
QSize sz( radius, radius );
472
rects += QRectF( r.topLeft(), sz );
473
rects += QRectF( r.topRight() - QPointF( radius, 0 ), sz );
474
rects += QRectF( r.bottomRight() - QPointF( radius, radius ), sz );
475
rects += QRectF( r.bottomLeft() - QPointF( 0, radius ), sz );
479
qwtFillBackground( painter, canvas, rects);
28
483
class QwtPlotCanvas::PrivateData
32
focusIndicator(NoFocusIndicator),
487
focusIndicator( NoFocusIndicator ),
489
paintAttributes( 0 ),
492
styleSheet.hasBorder = false;
43
500
FocusIndicator focusIndicator;
502
QwtPlotCanvas::PaintAttributes paintAttributes;
503
QPixmap *backingStore;
508
QPainterPath borderPath;
509
QVector<QRectF> cornerRects;
511
struct StyleSheetBackground
48
//! Sets a cross cursor, enables QwtPlotCanvas::PaintCached
521
//! Sets a cross cursor, enables QwtPlotCanvas::BackingStore
50
QwtPlotCanvas::QwtPlotCanvas(QwtPlot *plot):
523
QwtPlotCanvas::QwtPlotCanvas( QwtPlot *plot ):
53
526
d_data = new PrivateData;
55
#if QT_VERSION >= 0x040100
56
setAutoFillBackground(true);
59
#if QT_VERSION < 0x040000
60
setWFlags(Qt::WNoAutoErase);
62
setCursor(Qt::crossCursor);
66
setCursor(Qt::CrossCursor);
70
setPaintAttribute(PaintCached, true);
71
setPaintAttribute(PaintPacked, true);
529
setCursor( Qt::CrossCursor );
532
setAutoFillBackground( true );
533
setPaintAttribute( QwtPlotCanvas::BackingStore, true );
534
setPaintAttribute( QwtPlotCanvas::Opaque, true );
535
setPaintAttribute( QwtPlotCanvas::HackStyledBackground, true );
213
\param event Hide event
215
void QwtPlotCanvas::hideEvent(QHideEvent *event)
217
QFrame::hideEvent(event);
219
if ( d_data->paintAttributes & PaintPacked )
221
// enable system background to avoid the "looking through
222
// the canvas" effect, for the next show
224
setSystemBackground(true);
657
Set the radius for the corners of the border frame
659
\param radius Radius of a rounded corner
662
void QwtPlotCanvas::setBorderRadius( double radius )
664
d_data->borderRadius = qMax( 0.0, radius );
668
\return Radius for the corners of the border frame
669
\sa setBorderRadius()
671
double QwtPlotCanvas::borderRadius() const
673
return d_data->borderRadius;
677
Qt event handler for QEvent::PolishRequest and QEvent::StyleChange
678
\param event Qt Event
680
bool QwtPlotCanvas::event( QEvent *event )
682
if ( event->type() == QEvent::PolishRequest )
684
if ( testPaintAttribute( QwtPlotCanvas::Opaque ) )
686
// Setting a style sheet changes the
687
// Qt::WA_OpaquePaintEvent attribute, but we insist
688
// on painting the background.
690
setAttribute( Qt::WA_OpaquePaintEvent, true );
694
if ( event->type() == QEvent::PolishRequest ||
695
event->type() == QEvent::StyleChange )
697
updateStyleSheetInfo();
700
return QFrame::event( event );
230
705
\param event Paint event
232
void QwtPlotCanvas::paintEvent(QPaintEvent *event)
707
void QwtPlotCanvas::paintEvent( QPaintEvent *event )
234
#if QT_VERSION >= 0x040000
235
QPainter painter(this);
237
if ( !contentsRect().contains( event->rect() ) )
709
QPainter painter( this );
710
painter.setClipRegion( event->region() );
712
if ( testPaintAttribute( QwtPlotCanvas::BackingStore ) &&
713
d_data->backingStore != NULL )
240
painter.setClipRegion( event->region() & frameRect() );
241
drawFrame( &painter );
245
painter.setClipRegion(event->region() & contentsRect());
247
drawContents( &painter );
248
#else // QT_VERSION < 0x040000
249
QFrame::paintEvent(event);
715
QPixmap &bs = *d_data->backingStore;
716
if ( bs.size() != size() )
718
bs = QPixmap( size() );
721
if ( bs.x11Info().screen() != x11Info().screen() )
722
bs.x11SetScreen( x11Info().screen() );
252
if ( d_data->paintAttributes & PaintPacked )
253
setSystemBackground(false);
257
Redraw the canvas, and focus rect
258
\param painter Painter
260
void QwtPlotCanvas::drawContents(QPainter *painter)
262
if ( d_data->paintAttributes & PaintCached && d_data->cache
263
&& d_data->cache->size() == contentsRect().size() )
265
painter->drawPixmap(contentsRect().topLeft(), *d_data->cache);
725
if ( testAttribute(Qt::WA_StyledBackground) )
728
qwtFillBackground( &p, this );
729
drawCanvas( &p, true );
734
if ( d_data->borderRadius <= 0.0 )
736
bs.fill( this, 0, 0 );
738
drawCanvas( &p, false );
743
qwtFillBackground( &p, this );
744
drawCanvas( &p, true );
747
if ( frameWidth() > 0 )
752
painter.drawPixmap( 0, 0, *d_data->backingStore );
269
QwtPlot *plot = ((QwtPlot *)parent());
270
const bool doAutoReplot = plot->autoReplot();
271
plot->setAutoReplot(false);
275
plot->setAutoReplot(doAutoReplot);
756
if ( testAttribute(Qt::WA_StyledBackground ) )
758
if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
760
qwtFillBackground( &painter, this );
761
drawCanvas( &painter, true );
765
drawCanvas( &painter, false );
770
if ( testAttribute( Qt::WA_OpaquePaintEvent ) )
772
if ( autoFillBackground() )
773
qwtDrawBackground( &painter, this );
776
drawCanvas( &painter, false );
778
if ( frameWidth() > 0 )
779
drawBorder( &painter );
278
783
if ( hasFocus() && focusIndicator() == CanvasFocusIndicator )
279
drawFocusIndicator(painter);
784
drawFocusIndicator( &painter );
787
void QwtPlotCanvas::drawCanvas( QPainter *painter, bool withBackground )
789
bool hackStyledBackground = false;
791
if ( withBackground && testAttribute( Qt::WA_StyledBackground )
792
&& testPaintAttribute( HackStyledBackground ) )
794
// Antialiasing rounded borders is done by
795
// inserting pixels with colors between the
796
// border color and the color on the canvas,
797
// When the border is painted before the plot items
798
// these colors are interpolated for the canvas
799
// and the plot items need to be clipped excluding
800
// the anialiased pixels. In situations, where
801
// the plot items fill the area at the rounded
802
// borders this is noticeable.
803
// The only way to avoid these annoying "artefacts"
804
// is to paint the border on top of the plot items.
806
if ( d_data->styleSheet.hasBorder &&
807
!d_data->styleSheet.borderPath.isEmpty() )
809
// We have a border with at least one rounded corner
810
hackStyledBackground = true;
814
if ( withBackground )
818
if ( testAttribute( Qt::WA_StyledBackground ) )
820
if ( hackStyledBackground )
822
// paint background without border
824
painter->setPen( Qt::NoPen );
825
painter->setBrush( d_data->styleSheet.background.brush );
826
painter->setBrushOrigin( d_data->styleSheet.background.origin );
827
painter->setClipPath( d_data->styleSheet.borderPath );
828
painter->drawRect( contentsRect() );
832
qwtDrawStyledBackground( this, painter );
835
else if ( autoFillBackground() )
837
painter->setPen( Qt::NoPen );
838
painter->setBrush( palette().brush( backgroundRole() ) );
840
if ( d_data->borderRadius > 0.0 )
842
if ( frameWidth() > 0 )
844
painter->setClipPath( borderPath( rect() ) );
845
painter->drawRect( rect() );
849
painter->setRenderHint( QPainter::Antialiasing, true );
850
painter->drawPath( borderPath( rect() ) );
855
painter->drawRect( contentsRect() );
864
if ( !d_data->styleSheet.borderPath.isEmpty() )
866
painter->setClipPath(
867
d_data->styleSheet.borderPath, Qt::IntersectClip );
871
if ( d_data->borderRadius > 0.0 )
872
painter->setClipPath( borderPath( rect() ), Qt::IntersectClip );
874
painter->setClipRect( contentsRect(), Qt::IntersectClip );
877
plot()->drawCanvas( painter );
881
if ( withBackground && hackStyledBackground )
883
// Now paint the border on top
884
QStyleOptionFrame opt;
886
style()->drawPrimitive( QStyle::PE_Frame, &opt, painter, this);
285
Paints all plot items to the contentsRect(), using QwtPlot::drawCanvas
286
and updates the paint cache.
891
Draw the border of the plot canvas
288
893
\param painter Painter
290
\sa QwtPlot::drawCanvas(), setPaintAttributes(), testPaintAttributes()
894
\sa setBorderRadius(), QFrame::drawFrame()
292
void QwtPlotCanvas::drawCanvas(QPainter *painter)
896
void QwtPlotCanvas::drawBorder( QPainter *painter )
294
if ( !contentsRect().isValid() )
298
#if QT_VERSION >= 0x040000
299
bgBrush = palette().brush(backgroundRole());
301
QColorGroup::ColorRole role =
302
QPalette::backgroundRoleFromMode( backgroundMode() );
303
bgBrush = colorGroup().brush( role );
306
if ( d_data->paintAttributes & PaintCached && d_data->cache )
898
if ( d_data->borderRadius > 0 )
308
*d_data->cache = QPixmap(contentsRect().size());
311
#if QT_VERSION >= 0x040000
312
if ( d_data->cache->x11Info().screen() != x11Info().screen() )
313
d_data->cache->x11SetScreen(x11Info().screen());
315
if ( d_data->cache->x11Screen() != x11Screen() )
316
d_data->cache->x11SetScreen(x11Screen());
320
if ( d_data->paintAttributes & PaintPacked )
900
if ( frameWidth() > 0 )
322
QPainter bgPainter(d_data->cache);
323
bgPainter.setPen(Qt::NoPen);
325
bgPainter.setBrush(bgBrush);
326
bgPainter.drawRect(d_data->cache->rect());
902
QwtPainter::drawRoundedFrame( painter, QRectF( rect() ),
903
d_data->borderRadius, d_data->borderRadius,
904
palette(), frameWidth(), frameStyle() );
329
d_data->cache->fill(this, d_data->cache->rect().topLeft());
331
QPainter cachePainter(d_data->cache);
332
cachePainter.translate(-contentsRect().x(),
333
-contentsRect().y());
335
((QwtPlot *)parent())->drawCanvas(&cachePainter);
339
painter->drawPixmap(contentsRect(), *d_data->cache);
343
#if QT_VERSION >= 0x040000
344
if ( d_data->paintAttributes & PaintPacked )
349
painter->setPen(Qt::NoPen);
350
painter->setBrush(bgBrush);
351
painter->drawRect(contentsRect());
356
((QwtPlot *)parent())->drawCanvas(painter);
909
drawFrame( painter );
915
\param event Resize event
917
void QwtPlotCanvas::resizeEvent( QResizeEvent *event )
919
QFrame::resizeEvent( event );
920
updateStyleSheetInfo();
361
924
Draw the focus indication
362
925
\param painter Painter
364
void QwtPlotCanvas::drawFocusIndicator(QPainter *painter)
927
void QwtPlotCanvas::drawFocusIndicator( QPainter *painter )
366
929
const int margin = 1;
368
931
QRect focusRect = contentsRect();
369
focusRect.setRect(focusRect.x() + margin, focusRect.y() + margin,
370
focusRect.width() - 2 * margin, focusRect.height() - 2 * margin);
372
QwtPainter::drawFocusRect(painter, this, focusRect);
375
void QwtPlotCanvas::setSystemBackground(bool on)
377
#if QT_VERSION < 0x040000
378
if ( backgroundMode() == Qt::NoBackground )
381
setBackgroundMode(Qt::PaletteBackground);
386
setBackgroundMode(Qt::NoBackground);
389
if ( testAttribute(Qt::WA_NoSystemBackground) == on )
390
setAttribute(Qt::WA_NoSystemBackground, !on);
932
focusRect.setRect( focusRect.x() + margin, focusRect.y() + margin,
933
focusRect.width() - 2 * margin, focusRect.height() - 2 * margin );
935
QwtPainter::drawFocusRect( painter, this, focusRect );
398
942
void QwtPlotCanvas::replot()
400
invalidatePaintCache();
403
In case of cached or packed painting the canvas
404
is repainted completely and doesn't need to be erased.
407
!testPaintAttribute(QwtPlotCanvas::PaintPacked)
408
&& !testPaintAttribute(QwtPlotCanvas::PaintCached);
410
#if QT_VERSION >= 0x040000
411
const bool noBackgroundMode = testAttribute(Qt::WA_NoBackground);
412
if ( !erase && !noBackgroundMode )
413
setAttribute(Qt::WA_NoBackground, true);
415
repaint(contentsRect());
417
if ( !erase && !noBackgroundMode )
418
setAttribute(Qt::WA_NoBackground, false);
420
repaint(contentsRect(), erase);
944
invalidateBackingStore();
946
if ( testPaintAttribute( QwtPlotCanvas::ImmediatePaint ) )
947
repaint( contentsRect() );
949
update( contentsRect() );
952
//! Update the cached informations about the current style sheet
953
void QwtPlotCanvas::updateStyleSheetInfo()
955
if ( !testAttribute(Qt::WA_StyledBackground ) )
958
QwtStyleSheetRecorder recorder( size() );
960
QPainter painter( &recorder );
964
style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
968
d_data->styleSheet.hasBorder = !recorder.border.rectList.isEmpty();
969
d_data->styleSheet.cornerRects = recorder.clipRects;
971
if ( recorder.background.path.isEmpty() )
973
if ( !recorder.border.rectList.isEmpty() )
975
d_data->styleSheet.borderPath =
976
qwtCombinePathList( rect(), recorder.border.pathList );
981
d_data->styleSheet.borderPath = recorder.background.path;
982
d_data->styleSheet.background.brush = recorder.background.brush;
983
d_data->styleSheet.background.origin = recorder.background.origin;
988
Calculate the painter path for a styled or rounded border
990
When the canvas has no styled background or rounded borders
991
the painter path is empty.
993
\param rect Bounding rectangle of the canvas
994
\return Painter path, that can be used for clipping
996
QPainterPath QwtPlotCanvas::borderPath( const QRect &rect ) const
998
if ( testAttribute(Qt::WA_StyledBackground ) )
1000
QwtStyleSheetRecorder recorder( rect.size() );
1002
QPainter painter( &recorder );
1007
style()->drawPrimitive( QStyle::PE_Widget, &opt, &painter, this);
1011
if ( !recorder.background.path.isEmpty() )
1012
return recorder.background.path;
1014
if ( !recorder.border.rectList.isEmpty() )
1015
return qwtCombinePathList( rect, recorder.border.pathList );
1017
else if ( d_data->borderRadius > 0.0 )
1019
double fw2 = frameWidth() * 0.5;
1020
QRectF r = QRectF(rect).adjusted( fw2, fw2, -fw2, -fw2 );
1023
path.addRoundedRect( r, d_data->borderRadius, d_data->borderRadius );
1027
return QPainterPath();
1031
Calculate a mask, that can be used to clip away the border frame
1033
\param size Size including the frame
1035
QBitmap QwtPlotCanvas::borderMask( const QSize &size ) const
1037
const QRect r( 0, 0, size.width(), size.height() );
1039
const QPainterPath path = borderPath( r );
1040
if ( path.isEmpty() )
1043
QImage image( size, QImage::Format_ARGB32_Premultiplied );
1044
image.fill( Qt::color0 );
1046
QPainter painter( &image );
1047
painter.setClipPath( path );
1048
painter.fillRect( r, Qt::color1 );
1050
// now erase the frame
1052
painter.setCompositionMode( QPainter::CompositionMode_DestinationOut );
1054
if ( testAttribute(Qt::WA_StyledBackground ) )
1056
QStyleOptionFrame opt;
1059
style()->drawPrimitive( QStyle::PE_Frame, &opt, &painter, this );
1063
if ( d_data->borderRadius > 0 && frameWidth() > 0 )
1065
painter.setPen( QPen( Qt::color1, frameWidth() ) );
1066
painter.setBrush( Qt::NoBrush );
1067
painter.setRenderHint( QPainter::Antialiasing, true );
1069
painter.drawPath( path );
1075
const QImage mask = image.createMaskFromColor(
1076
QColor( Qt::color1 ).rgb(), Qt::MaskOutColor );
1078
return QBitmap::fromImage( mask );