Qwt User's Guide: qwt_graphic.cpp Source File

Qwt User's Guide 6.3.0

Loading...
Searching...
No Matches
qwt_graphic.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_graphic.h"
11#include "qwt_painter_command.h"
12#include "qwt_math.h"
13
14#include <qvector.h>
15#include <qpainter.h>
16#include <qpaintengine.h>
17#include <qimage.h>
18#include <qpixmap.h>
19#include <qpainterpath.h>
20
21#if QT_VERSION >= 0x050000
22
23#include <qguiapplication.h>
24
25static inline qreal qwtDevicePixelRatio()
26{
27 return qGuiApp ? qGuiApp->devicePixelRatio() : 1.0;
28}
29
30#endif
31
32static bool qwtHasScalablePen( const QPainter* painter )
33{
34 const QPen pen = painter->pen();
35
36 bool scalablePen = false;
37
38 if ( pen.style() != Qt::NoPen && pen.brush().style() != Qt::NoBrush )
39 {
40 scalablePen = !pen.isCosmetic();
41#if QT_VERSION < 0x050000
42 if ( !scalablePen && pen.widthF() == 0.0 )
43 {
44 const QPainter::RenderHints hints = painter->renderHints();
45 if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) )
46 scalablePen = true;
47 }
48#endif
49 }
50
51 return scalablePen;
52}
53
54static QRectF qwtStrokedPathRect(
55 const QPainter* painter, const QPainterPath& path )
56{
57 QPainterPathStroker stroker;
58 stroker.setWidth( painter->pen().widthF() );
59 stroker.setCapStyle( painter->pen().capStyle() );
60 stroker.setJoinStyle( painter->pen().joinStyle() );
61 stroker.setMiterLimit( painter->pen().miterLimit() );
62
63 QRectF rect;
64 if ( qwtHasScalablePen( painter ) )
65 {
66 QPainterPath stroke = stroker.createStroke( path );
67 rect = painter->transform().map( stroke ).boundingRect();
68 }
69 else
70 {
71 QPainterPath mappedPath = painter->transform().map( path );
72 mappedPath = stroker.createStroke( mappedPath );
73
74 rect = mappedPath.boundingRect();
75 }
76
77 return rect;
78}
79
80static inline void qwtExecCommand(
81 QPainter* painter, const QwtPainterCommand& cmd,
82 QwtGraphic::RenderHints renderHints,
83 const QTransform& transform,
84 const QTransform* initialTransform )
85{
86 switch( cmd.type() )
87 {
88 case QwtPainterCommand::Path:
89 {
90 bool doMap = false;
91
92 if ( painter->transform().isScaling() )
93 {
94 bool isCosmetic = painter->pen().isCosmetic();
95#if QT_VERSION < 0x050000
96 if ( isCosmetic && painter->pen().widthF() == 0.0 )
97 {
98 QPainter::RenderHints hints = painter->renderHints();
99 if ( hints.testFlag( QPainter::NonCosmeticDefaultPen ) )
100 isCosmetic = false;
101 }
102#endif
103
104 if ( isCosmetic )
105 {
106 // OpenGL2 seems to be buggy for cosmetic pens.
107 // It interpolates curves in too rough steps then
108
109 doMap = painter->paintEngine()->type() == QPaintEngine::OpenGL2;
110 }
111 else
112 {
113 doMap = renderHints.testFlag( QwtGraphic::RenderPensUnscaled );
114 }
115 }
116
117 if ( doMap )
118 {
119 const QTransform tr = painter->transform();
120
121 painter->resetTransform();
122
123 QPainterPath path = tr.map( *cmd.path() );
124 if ( initialTransform )
125 {
126 painter->setTransform( *initialTransform );
127 path = initialTransform->inverted().map( path );
128 }
129
130 painter->drawPath( path );
131
132 painter->setTransform( tr );
133 }
134 else
135 {
136 painter->drawPath( *cmd.path() );
137 }
138 break;
139 }
140 case QwtPainterCommand::Pixmap:
141 {
142 const QwtPainterCommand::PixmapData* data = cmd.pixmapData();
143 painter->drawPixmap( data->rect, data->pixmap, data->subRect );
144 break;
145 }
146 case QwtPainterCommand::Image:
147 {
148 const QwtPainterCommand::ImageData* data = cmd.imageData();
149 painter->drawImage( data->rect, data->image,
150 data->subRect, data->flags );
151 break;
152 }
153 case QwtPainterCommand::State:
154 {
155 const QwtPainterCommand::StateData* data = cmd.stateData();
156
157 if ( data->flags & QPaintEngine::DirtyPen )
158 painter->setPen( data->pen );
159
160 if ( data->flags & QPaintEngine::DirtyBrush )
161 painter->setBrush( data->brush );
162
163 if ( data->flags & QPaintEngine::DirtyBrushOrigin )
164 painter->setBrushOrigin( data->brushOrigin );
165
166 if ( data->flags & QPaintEngine::DirtyFont )
167 painter->setFont( data->font );
168
169 if ( data->flags & QPaintEngine::DirtyBackground )
170 {
171 painter->setBackgroundMode( data->backgroundMode );
172 painter->setBackground( data->backgroundBrush );
173 }
174
175 if ( data->flags & QPaintEngine::DirtyTransform )
176 {
177 painter->setTransform( data->transform * transform );
178 }
179
180 if ( data->flags & QPaintEngine::DirtyClipEnabled )
181 painter->setClipping( data->isClipEnabled );
182
183 if ( data->flags & QPaintEngine::DirtyClipRegion )
184 {
185 painter->setClipRegion( data->clipRegion,
186 data->clipOperation );
187 }
188
189 if ( data->flags & QPaintEngine::DirtyClipPath )
190 {
191 painter->setClipPath( data->clipPath, data->clipOperation );
192 }
193
194 if ( data->flags & QPaintEngine::DirtyHints )
195 {
196 for ( int i = 0; i < 8; i++ )
197 {
198 const QPainter::RenderHint hint = static_cast< QPainter::RenderHint >( 1 << i );
199 painter->setRenderHint( hint, data->renderHints.testFlag( hint ) );
200 }
201 }
202
203 if ( data->flags & QPaintEngine::DirtyCompositionMode )
204 painter->setCompositionMode( data->compositionMode );
205
206 if ( data->flags & QPaintEngine::DirtyOpacity )
207 painter->setOpacity( data->opacity );
208
209 break;
210 }
211 default:
212 break;
213 }
214}
215
216class QwtGraphic::PathInfo
217{
218 public:
219 PathInfo()
220 : m_scalablePen( false )
221 {
222 // QVector needs a default constructor
223 }
224
225 PathInfo( const QRectF& pointRect,
226 const QRectF& boundingRect, bool scalablePen )
227 : m_pointRect( pointRect )
228 , m_boundingRect( boundingRect )
229 , m_scalablePen( scalablePen )
230 {
231 }
232
233 inline QRectF scaledBoundingRect( qreal sx, qreal sy, bool scalePens ) const
234 {
235 if ( sx == 1.0 && sy == 1.0 )
236 return m_boundingRect;
237
238 QTransform transform;
239 transform.scale( sx, sy );
240
241 QRectF rect;
242 if ( scalePens && m_scalablePen )
243 {
244 rect = transform.mapRect( m_boundingRect );
245 }
246 else
247 {
248 rect = transform.mapRect( m_pointRect );
249
250 const qreal l = qAbs( m_pointRect.left() - m_boundingRect.left() );
251 const qreal r = qAbs( m_pointRect.right() - m_boundingRect.right() );
252 const qreal t = qAbs( m_pointRect.top() - m_boundingRect.top() );
253 const qreal b = qAbs( m_pointRect.bottom() - m_boundingRect.bottom() );
254
255 rect.adjust( -l, -t, r, b );
256 }
257
258 return rect;
259 }
260
261 inline double scaleFactorX( const QRectF& pathRect,
262 const QRectF& targetRect, bool scalePens ) const
263 {
264 if ( pathRect.width() <= 0.0 )
265 return 0.0;
266
267 const QPointF p0 = m_pointRect.center();
268
269 const qreal l = qAbs( pathRect.left() - p0.x() );
270 const qreal r = qAbs( pathRect.right() - p0.x() );
271
272 const double w = 2.0 * qwtMinF( l, r )
273 * targetRect.width() / pathRect.width();
274
275 double sx;
276 if ( scalePens && m_scalablePen )
277 {
278 sx = w / m_boundingRect.width();
279 }
280 else
281 {
282 const qreal pw = qwtMaxF(
283 qAbs( m_boundingRect.left() - m_pointRect.left() ),
284 qAbs( m_boundingRect.right() - m_pointRect.right() ) );
285
286 sx = ( w - 2 * pw ) / m_pointRect.width();
287 }
288
289 return sx;
290 }
291
292 inline double scaleFactorY( const QRectF& pathRect,
293 const QRectF& targetRect, bool scalePens ) const
294 {
295 if ( pathRect.height() <= 0.0 )
296 return 0.0;
297
298 const QPointF p0 = m_pointRect.center();
299
300 const qreal t = qAbs( pathRect.top() - p0.y() );
301 const qreal b = qAbs( pathRect.bottom() - p0.y() );
302
303 const qreal h = 2.0 * qwtMinF( t, b )
304 * targetRect.height() / pathRect.height();
305
306 double sy;
307 if ( scalePens && m_scalablePen )
308 {
309 sy = h / m_boundingRect.height();
310 }
311 else
312 {
313 const qreal pw = qwtMaxF(
314 qAbs( m_boundingRect.top() - m_pointRect.top() ),
315 qAbs( m_boundingRect.bottom() - m_pointRect.bottom() ) );
316
317 sy = ( h - 2 * pw ) / m_pointRect.height();
318 }
319
320 return sy;
321 }
322
323 private:
324 QRectF m_pointRect;
325 QRectF m_boundingRect;
326 bool m_scalablePen;
327};
328
329class QwtGraphic::PrivateData
330{
331 public:
332 PrivateData()
333 : boundingRect( 0.0, 0.0, -1.0, -1.0 )
334 , pointRect( 0.0, 0.0, -1.0, -1.0 )
335 {
336 }
337
338 QSizeF defaultSize;
339 QVector< QwtPainterCommand > commands;
340 QVector< QwtGraphic::PathInfo > pathInfos;
341
342 QRectF boundingRect;
343 QRectF pointRect;
344
345 QwtGraphic::CommandTypes commandTypes;
346 QwtGraphic::RenderHints renderHints;
347};
348
355QwtGraphic::QwtGraphic()
356{
357 setMode( QwtNullPaintDevice::PathMode );
358 m_data = new PrivateData;
359}
360
367 QwtGraphic::QwtGraphic( const QwtGraphic& other )
368{
369 setMode( other.mode() );
370 m_data = new PrivateData( *other.m_data );
371}
372
374QwtGraphic::~QwtGraphic()
375{
376 delete m_data;
377}
378
385 QwtGraphic& QwtGraphic::operator=( const QwtGraphic& other )
386{
387 setMode( other.mode() );
388 *m_data = *other.m_data;
389
390 return *this;
391}
392
397 void QwtGraphic::reset()
398{
399 m_data->commands.clear();
400 m_data->pathInfos.clear();
401
402 m_data->commandTypes = CommandTypes();
403
404 m_data->boundingRect = QRectF( 0.0, 0.0, -1.0, -1.0 );
405 m_data->pointRect = QRectF( 0.0, 0.0, -1.0, -1.0 );
406 m_data->defaultSize = QSizeF();
407}
408
413 bool QwtGraphic::isNull() const
414{
415 return m_data->commands.isEmpty();
416}
417
422 bool QwtGraphic::isEmpty() const
423{
424 return m_data->boundingRect.isEmpty();
425}
426
430 QwtGraphic::CommandTypes QwtGraphic::commandTypes() const
431{
432 return m_data->commandTypes;
433}
434
443 void QwtGraphic::setRenderHint( RenderHint hint, bool on )
444{
445 if ( on )
446 m_data->renderHints |= hint;
447 else
448 m_data->renderHints &= ~hint;
449}
450
458 bool QwtGraphic::testRenderHint( RenderHint hint ) const
459{
460 return m_data->renderHints.testFlag( hint );
461}
462
464 QwtGraphic::RenderHints QwtGraphic::renderHints() const
465{
466 return m_data->renderHints;
467}
468
477QRectF QwtGraphic::boundingRect() const
478{
479 if ( m_data->boundingRect.width() < 0 )
480 return QRectF();
481
482 return m_data->boundingRect;
483}
484
493QRectF QwtGraphic::controlPointRect() const
494{
495 if ( m_data->pointRect.width() < 0 )
496 return QRectF();
497
498 return m_data->pointRect;
499}
500
514QRectF QwtGraphic::scaledBoundingRect( qreal sx, qreal sy ) const
515{
516 if ( sx == 1.0 && sy == 1.0 )
517 return m_data->boundingRect;
518
519 const bool scalePens = !( m_data->renderHints & RenderPensUnscaled );
520
521 QTransform transform;
522 transform.scale( sx, sy );
523
524 QRectF rect = transform.mapRect( m_data->pointRect );
525
526 for ( int i = 0; i < m_data->pathInfos.size(); i++ )
527 rect |= m_data->pathInfos[i].scaledBoundingRect( sx, sy, scalePens );
528
529 return rect;
530}
531
533QSize QwtGraphic::sizeMetrics() const
534{
535 const QSizeF sz = defaultSize();
536 return QSize( qwtCeil( sz.width() ), qwtCeil( sz.height() ) );
537}
538
553 void QwtGraphic::setDefaultSize( const QSizeF& size )
554{
555 const double w = qwtMaxF( 0.0, size.width() );
556 const double h = qwtMaxF( 0.0, size.height() );
557
558 m_data->defaultSize = QSizeF( w, h );
559}
560
574QSizeF QwtGraphic::defaultSize() const
575{
576 if ( !m_data->defaultSize.isEmpty() )
577 return m_data->defaultSize;
578
579 return boundingRect().size();
580}
581
592qreal QwtGraphic::heightForWidth( qreal width ) const
593{
594 const QSizeF sz = defaultSize();
595 if ( sz.isEmpty() )
596 return 0.0;
597
598 return sz.height() * width / sz.width();
599}
600
611qreal QwtGraphic::widthForHeight( qreal height ) const
612{
613 const QSizeF sz = defaultSize();
614 if ( sz.isEmpty() )
615 return 0.0;
616
617 return sz.width() * height / sz.height();
618}
619
624 void QwtGraphic::render( QPainter* painter ) const
625{
626 renderGraphic( painter, NULL );
627}
628
629void QwtGraphic::renderGraphic( QPainter* painter, QTransform* initialTransform ) const
630{
631 if ( isNull() )
632 return;
633
634 const int numCommands = m_data->commands.size();
635 const QwtPainterCommand* commands = m_data->commands.constData();
636
637 const QTransform transform = painter->transform();
638
639 painter->save();
640
641 for ( int i = 0; i < numCommands; i++ )
642 {
643 qwtExecCommand( painter, commands[i],
644 m_data->renderHints, transform, initialTransform );
645 }
646
647 painter->restore();
648}
649
660 void QwtGraphic::render( QPainter* painter, const QSizeF& size,
661 Qt::AspectRatioMode aspectRatioMode ) const
662{
663 const QRectF r( 0.0, 0.0, size.width(), size.height() );
664 render( painter, r, aspectRatioMode );
665}
666
676 void QwtGraphic::render( QPainter* painter, const QRectF& rect,
677 Qt::AspectRatioMode aspectRatioMode ) const
678{
679 if ( isEmpty() || rect.isEmpty() )
680 return;
681
682 double sx = 1.0;
683 double sy = 1.0;
684
685 if ( m_data->pointRect.width() > 0.0 )
686 sx = rect.width() / m_data->pointRect.width();
687
688 if ( m_data->pointRect.height() > 0.0 )
689 sy = rect.height() / m_data->pointRect.height();
690
691 const bool scalePens = !m_data->renderHints.testFlag( RenderPensUnscaled );
692
693 for ( int i = 0; i < m_data->pathInfos.size(); i++ )
694 {
695 const PathInfo& info = m_data->pathInfos[i];
696
697 const double ssx = info.scaleFactorX(
698 m_data->pointRect, rect, scalePens );
699
700 if ( ssx > 0.0 )
701 sx = qwtMinF( sx, ssx );
702
703 const double ssy = info.scaleFactorY(
704 m_data->pointRect, rect, scalePens );
705
706 if ( ssy > 0.0 )
707 sy = qwtMinF( sy, ssy );
708 }
709
710 if ( aspectRatioMode == Qt::KeepAspectRatio )
711 {
712 const qreal s = qwtMinF( sx, sy );
713 sx = s;
714 sy = s;
715 }
716 else if ( aspectRatioMode == Qt::KeepAspectRatioByExpanding )
717 {
718 const qreal s = qwtMaxF( sx, sy );
719 sx = s;
720 sy = s;
721 }
722
723 QTransform tr;
724 tr.translate( rect.center().x() - 0.5 * sx * m_data->pointRect.width(),
725 rect.center().y() - 0.5 * sy * m_data->pointRect.height() );
726 tr.scale( sx, sy );
727 tr.translate( -m_data->pointRect.x(), -m_data->pointRect.y() );
728
729 const QTransform transform = painter->transform();
730
731 painter->setTransform( tr, true );
732
733 if ( !scalePens && transform.isScaling() )
734 {
735 // we don't want to scale pens according to sx/sy,
736 // but we want to apply the scaling from the
737 // painter transformation later
738
739 QTransform initialTransform;
740 initialTransform.scale( transform.m11(), transform.m22() );
741
742 renderGraphic( painter, &initialTransform );
743 }
744 else
745 {
746 renderGraphic( painter, NULL );
747 }
748
749 painter->setTransform( transform );
750}
751
762 void QwtGraphic::render( QPainter* painter,
763 const QPointF& pos, Qt::Alignment alignment ) const
764{
765 QRectF r( pos, defaultSize() );
766
767 if ( alignment & Qt::AlignLeft )
768 {
769 r.moveLeft( pos.x() );
770 }
771 else if ( alignment & Qt::AlignHCenter )
772 {
773 r.moveCenter( QPointF( pos.x(), r.center().y() ) );
774 }
775 else if ( alignment & Qt::AlignRight )
776 {
777 r.moveRight( pos.x() );
778 }
779
780 if ( alignment & Qt::AlignTop )
781 {
782 r.moveTop( pos.y() );
783 }
784 else if ( alignment & Qt::AlignVCenter )
785 {
786 r.moveCenter( QPointF( r.center().x(), pos.y() ) );
787 }
788 else if ( alignment & Qt::AlignBottom )
789 {
790 r.moveBottom( pos.y() );
791 }
792
793 render( painter, r );
794}
795
812QPixmap QwtGraphic::toPixmap( qreal devicePixelRatio ) const
813{
814 if ( isNull() )
815 return QPixmap();
816
817 const QSizeF sz = defaultSize();
818
819#if QT_VERSION >= 0x050000
820 if ( devicePixelRatio <= 0.0 )
821 devicePixelRatio = qwtDevicePixelRatio();
822
823 const int w = qwtCeil( sz.width() * devicePixelRatio );
824 const int h = qwtCeil( sz.height() * devicePixelRatio );
825
826 QPixmap pixmap( w, h );
827 pixmap.setDevicePixelRatio( devicePixelRatio );
828#else
829 Q_UNUSED( devicePixelRatio )
830
831 const int w = qwtCeil( sz.width() );
832 const int h = qwtCeil( sz.height() );
833
834 QPixmap pixmap( w, h );
835#endif
836
837 pixmap.fill( Qt::transparent );
838
839 const QRectF r( 0.0, 0.0, sz.width(), sz.height() );
840
841 QPainter painter( &pixmap );
842 render( &painter, r, Qt::KeepAspectRatio );
843 painter.end();
844
845 return pixmap;
846}
847
863QPixmap QwtGraphic::toPixmap( const QSize& size,
864 Qt::AspectRatioMode aspectRatioMode, qreal devicePixelRatio ) const
865{
866#if QT_VERSION >= 0x050000
867 if ( devicePixelRatio <= 0.0 )
868 devicePixelRatio = qwtDevicePixelRatio();
869
870 const int w = qwtCeil( size.width() * devicePixelRatio );
871 const int h = qwtCeil( size.height() * devicePixelRatio );
872
873 QPixmap pixmap( w, h );
874 pixmap.setDevicePixelRatio( devicePixelRatio );
875#else
876 Q_UNUSED( devicePixelRatio )
877 QPixmap pixmap( size );
878#endif
879 pixmap.fill( Qt::transparent );
880
881 const QRect r( 0, 0, size.width(), size.height() );
882
883 QPainter painter( &pixmap );
884 render( &painter, r, aspectRatioMode );
885 painter.end();
886
887 return pixmap;
888}
889
907QImage QwtGraphic::toImage( const QSize& size,
908 Qt::AspectRatioMode aspectRatioMode, qreal devicePixelRatio ) const
909{
910#if QT_VERSION >= 0x050000
911 if ( devicePixelRatio <= 0.0 )
912 devicePixelRatio = qwtDevicePixelRatio();
913
914 const int w = qwtCeil( size.width() * devicePixelRatio );
915 const int h = qwtCeil( size.height() * devicePixelRatio );
916
917 QImage image( w, h, QImage::Format_ARGB32_Premultiplied );
918 image.setDevicePixelRatio( devicePixelRatio );
919#else
920 Q_UNUSED( devicePixelRatio )
921 QImage image( size, QImage::Format_ARGB32_Premultiplied );
922#endif
923
924 image.fill( 0 );
925
926 const QRect r( 0, 0, size.width(), size.height() );
927
928 QPainter painter( &image );
929 render( &painter, r, aspectRatioMode );
930 painter.end();
931
932 return image;
933}
934
953QImage QwtGraphic::toImage( qreal devicePixelRatio ) const
954{
955 if ( isNull() )
956 return QImage();
957
958 const QSizeF sz = defaultSize();
959
960#if QT_VERSION >= 0x050000
961 if ( devicePixelRatio <= 0.0 )
962 devicePixelRatio = qwtDevicePixelRatio();
963
964 const int w = qwtCeil( sz.width() * devicePixelRatio );
965 const int h = qwtCeil( sz.height() * devicePixelRatio );
966
967 QImage image( w, h, QImage::Format_ARGB32 );
968 image.setDevicePixelRatio( devicePixelRatio );
969#else
970 Q_UNUSED( devicePixelRatio )
971
972 const int w = qwtCeil( sz.width() );
973 const int h = qwtCeil( sz.height() );
974
975 QImage image( w, h, QImage::Format_ARGB32 );
976#endif
977
978 image.fill( 0 );
979
980 const QRect r( 0, 0, sz.width(), sz.height() );
981
982 QPainter painter( &image );
983 render( &painter, r, Qt::KeepAspectRatio );
984 painter.end();
985
986 return image;
987}
988
995 void QwtGraphic::drawPath( const QPainterPath& path )
996{
997 const QPainter* painter = paintEngine()->painter();
998 if ( painter == NULL )
999 return;
1000
1001 m_data->commands += QwtPainterCommand( path );
1002 m_data->commandTypes |= QwtGraphic::VectorData;
1003
1004 if ( !path.isEmpty() )
1005 {
1006 const QPainterPath scaledPath = painter->transform().map( path );
1007
1008 QRectF pointRect = scaledPath.boundingRect();
1009 QRectF boundingRect = pointRect;
1010
1011 if ( painter->pen().style() != Qt::NoPen
1012 && painter->pen().brush().style() != Qt::NoBrush )
1013 {
1014 boundingRect = qwtStrokedPathRect( painter, path );
1015 }
1016
1017 updateControlPointRect( pointRect );
1018 updateBoundingRect( boundingRect );
1019
1020 m_data->pathInfos += PathInfo( pointRect,
1021 boundingRect, qwtHasScalablePen( painter ) );
1022 }
1023}
1024
1034 void QwtGraphic::drawPixmap( const QRectF& rect,
1035 const QPixmap& pixmap, const QRectF& subRect )
1036{
1037 const QPainter* painter = paintEngine()->painter();
1038 if ( painter == NULL )
1039 return;
1040
1041 m_data->commands += QwtPainterCommand( rect, pixmap, subRect );
1042 m_data->commandTypes |= QwtGraphic::RasterData;
1043
1044 const QRectF r = painter->transform().mapRect( rect );
1045 updateControlPointRect( r );
1046 updateBoundingRect( r );
1047}
1048
1059 void QwtGraphic::drawImage( const QRectF& rect, const QImage& image,
1060 const QRectF& subRect, Qt::ImageConversionFlags flags )
1061{
1062 const QPainter* painter = paintEngine()->painter();
1063 if ( painter == NULL )
1064 return;
1065
1066 m_data->commands += QwtPainterCommand( rect, image, subRect, flags );
1067 m_data->commandTypes |= QwtGraphic::RasterData;
1068
1069 const QRectF r = painter->transform().mapRect( rect );
1070
1071 updateControlPointRect( r );
1072 updateBoundingRect( r );
1073}
1074
1081 void QwtGraphic::updateState( const QPaintEngineState& state )
1082{
1083 m_data->commands += QwtPainterCommand( state );
1084
1085 if ( state.state() & QPaintEngine::DirtyTransform )
1086 {
1087 if ( !( m_data->commandTypes & QwtGraphic::Transformation ) )
1088 {
1089 /*
1090 QTransform::isScaling() returns true for all type
1091 of transformations beside simple translations
1092 even if it is f.e a rotation
1093 */
1094 if ( state.transform().isScaling() )
1095 m_data->commandTypes |= QwtGraphic::Transformation;
1096 }
1097 }
1098}
1099
1100void QwtGraphic::updateBoundingRect( const QRectF& rect )
1101{
1102 QRectF br = rect;
1103
1104 const QPainter* painter = paintEngine()->painter();
1105 if ( painter && painter->hasClipping() )
1106 {
1107 QRectF cr = painter->clipRegion().boundingRect();
1108 cr = painter->transform().mapRect( cr );
1109
1110 br &= cr;
1111 }
1112
1113 if ( m_data->boundingRect.width() < 0 )
1114 m_data->boundingRect = br;
1115 else
1116 m_data->boundingRect |= br;
1117}
1118
1119void QwtGraphic::updateControlPointRect( const QRectF& rect )
1120{
1121 if ( m_data->pointRect.width() < 0.0 )
1122 m_data->pointRect = rect;
1123 else
1124 m_data->pointRect |= rect;
1125}
1126
1131 const QVector< QwtPainterCommand >& QwtGraphic::commands() const
1132{
1133 return m_data->commands;
1134}
1135
1142 void QwtGraphic::setCommands( const QVector< QwtPainterCommand >& commands )
1143{
1144 reset();
1145
1146 const int numCommands = commands.size();
1147 if ( numCommands <= 0 )
1148 return;
1149
1150 // to calculate a proper bounding rectangle we don't simply copy
1151 // the commands.
1152
1153 const QwtPainterCommand* cmds = commands.constData();
1154
1155 const QTransform noTransform;
1156 const RenderHints noRenderHints;
1157
1158 QPainter painter( this );
1159 for ( int i = 0; i < numCommands; i++ )
1160 qwtExecCommand( &painter, cmds[i], noRenderHints, noTransform, NULL );
1161
1162 painter.end();
1163}
QVector< QwtPainterCommand >
QwtGraphic
A paint device for scalable graphics.
Definition qwt_graphic.h:76
QwtGraphic::heightForWidth
qreal heightForWidth(qreal width) const
Definition qwt_graphic.cpp:592
QwtGraphic::~QwtGraphic
virtual ~QwtGraphic()
Destructor.
Definition qwt_graphic.cpp:374
QwtGraphic::updateState
virtual void updateState(const QPaintEngineState &) override
Store a state command in the command list.
Definition qwt_graphic.cpp:1081
QwtGraphic::testRenderHint
bool testRenderHint(RenderHint) const
Definition qwt_graphic.cpp:458
QwtGraphic::RenderHint
RenderHint
Definition qwt_graphic.h:83
QwtGraphic::RenderPensUnscaled
@ RenderPensUnscaled
Definition qwt_graphic.h:96
QwtGraphic::isEmpty
bool isEmpty() const
Definition qwt_graphic.cpp:422
QwtGraphic::reset
void reset()
Clear all stored commands.
Definition qwt_graphic.cpp:397
QwtGraphic::QwtGraphic
QwtGraphic()
Constructor.
Definition qwt_graphic.cpp:355
QwtGraphic::setRenderHint
void setRenderHint(RenderHint, bool on=true)
Definition qwt_graphic.cpp:443
QwtGraphic::isNull
bool isNull() const
Definition qwt_graphic.cpp:413
QwtGraphic::operator=
QwtGraphic & operator=(const QwtGraphic &)
Assignment operator.
Definition qwt_graphic.cpp:385
QwtGraphic::toImage
QImage toImage(qreal devicePixelRatio=0.0) const
Convert the graphic to a QImage.
Definition qwt_graphic.cpp:953
QwtGraphic::toPixmap
QPixmap toPixmap(qreal devicePixelRatio=0.0) const
Convert the graphic to a QPixmap.
Definition qwt_graphic.cpp:812
QwtGraphic::widthForHeight
qreal widthForHeight(qreal height) const
Definition qwt_graphic.cpp:611
QwtGraphic::RenderHints
QFlags< RenderHint > RenderHints
Definition qwt_graphic.h:99
QwtGraphic::CommandTypes
QFlags< CommandType > CommandTypes
Definition qwt_graphic.h:117
QwtGraphic::controlPointRect
QRectF controlPointRect() const
Definition qwt_graphic.cpp:493
QwtGraphic::drawPixmap
virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) override
Store a pixmap command in the command list.
Definition qwt_graphic.cpp:1034
QwtGraphic::commandTypes
CommandTypes commandTypes() const
Definition qwt_graphic.cpp:430
QwtGraphic::VectorData
@ VectorData
The graphic contains scalable vector data.
Definition qwt_graphic.h:108
QwtGraphic::Transformation
@ Transformation
The graphic contains transformations beyond simple translations.
Definition qwt_graphic.h:114
QwtGraphic::RasterData
@ RasterData
The graphic contains raster data ( QPixmap or QImage )
Definition qwt_graphic.h:111
QwtGraphic::defaultSize
QSizeF defaultSize() const
Default size.
Definition qwt_graphic.cpp:574
QwtGraphic::sizeMetrics
virtual QSize sizeMetrics() const override
Definition qwt_graphic.cpp:533
QwtGraphic::setDefaultSize
void setDefaultSize(const QSizeF &)
Set a default size.
Definition qwt_graphic.cpp:553
QwtGraphic::setCommands
void setCommands(const QVector< QwtPainterCommand > &)
Append paint commands.
Definition qwt_graphic.cpp:1142
QwtGraphic::commands
const QVector< QwtPainterCommand > & commands() const
Definition qwt_graphic.cpp:1131
QwtGraphic::drawPath
virtual void drawPath(const QPainterPath &) override
Definition qwt_graphic.cpp:995
QwtGraphic::scaledBoundingRect
QRectF scaledBoundingRect(qreal sx, qreal sy) const
Calculate the target rectangle for scaling the graphic.
Definition qwt_graphic.cpp:514
QwtGraphic::renderHints
RenderHints renderHints() const
Definition qwt_graphic.cpp:464
QwtGraphic::boundingRect
QRectF boundingRect() const
Definition qwt_graphic.cpp:477
QwtGraphic::render
void render(QPainter *) const
Replay all recorded painter commands.
Definition qwt_graphic.cpp:624
QwtGraphic::drawImage
virtual void drawImage(const QRectF &, const QImage &, const QRectF &, Qt::ImageConversionFlags) override
Store a image command in the command list.
Definition qwt_graphic.cpp:1059
QwtNullPaintDevice::PathMode
@ PathMode
Definition qwt_null_paintdevice.h:69
QwtNullPaintDevice::paintEngine
virtual QPaintEngine * paintEngine() const override
See QPaintDevice::paintEngine()
Definition qwt_null_paintdevice.cpp:401
QwtNullPaintDevice::setMode
void setMode(Mode)
Definition qwt_null_paintdevice.cpp:386
QwtNullPaintDevice::mode
Mode mode() const
Definition qwt_null_paintdevice.cpp:395
QwtPainterCommand
Definition qwt_painter_command.h:33
QwtPainterCommand::path
QPainterPath * path()
Definition qwt_painter_command.cpp:216
QwtPainterCommand::Pixmap
@ Pixmap
Draw a QPixmap.
Definition qwt_painter_command.h:45
QwtPainterCommand::Path
@ Path
Draw a QPainterPath.
Definition qwt_painter_command.h:42
QwtPainterCommand::Image
@ Image
Draw a QImage.
Definition qwt_painter_command.h:48
QwtPainterCommand::State
@ State
QPainter state change.
Definition qwt_painter_command.h:51
QwtPainterCommand::type
Type type() const
Definition qwt_painter_command.h:142
QwtPainterCommand::pixmapData
PixmapData * pixmapData()
Definition qwt_painter_command.cpp:222
QwtPainterCommand::imageData
ImageData * imageData()
Definition qwt_painter_command.cpp:228
QwtPainterCommand::stateData
StateData * stateData()
Definition qwt_painter_command.cpp:234