Qwt User's Guide: qwt_graphic.cpp Source File

Qwt User's Guide 6.2.0

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
25 static inline qreal qwtDevicePixelRatio()
26 {
27 return qGuiApp ? qGuiApp->devicePixelRatio() : 1.0;
28 }
29
30 #endif
31
32 static 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
54 static 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
80 static 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
216 class 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
329 class 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
355 QwtGraphic::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
374 QwtGraphic::~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
477 QRectF QwtGraphic::boundingRect() const
478 {
479 if ( m_data->boundingRect.width() < 0 )
480 return QRectF();
481
482 return m_data->boundingRect;
483 }
484
493 QRectF QwtGraphic::controlPointRect() const
494 {
495 if ( m_data->pointRect.width() < 0 )
496 return QRectF();
497
498 return m_data->pointRect;
499 }
500
514 QRectF 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
533 QSize 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
574 QSizeF QwtGraphic::defaultSize() const
575 {
576 if ( !m_data->defaultSize.isEmpty() )
577 return m_data->defaultSize;
578
579 return boundingRect().size();
580 }
581
592 qreal 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
611 qreal 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
629 void 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
812 QPixmap QwtGraphic::toPixmap( qreal devicePixelRatio ) const
813 {
814 if ( isNull() )
815 return QPixmap();
816
817 const QSizeF sz = defaultSize();
818
819 const int w = qwtCeil( sz.width() );
820 const int h = qwtCeil( sz.height() );
821
822 QPixmap pixmap( w, h );
823
824 #if QT_VERSION >= 0x050000
825 if ( devicePixelRatio <= 0.0 )
826 devicePixelRatio = qwtDevicePixelRatio();
827
828 pixmap.setDevicePixelRatio( devicePixelRatio );
829 #else
830 Q_UNUSED( devicePixelRatio )
831 #endif
832
833 pixmap.fill( Qt::transparent );
834
835 const QRectF r( 0.0, 0.0, sz.width(), sz.height() );
836
837 QPainter painter( &pixmap );
838 render( &painter, r, Qt::KeepAspectRatio );
839 painter.end();
840
841 return pixmap;
842 }
843
859 QPixmap QwtGraphic::toPixmap( const QSize& size,
860 Qt::AspectRatioMode aspectRatioMode, qreal devicePixelRatio ) const
861 {
862 QPixmap pixmap( size );
863
864 #if QT_VERSION >= 0x050000
865 if ( devicePixelRatio <= 0.0 )
866 devicePixelRatio = qwtDevicePixelRatio();
867
868 pixmap.setDevicePixelRatio( devicePixelRatio );
869 #else
870 Q_UNUSED( devicePixelRatio )
871 #endif
872 pixmap.fill( Qt::transparent );
873
874 const QRect r( 0, 0, size.width(), size.height() );
875
876 QPainter painter( &pixmap );
877 render( &painter, r, aspectRatioMode );
878 painter.end();
879
880 return pixmap;
881 }
882
900 QImage QwtGraphic::toImage( const QSize& size,
901 Qt::AspectRatioMode aspectRatioMode, qreal devicePixelRatio ) const
902 {
903 #if QT_VERSION >= 0x050000
904 if ( devicePixelRatio <= 0.0 )
905 devicePixelRatio = qwtDevicePixelRatio();
906
907 QImage image( size* devicePixelRatio, QImage::Format_ARGB32_Premultiplied );
908 image.setDevicePixelRatio( devicePixelRatio );
909 #else
910 Q_UNUSED( devicePixelRatio )
911 QImage image( size, QImage::Format_ARGB32_Premultiplied );
912 #endif
913
914 image.fill( 0 );
915
916 const QRect r( 0, 0, size.width(), size.height() );
917
918 QPainter painter( &image );
919 render( &painter, r, aspectRatioMode );
920 painter.end();
921
922 return image;
923 }
924
943 QImage QwtGraphic::toImage( qreal devicePixelRatio ) const
944 {
945 if ( isNull() )
946 return QImage();
947
948 const QSizeF sz = defaultSize();
949
950 int w = qwtCeil( sz.width() );
951 int h = qwtCeil( sz.height() );
952
953 #if QT_VERSION >= 0x050000
954 if ( devicePixelRatio <= 0.0 )
955 devicePixelRatio = qwtDevicePixelRatio();
956
957 w *= devicePixelRatio;
958 h *= devicePixelRatio;
959
960 QImage image( w, h, QImage::Format_ARGB32 );
961 image.setDevicePixelRatio( devicePixelRatio );
962 #else
963 Q_UNUSED( devicePixelRatio )
964 QImage image( w, h, QImage::Format_ARGB32 );
965 #endif
966
967 image.fill( 0 );
968
969 const QRect r( 0, 0, sz.width(), sz.height() );
970
971 QPainter painter( &image );
972 render( &painter, r, Qt::KeepAspectRatio );
973 painter.end();
974
975 return image;
976 }
977
984 void QwtGraphic::drawPath( const QPainterPath& path )
985 {
986 const QPainter* painter = paintEngine()->painter();
987 if ( painter == NULL )
988 return;
989
990 m_data->commands += QwtPainterCommand( path );
991 m_data->commandTypes |= QwtGraphic::VectorData;
992
993 if ( !path.isEmpty() )
994 {
995 const QPainterPath scaledPath = painter->transform().map( path );
996
997 QRectF pointRect = scaledPath.boundingRect();
998 QRectF boundingRect = pointRect;
999
1000 if ( painter->pen().style() != Qt::NoPen
1001 && painter->pen().brush().style() != Qt::NoBrush )
1002 {
1003 boundingRect = qwtStrokedPathRect( painter, path );
1004 }
1005
1006 updateControlPointRect( pointRect );
1007 updateBoundingRect( boundingRect );
1008
1009 m_data->pathInfos += PathInfo( pointRect,
1010 boundingRect, qwtHasScalablePen( painter ) );
1011 }
1012 }
1013
1023 void QwtGraphic::drawPixmap( const QRectF& rect,
1024 const QPixmap& pixmap, const QRectF& subRect )
1025 {
1026 const QPainter* painter = paintEngine()->painter();
1027 if ( painter == NULL )
1028 return;
1029
1030 m_data->commands += QwtPainterCommand( rect, pixmap, subRect );
1031 m_data->commandTypes |= QwtGraphic::RasterData;
1032
1033 const QRectF r = painter->transform().mapRect( rect );
1034 updateControlPointRect( r );
1035 updateBoundingRect( r );
1036 }
1037
1048 void QwtGraphic::drawImage( const QRectF& rect, const QImage& image,
1049 const QRectF& subRect, Qt::ImageConversionFlags flags )
1050 {
1051 const QPainter* painter = paintEngine()->painter();
1052 if ( painter == NULL )
1053 return;
1054
1055 m_data->commands += QwtPainterCommand( rect, image, subRect, flags );
1056 m_data->commandTypes |= QwtGraphic::RasterData;
1057
1058 const QRectF r = painter->transform().mapRect( rect );
1059
1060 updateControlPointRect( r );
1061 updateBoundingRect( r );
1062 }
1063
1070 void QwtGraphic::updateState( const QPaintEngineState& state )
1071 {
1072 m_data->commands += QwtPainterCommand( state );
1073
1074 if ( state.state() & QPaintEngine::DirtyTransform )
1075 {
1076 if ( !( m_data->commandTypes & QwtGraphic::Transformation ) )
1077 {
1078 /*
1079 QTransform::isScaling() returns true for all type
1080 of transformations beside simple translations
1081 even if it is f.e a rotation
1082 */
1083 if ( state.transform().isScaling() )
1084 m_data->commandTypes |= QwtGraphic::Transformation;
1085 }
1086 }
1087 }
1088
1089 void QwtGraphic::updateBoundingRect( const QRectF& rect )
1090 {
1091 QRectF br = rect;
1092
1093 const QPainter* painter = paintEngine()->painter();
1094 if ( painter && painter->hasClipping() )
1095 {
1096 QRectF cr = painter->clipRegion().boundingRect();
1097 cr = painter->transform().mapRect( cr );
1098
1099 br &= cr;
1100 }
1101
1102 if ( m_data->boundingRect.width() < 0 )
1103 m_data->boundingRect = br;
1104 else
1105 m_data->boundingRect |= br;
1106 }
1107
1108 void QwtGraphic::updateControlPointRect( const QRectF& rect )
1109 {
1110 if ( m_data->pointRect.width() < 0.0 )
1111 m_data->pointRect = rect;
1112 else
1113 m_data->pointRect |= rect;
1114 }
1115
1120 const QVector< QwtPainterCommand >& QwtGraphic::commands() const
1121 {
1122 return m_data->commands;
1123 }
1124
1131 void QwtGraphic::setCommands( const QVector< QwtPainterCommand >& commands )
1132 {
1133 reset();
1134
1135 const int numCommands = commands.size();
1136 if ( numCommands <= 0 )
1137 return;
1138
1139 // to calculate a proper bounding rectangle we don't simply copy
1140 // the commands.
1141
1142 const QwtPainterCommand* cmds = commands.constData();
1143
1144 const QTransform noTransform;
1145 const RenderHints noRenderHints;
1146
1147 QPainter painter( this );
1148 for ( int i = 0; i < numCommands; i++ )
1149 qwtExecCommand( &painter, cmds[i], noRenderHints, noTransform, NULL );
1150
1151 painter.end();
1152 }
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:1070
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:943
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:1023
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:1131
QwtGraphic::commands
const QVector< QwtPainterCommand > & commands() const
Definition: qwt_graphic.cpp:1120
QwtGraphic::drawPath
virtual void drawPath(const QPainterPath &) override
Definition: qwt_graphic.cpp:984
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:1048
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