source: ntrip/trunk/BNC/qwt/qwt_symbol.cpp@ 9383

Last change on this file since 9383 was 9383, checked in by stoecker, 3 years ago

update to qwt verion 6.1.1 to fix build with newer Qt5

File size: 43.2 KB
Line 
1/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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_symbol.h"
11#include "qwt_painter.h"
12#include "qwt_graphic.h"
13#include <qapplication.h>
14#include <qpainter.h>
15#include <qpainterpath.h>
16#include <qpixmap.h>
17#include <qpaintengine.h>
18#include <qmath.h>
19#ifndef QWT_NO_SVG
20#include <qsvgrenderer.h>
21#endif
22
23namespace QwtTriangle
24{
25 enum Type
26 {
27 Left,
28 Right,
29 Up,
30 Down
31 };
32}
33
34static QwtGraphic qwtPathGraphic( const QPainterPath &path,
35 const QPen &pen, const QBrush& brush )
36{
37 QwtGraphic graphic;
38 graphic.setRenderHint( QwtGraphic::RenderPensUnscaled );
39
40 QPainter painter( &graphic );
41 painter.setPen( pen );
42 painter.setBrush( brush );
43 painter.drawPath( path );
44 painter.end();
45
46 return graphic;
47}
48
49static inline QRectF qwtScaledBoundingRect(
50 const QwtGraphic &graphic, const QSizeF size )
51{
52 QSizeF scaledSize = size;
53 if ( scaledSize.isEmpty() )
54 scaledSize = graphic.defaultSize();
55
56 const QSizeF sz = graphic.controlPointRect().size();
57
58 double sx = 1.0;
59 if ( sz.width() > 0.0 )
60 sx = scaledSize.width() / sz.width();
61
62 double sy = 1.0;
63 if ( sz.height() > 0.0 )
64 sy = scaledSize.height() / sz.height();
65
66 return graphic.scaledBoundingRect( sx, sy );
67}
68
69static inline void qwtDrawPixmapSymbols( QPainter *painter,
70 const QPointF *points, int numPoints, const QwtSymbol &symbol )
71{
72 QSize size = symbol.size();
73 if ( size.isEmpty() )
74 size = symbol.pixmap().size();
75
76 const QTransform transform = painter->transform();
77 if ( transform.isScaling() )
78 {
79 const QRect r( 0, 0, size.width(), size.height() );
80 size = transform.mapRect( r ).size();
81 }
82
83 QPixmap pm = symbol.pixmap();
84 if ( pm.size() != size )
85 pm = pm.scaled( size );
86
87 QPointF pinPoint( 0.5 * size.width(), 0.5 * size.height() );
88 if ( symbol.isPinPointEnabled() )
89 pinPoint = symbol.pinPoint();
90
91 painter->resetTransform();
92
93 for ( int i = 0; i < numPoints; i++ )
94 {
95 const QPointF pos = transform.map( points[i] ) - pinPoint;
96
97 QwtPainter::drawPixmap( painter,
98 QRect( pos.toPoint(), pm.size() ), pm );
99 }
100}
101
102#ifndef QWT_NO_SVG
103
104static inline void qwtDrawSvgSymbols( QPainter *painter,
105 const QPointF *points, int numPoints,
106 QSvgRenderer *renderer, const QwtSymbol &symbol )
107{
108 if ( renderer == NULL || !renderer->isValid() )
109 return;
110
111 const QRectF viewBox = renderer->viewBoxF();
112 if ( viewBox.isEmpty() )
113 return;
114
115 QSizeF sz = symbol.size();
116 if ( !sz.isValid() )
117 sz = viewBox.size();
118
119 const double sx = sz.width() / viewBox.width();
120 const double sy = sz.height() / viewBox.height();
121
122 QPointF pinPoint = viewBox.center();
123 if ( symbol.isPinPointEnabled() )
124 pinPoint = symbol.pinPoint();
125
126 const double dx = sx * ( pinPoint.x() - viewBox.left() );
127 const double dy = sy * ( pinPoint.y() - viewBox.top() );
128
129 for ( int i = 0; i < numPoints; i++ )
130 {
131 const double x = points[i].x() - dx;
132 const double y = points[i].y() - dy;
133
134 renderer->render( painter,
135 QRectF( x, y, sz.width(), sz.height() ) );
136 }
137}
138
139#endif
140
141static inline void qwtDrawGraphicSymbols( QPainter *painter,
142 const QPointF *points, int numPoints, const QwtGraphic &graphic,
143 const QwtSymbol &symbol )
144{
145 const QRectF pointRect = graphic.controlPointRect();
146 if ( pointRect.isEmpty() )
147 return;
148
149 double sx = 1.0;
150 double sy = 1.0;
151
152 const QSize sz = symbol.size();
153 if ( sz.isValid() )
154 {
155 sx = sz.width() / pointRect.width();
156 sy = sz.height() / pointRect.height();
157 }
158
159 QPointF pinPoint = pointRect.center();
160 if ( symbol.isPinPointEnabled() )
161 pinPoint = symbol.pinPoint();
162
163 const QTransform transform = painter->transform();
164
165 for ( int i = 0; i < numPoints; i++ )
166 {
167 QTransform tr = transform;
168 tr.translate( points[i].x(), points[i].y() );
169 tr.scale( sx, sy );
170 tr.translate( -pinPoint.x(), -pinPoint.y() );
171
172 painter->setTransform( tr );
173
174 graphic.render( painter );
175 }
176
177 painter->setTransform( transform );
178}
179
180static inline void qwtDrawEllipseSymbols( QPainter *painter,
181 const QPointF *points, int numPoints, const QwtSymbol &symbol )
182{
183 painter->setBrush( symbol.brush() );
184 painter->setPen( symbol.pen() );
185
186 const QSize size = symbol.size();
187
188 if ( QwtPainter::roundingAlignment( painter ) )
189 {
190 const int sw = size.width();
191 const int sh = size.height();
192 const int sw2 = size.width() / 2;
193 const int sh2 = size.height() / 2;
194
195 for ( int i = 0; i < numPoints; i++ )
196 {
197 const int x = qRound( points[i].x() );
198 const int y = qRound( points[i].y() );
199
200 const QRectF r( x - sw2, y - sh2, sw, sh );
201 QwtPainter::drawEllipse( painter, r );
202 }
203 }
204 else
205 {
206 const double sw = size.width();
207 const double sh = size.height();
208 const double sw2 = 0.5 * size.width();
209 const double sh2 = 0.5 * size.height();
210
211 for ( int i = 0; i < numPoints; i++ )
212 {
213 const double x = points[i].x();
214 const double y = points[i].y();
215
216 const QRectF r( x - sw2, y - sh2, sw, sh );
217 QwtPainter::drawEllipse( painter, r );
218 }
219 }
220}
221
222static inline void qwtDrawRectSymbols( QPainter *painter,
223 const QPointF *points, int numPoints, const QwtSymbol &symbol )
224{
225 const QSize size = symbol.size();
226
227 QPen pen = symbol.pen();
228 pen.setJoinStyle( Qt::MiterJoin );
229 painter->setPen( pen );
230 painter->setBrush( symbol.brush() );
231 painter->setRenderHint( QPainter::Antialiasing, false );
232
233 if ( QwtPainter::roundingAlignment( painter ) )
234 {
235 const int sw = size.width();
236 const int sh = size.height();
237 const int sw2 = size.width() / 2;
238 const int sh2 = size.height() / 2;
239
240 for ( int i = 0; i < numPoints; i++ )
241 {
242 const int x = qRound( points[i].x() );
243 const int y = qRound( points[i].y() );
244
245 const QRect r( x - sw2, y - sh2, sw, sh );
246 QwtPainter::drawRect( painter, r );
247 }
248 }
249 else
250 {
251 const double sw = size.width();
252 const double sh = size.height();
253 const double sw2 = 0.5 * size.width();
254 const double sh2 = 0.5 * size.height();
255
256 for ( int i = 0; i < numPoints; i++ )
257 {
258 const double x = points[i].x();
259 const double y = points[i].y();
260
261 const QRectF r( x - sw2, y - sh2, sw, sh );
262 QwtPainter::drawRect( painter, r );
263 }
264 }
265}
266
267static inline void qwtDrawDiamondSymbols( QPainter *painter,
268 const QPointF *points, int numPoints, const QwtSymbol &symbol )
269{
270 const QSize size = symbol.size();
271
272 QPen pen = symbol.pen();
273 pen.setJoinStyle( Qt::MiterJoin );
274 painter->setPen( pen );
275 painter->setBrush( symbol.brush() );
276
277 if ( QwtPainter::roundingAlignment( painter ) )
278 {
279 for ( int i = 0; i < numPoints; i++ )
280 {
281 const int x = qRound( points[i].x() );
282 const int y = qRound( points[i].y() );
283
284 const int x1 = x - size.width() / 2;
285 const int y1 = y - size.height() / 2;
286 const int x2 = x1 + size.width();
287 const int y2 = y1 + size.height();
288
289 QPolygonF polygon;
290 polygon += QPointF( x, y1 );
291 polygon += QPointF( x1, y );
292 polygon += QPointF( x, y2 );
293 polygon += QPointF( x2, y );
294
295 QwtPainter::drawPolygon( painter, polygon );
296 }
297 }
298 else
299 {
300 for ( int i = 0; i < numPoints; i++ )
301 {
302 const QPointF &pos = points[i];
303
304 const double x1 = pos.x() - 0.5 * size.width();
305 const double y1 = pos.y() - 0.5 * size.height();
306 const double x2 = x1 + size.width();
307 const double y2 = y1 + size.height();
308
309 QPolygonF polygon;
310 polygon += QPointF( pos.x(), y1 );
311 polygon += QPointF( x2, pos.y() );
312 polygon += QPointF( pos.x(), y2 );
313 polygon += QPointF( x1, pos.y() );
314
315 QwtPainter::drawPolygon( painter, polygon );
316 }
317 }
318}
319
320static inline void qwtDrawTriangleSymbols(
321 QPainter *painter, QwtTriangle::Type type,
322 const QPointF *points, int numPoints,
323 const QwtSymbol &symbol )
324{
325 const QSize size = symbol.size();
326
327 QPen pen = symbol.pen();
328 pen.setJoinStyle( Qt::MiterJoin );
329 painter->setPen( pen );
330
331 painter->setBrush( symbol.brush() );
332
333 const bool doAlign = QwtPainter::roundingAlignment( painter );
334
335 double sw2 = 0.5 * size.width();
336 double sh2 = 0.5 * size.height();
337
338 if ( doAlign )
339 {
340 sw2 = qFloor( sw2 );
341 sh2 = qFloor( sh2 );
342 }
343
344 QPolygonF triangle( 3 );
345 QPointF *trianglePoints = triangle.data();
346
347 for ( int i = 0; i < numPoints; i++ )
348 {
349 const QPointF &pos = points[i];
350
351 double x = pos.x();
352 double y = pos.y();
353
354 if ( doAlign )
355 {
356 x = qRound( x );
357 y = qRound( y );
358 }
359
360 const double x1 = x - sw2;
361 const double x2 = x1 + size.width();
362 const double y1 = y - sh2;
363 const double y2 = y1 + size.height();
364
365 switch ( type )
366 {
367 case QwtTriangle::Left:
368 {
369 trianglePoints[0].rx() = x2;
370 trianglePoints[0].ry() = y1;
371
372 trianglePoints[1].rx() = x1;
373 trianglePoints[1].ry() = y;
374
375 trianglePoints[2].rx() = x2;
376 trianglePoints[2].ry() = y2;
377
378 break;
379 }
380 case QwtTriangle::Right:
381 {
382 trianglePoints[0].rx() = x1;
383 trianglePoints[0].ry() = y1;
384
385 trianglePoints[1].rx() = x2;
386 trianglePoints[1].ry() = y;
387
388 trianglePoints[2].rx() = x1;
389 trianglePoints[2].ry() = y2;
390
391 break;
392 }
393 case QwtTriangle::Up:
394 {
395 trianglePoints[0].rx() = x1;
396 trianglePoints[0].ry() = y2;
397
398 trianglePoints[1].rx() = x;
399 trianglePoints[1].ry() = y1;
400
401 trianglePoints[2].rx() = x2;
402 trianglePoints[2].ry() = y2;
403
404 break;
405 }
406 case QwtTriangle::Down:
407 {
408 trianglePoints[0].rx() = x1;
409 trianglePoints[0].ry() = y1;
410
411 trianglePoints[1].rx() = x;
412 trianglePoints[1].ry() = y2;
413
414 trianglePoints[2].rx() = x2;
415 trianglePoints[2].ry() = y1;
416
417 break;
418 }
419 }
420 QwtPainter::drawPolygon( painter, triangle );
421 }
422}
423
424static inline void qwtDrawLineSymbols(
425 QPainter *painter, int orientations,
426 const QPointF *points, int numPoints, const QwtSymbol &symbol )
427{
428 const QSize size = symbol.size();
429
430 int off = 0;
431
432 QPen pen = symbol.pen();
433 if ( pen.width() > 1 )
434 {
435 pen.setCapStyle( Qt::FlatCap );
436 off = 1;
437 }
438
439 painter->setPen( pen );
440 painter->setRenderHint( QPainter::Antialiasing, false );
441
442 if ( QwtPainter::roundingAlignment( painter ) )
443 {
444 const int sw = qFloor( size.width() );
445 const int sh = qFloor( size.height() );
446 const int sw2 = size.width() / 2;
447 const int sh2 = size.height() / 2;
448
449 for ( int i = 0; i < numPoints; i++ )
450 {
451 if ( orientations & Qt::Horizontal )
452 {
453 const int x = qRound( points[i].x() ) - sw2;
454 const int y = qRound( points[i].y() );
455
456 QwtPainter::drawLine( painter, x, y, x + sw + off, y );
457 }
458 if ( orientations & Qt::Vertical )
459 {
460 const int x = qRound( points[i].x() );
461 const int y = qRound( points[i].y() ) - sh2;
462
463 QwtPainter::drawLine( painter, x, y, x, y + sh + off );
464 }
465 }
466 }
467 else
468 {
469 const double sw = size.width();
470 const double sh = size.height();
471 const double sw2 = 0.5 * size.width();
472 const double sh2 = 0.5 * size.height();
473
474 for ( int i = 0; i < numPoints; i++ )
475 {
476 if ( orientations & Qt::Horizontal )
477 {
478 const double x = points[i].x() - sw2;
479 const double y = points[i].y();
480
481 QwtPainter::drawLine( painter, x, y, x + sw, y );
482 }
483 if ( orientations & Qt::Vertical )
484 {
485 const double y = points[i].y() - sh2;
486 const double x = points[i].x();
487
488 QwtPainter::drawLine( painter, x, y, x, y + sh );
489 }
490 }
491 }
492}
493
494static inline void qwtDrawXCrossSymbols( QPainter *painter,
495 const QPointF *points, int numPoints, const QwtSymbol &symbol )
496{
497 const QSize size = symbol.size();
498 int off = 0;
499
500 QPen pen = symbol.pen();
501 if ( pen.width() > 1 )
502 {
503 pen.setCapStyle( Qt::FlatCap );
504 off = 1;
505 }
506 painter->setPen( pen );
507
508
509 if ( QwtPainter::roundingAlignment( painter ) )
510 {
511 const int sw = size.width();
512 const int sh = size.height();
513 const int sw2 = size.width() / 2;
514 const int sh2 = size.height() / 2;
515
516 for ( int i = 0; i < numPoints; i++ )
517 {
518 const QPointF &pos = points[i];
519
520 const int x = qRound( pos.x() );
521 const int y = qRound( pos.y() );
522
523 const int x1 = x - sw2;
524 const int x2 = x1 + sw + off;
525 const int y1 = y - sh2;
526 const int y2 = y1 + sh + off;
527
528 QwtPainter::drawLine( painter, x1, y1, x2, y2 );
529 QwtPainter::drawLine( painter, x2, y1, x1, y2 );
530 }
531 }
532 else
533 {
534 const double sw = size.width();
535 const double sh = size.height();
536 const double sw2 = 0.5 * size.width();
537 const double sh2 = 0.5 * size.height();
538
539 for ( int i = 0; i < numPoints; i++ )
540 {
541 const QPointF &pos = points[i];
542
543 const double x1 = pos.x() - sw2;
544 const double x2 = x1 + sw;
545 const double y1 = pos.y() - sh2;
546 const double y2 = y1 + sh;
547
548 QwtPainter::drawLine( painter, x1, y1, x2, y2 );
549 QwtPainter::drawLine( painter, x1, y2, x2, y1 );
550 }
551 }
552}
553
554static inline void qwtDrawStar1Symbols( QPainter *painter,
555 const QPointF *points, int numPoints, const QwtSymbol &symbol )
556{
557 const QSize size = symbol.size();
558 painter->setPen( symbol.pen() );
559
560 if ( QwtPainter::roundingAlignment( painter ) )
561 {
562 QRect r( 0, 0, size.width(), size.height() );
563
564 for ( int i = 0; i < numPoints; i++ )
565 {
566 r.moveCenter( points[i].toPoint() );
567
568 const double sqrt1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
569
570 const double d1 = r.width() / 2.0 * ( 1.0 - sqrt1_2 );
571
572 QwtPainter::drawLine( painter,
573 qRound( r.left() + d1 ), qRound( r.top() + d1 ),
574 qRound( r.right() - d1 ), qRound( r.bottom() - d1 ) );
575 QwtPainter::drawLine( painter,
576 qRound( r.left() + d1 ), qRound( r.bottom() - d1 ),
577 qRound( r .right() - d1), qRound( r.top() + d1 ) );
578
579 const QPoint c = r.center();
580
581 QwtPainter::drawLine( painter,
582 c.x(), r.top(), c.x(), r.bottom() );
583 QwtPainter::drawLine( painter,
584 r.left(), c.y(), r.right(), c.y() );
585 }
586 }
587 else
588 {
589 QRectF r( 0, 0, size.width(), size.height() );
590
591 for ( int i = 0; i < numPoints; i++ )
592 {
593 r.moveCenter( points[i] );
594
595 const double sqrt1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
596
597 const QPointF c = r.center();
598 const double d1 = r.width() / 2.0 * ( 1.0 - sqrt1_2 );
599
600 QwtPainter::drawLine( painter,
601 r.left() + d1, r.top() + d1,
602 r.right() - d1, r.bottom() - d1 );
603 QwtPainter::drawLine( painter,
604 r.left() + d1, r.bottom() - d1,
605 r.right() - d1, r.top() + d1 );
606 QwtPainter::drawLine( painter,
607 c.x(), r.top(),
608 c.x(), r.bottom() );
609 QwtPainter::drawLine( painter,
610 r.left(), c.y(),
611 r.right(), c.y() );
612 }
613 }
614}
615
616static inline void qwtDrawStar2Symbols( QPainter *painter,
617 const QPointF *points, int numPoints, const QwtSymbol &symbol )
618{
619 QPen pen = symbol.pen();
620 if ( pen.width() > 1 )
621 pen.setCapStyle( Qt::FlatCap );
622 pen.setJoinStyle( Qt::MiterJoin );
623 painter->setPen( pen );
624
625 painter->setBrush( symbol.brush() );
626
627 const double cos30 = 0.866025; // cos(30°)
628
629 const double dy = 0.25 * symbol.size().height();
630 const double dx = 0.5 * symbol.size().width() * cos30 / 3.0;
631
632 QPolygonF star( 12 );
633 QPointF *starPoints = star.data();
634
635 const bool doAlign = QwtPainter::roundingAlignment( painter );
636
637 for ( int i = 0; i < numPoints; i++ )
638 {
639 double x = points[i].x();
640 double y = points[i].y();
641 if ( doAlign )
642 {
643 x = qRound( x );
644 y = qRound( y );
645 }
646
647 double x1 = x - 3 * dx;
648 double y1 = y - 2 * dy;
649 if ( doAlign )
650 {
651 x1 = qRound( x - 3 * dx );
652 y1 = qRound( y - 2 * dy );
653 }
654
655 const double x2 = x1 + 1 * dx;
656 const double x3 = x1 + 2 * dx;
657 const double x4 = x1 + 3 * dx;
658 const double x5 = x1 + 4 * dx;
659 const double x6 = x1 + 5 * dx;
660 const double x7 = x1 + 6 * dx;
661
662 const double y2 = y1 + 1 * dy;
663 const double y3 = y1 + 2 * dy;
664 const double y4 = y1 + 3 * dy;
665 const double y5 = y1 + 4 * dy;
666
667 starPoints[0].rx() = x4;
668 starPoints[0].ry() = y1;
669
670 starPoints[1].rx() = x5;
671 starPoints[1].ry() = y2;
672
673 starPoints[2].rx() = x7;
674 starPoints[2].ry() = y2;
675
676 starPoints[3].rx() = x6;
677 starPoints[3].ry() = y3;
678
679 starPoints[4].rx() = x7;
680 starPoints[4].ry() = y4;
681
682 starPoints[5].rx() = x5;
683 starPoints[5].ry() = y4;
684
685 starPoints[6].rx() = x4;
686 starPoints[6].ry() = y5;
687
688 starPoints[7].rx() = x3;
689 starPoints[7].ry() = y4;
690
691 starPoints[8].rx() = x1;
692 starPoints[8].ry() = y4;
693
694 starPoints[9].rx() = x2;
695 starPoints[9].ry() = y3;
696
697 starPoints[10].rx() = x1;
698 starPoints[10].ry() = y2;
699
700 starPoints[11].rx() = x3;
701 starPoints[11].ry() = y2;
702
703 QwtPainter::drawPolygon( painter, star );
704 }
705}
706
707static inline void qwtDrawHexagonSymbols( QPainter *painter,
708 const QPointF *points, int numPoints, const QwtSymbol &symbol )
709{
710 painter->setBrush( symbol.brush() );
711 painter->setPen( symbol.pen() );
712
713 const double cos30 = 0.866025; // cos(30°)
714 const double dx = 0.5 * ( symbol.size().width() - cos30 );
715
716 const double dy = 0.25 * symbol.size().height();
717
718 QPolygonF hexaPolygon( 6 );
719 QPointF *hexaPoints = hexaPolygon.data();
720
721 const bool doAlign = QwtPainter::roundingAlignment( painter );
722
723 for ( int i = 0; i < numPoints; i++ )
724 {
725 double x = points[i].x();
726 double y = points[i].y();
727 if ( doAlign )
728 {
729 x = qRound( x );
730 y = qRound( y );
731 }
732
733 double x1 = x - dx;
734 double y1 = y - 2 * dy;
735 if ( doAlign )
736 {
737 x1 = qCeil( x1 );
738 y1 = qCeil( y1 );
739 }
740
741 const double x2 = x1 + 1 * dx;
742 const double x3 = x1 + 2 * dx;
743
744 const double y2 = y1 + 1 * dy;
745 const double y3 = y1 + 3 * dy;
746 const double y4 = y1 + 4 * dy;
747
748 hexaPoints[0].rx() = x2;
749 hexaPoints[0].ry() = y1;
750
751 hexaPoints[1].rx() = x3;
752 hexaPoints[1].ry() = y2;
753
754 hexaPoints[2].rx() = x3;
755 hexaPoints[2].ry() = y3;
756
757 hexaPoints[3].rx() = x2;
758 hexaPoints[3].ry() = y4;
759
760 hexaPoints[4].rx() = x1;
761 hexaPoints[4].ry() = y3;
762
763 hexaPoints[5].rx() = x1;
764 hexaPoints[5].ry() = y2;
765
766 QwtPainter::drawPolygon( painter, hexaPolygon );
767 }
768}
769
770class QwtSymbol::PrivateData
771{
772public:
773 PrivateData( QwtSymbol::Style st, const QBrush &br,
774 const QPen &pn, const QSize &sz ):
775 style( st ),
776 size( sz ),
777 brush( br ),
778 pen( pn ),
779 isPinPointEnabled( false )
780 {
781 cache.policy = QwtSymbol::AutoCache;
782#ifndef QWT_NO_SVG
783 svg.renderer = NULL;
784#endif
785 }
786
787 ~PrivateData()
788 {
789#ifndef QWT_NO_SVG
790 delete svg.renderer;
791#endif
792 }
793
794 Style style;
795 QSize size;
796 QBrush brush;
797 QPen pen;
798
799 bool isPinPointEnabled;
800 QPointF pinPoint;
801
802 struct Path
803 {
804 QPainterPath path;
805 QwtGraphic graphic;
806
807 } path;
808
809 struct Pixmap
810 {
811 QPixmap pixmap;
812
813 } pixmap;
814
815 struct Graphic
816 {
817 QwtGraphic graphic;
818
819 } graphic;
820
821#ifndef QWT_NO_SVG
822 struct SVG
823 {
824 QSvgRenderer *renderer;
825 } svg;
826#endif
827
828 struct PaintCache
829 {
830 QwtSymbol::CachePolicy policy;
831 QPixmap pixmap;
832
833 } cache;
834};
835
836/*!
837 Default Constructor
838 \param style Symbol Style
839
840 The symbol is constructed with gray interior,
841 black outline with zero width, no size and style 'NoSymbol'.
842*/
843QwtSymbol::QwtSymbol( Style style )
844{
845 d_data = new PrivateData( style, QBrush( Qt::gray ),
846 QPen( Qt::black, 0 ), QSize() );
847}
848
849/*!
850 \brief Constructor
851 \param style Symbol Style
852 \param brush brush to fill the interior
853 \param pen outline pen
854 \param size size
855
856 \sa setStyle(), setBrush(), setPen(), setSize()
857*/
858QwtSymbol::QwtSymbol( QwtSymbol::Style style, const QBrush &brush,
859 const QPen &pen, const QSize &size )
860{
861 d_data = new PrivateData( style, brush, pen, size );
862}
863
864/*!
865 \brief Constructor
866
867 The symbol gets initialized by a painter path. The style is
868 set to QwtSymbol::Path, the size is set to empty ( the path
869 is displayed unscaled ).
870
871 \param path painter path
872 \param brush brush to fill the interior
873 \param pen outline pen
874
875 \sa setPath(), setBrush(), setPen(), setSize()
876*/
877
878QwtSymbol::QwtSymbol( const QPainterPath &path,
879 const QBrush &brush, const QPen &pen )
880{
881 d_data = new PrivateData( QwtSymbol::Path, brush, pen, QSize() );
882 setPath( path );
883}
884
885//! Destructor
886QwtSymbol::~QwtSymbol()
887{
888 delete d_data;
889}
890
891/*!
892 Change the cache policy
893
894 The default policy is AutoCache
895
896 \param policy Cache policy
897 \sa CachePolicy, cachePolicy()
898*/
899void QwtSymbol::setCachePolicy(
900 QwtSymbol::CachePolicy policy )
901{
902 if ( d_data->cache.policy != policy )
903 {
904 d_data->cache.policy = policy;
905 invalidateCache();
906 }
907}
908
909/*!
910 \return Cache policy
911 \sa CachePolicy, setCachePolicy()
912*/
913QwtSymbol::CachePolicy QwtSymbol::cachePolicy() const
914{
915 return d_data->cache.policy;
916}
917
918/*!
919 \brief Set a painter path as symbol
920
921 The symbol is represented by a painter path, where the
922 origin ( 0, 0 ) of the path coordinate system is mapped to
923 the position of the symbol.
924
925 When the symbol has valid size the painter path gets scaled
926 to fit into the size. Otherwise the symbol size depends on
927 the bounding rectangle of the path.
928
929 \par Example
930 The following code defines a symbol drawing an arrow:
931
932 \code
933 #include <qwt_symbol.h>
934
935 QwtSymbol *symbol = new QwtSymbol();
936
937 QPen pen( Qt::black, 2 );
938 pen.setJoinStyle( Qt::MiterJoin );
939
940 symbol->setPen( pen );
941 symbol->setBrush( Qt::red );
942
943 QPainterPath path;
944 path.moveTo( 0, 8 );
945 path.lineTo( 0, 5 );
946 path.lineTo( -3, 5 );
947 path.lineTo( 0, 0 );
948 path.lineTo( 3, 5 );
949 path.lineTo( 0, 5 );
950
951 QTransform transform;
952 transform.rotate( -30.0 );
953 path = transform.map( path );
954
955 symbol->setPath( path );
956 symbol->setPinPoint( QPointF( 0.0, 0.0 ) );
957
958 setSize( 10, 14 );
959 \endcode
960 \endpar
961
962 \param path Painter path
963
964 \note The style is implicitely set to QwtSymbol::Path.
965 \sa path(), setSize()
966 */
967void QwtSymbol::setPath( const QPainterPath &path )
968{
969 d_data->style = QwtSymbol::Path;
970 d_data->path.path = path;
971 d_data->path.graphic.reset();
972}
973
974/*!
975 \return Painter path for displaying the symbol
976 \sa setPath()
977*/
978const QPainterPath &QwtSymbol::path() const
979{
980 return d_data->path.path;
981}
982
983/*!
984 Set a pixmap as symbol
985
986 \param pixmap Pixmap
987
988 \sa pixmap(), setGraphic()
989
990 \note the style() is set to QwtSymbol::Pixmap
991 \note brush() and pen() have no effect
992 */
993void QwtSymbol::setPixmap( const QPixmap &pixmap )
994{
995 d_data->style = QwtSymbol::Pixmap;
996 d_data->pixmap.pixmap = pixmap;
997}
998
999/*!
1000 \return Assigned pixmap
1001 \sa setPixmap()
1002 */
1003const QPixmap &QwtSymbol::pixmap() const
1004{
1005 return d_data->pixmap.pixmap;
1006}
1007
1008/*!
1009 Set a graphic as symbol
1010
1011 \param graphic Graphic
1012
1013 \sa graphic(), setPixmap()
1014
1015 \note the style() is set to QwtSymbol::Graphic
1016 \note brush() and pen() have no effect
1017 */
1018void QwtSymbol::setGraphic( const QwtGraphic &graphic )
1019{
1020 d_data->style = QwtSymbol::Graphic;
1021 d_data->graphic.graphic = graphic;
1022}
1023
1024/*!
1025 \return Assigned graphic
1026 \sa setGraphic()
1027 */
1028const QwtGraphic &QwtSymbol::graphic() const
1029{
1030 return d_data->graphic.graphic;
1031}
1032
1033#ifndef QWT_NO_SVG
1034
1035/*!
1036 Set a SVG icon as symbol
1037
1038 \param svgDocument SVG icon
1039
1040 \sa setGraphic(), setPixmap()
1041
1042 \note the style() is set to QwtSymbol::SvgDocument
1043 \note brush() and pen() have no effect
1044 */
1045void QwtSymbol::setSvgDocument( const QByteArray &svgDocument )
1046{
1047 d_data->style = QwtSymbol::SvgDocument;
1048 if ( d_data->svg.renderer == NULL )
1049 d_data->svg.renderer = new QSvgRenderer();
1050
1051 d_data->svg.renderer->load( svgDocument );
1052}
1053
1054#endif
1055
1056/*!
1057 \brief Specify the symbol's size
1058
1059 If the 'h' parameter is left out or less than 0,
1060 and the 'w' parameter is greater than or equal to 0,
1061 the symbol size will be set to (w,w).
1062
1063 \param width Width
1064 \param height Height (defaults to -1)
1065
1066 \sa size()
1067*/
1068void QwtSymbol::setSize( int width, int height )
1069{
1070 if ( ( width >= 0 ) && ( height < 0 ) )
1071 height = width;
1072
1073 setSize( QSize( width, height ) );
1074}
1075
1076/*!
1077 Set the symbol's size
1078 \param size Size
1079
1080 \sa size()
1081*/
1082void QwtSymbol::setSize( const QSize &size )
1083{
1084 if ( size.isValid() && size != d_data->size )
1085 {
1086 d_data->size = size;
1087 invalidateCache();
1088 }
1089}
1090
1091/*!
1092 \return Size
1093 \sa setSize()
1094*/
1095const QSize& QwtSymbol::size() const
1096{
1097 return d_data->size;
1098}
1099
1100/*!
1101 \brief Assign a brush
1102
1103 The brush is used to draw the interior of the symbol.
1104 \param brush Brush
1105
1106 \sa brush()
1107*/
1108void QwtSymbol::setBrush( const QBrush &brush )
1109{
1110 if ( brush != d_data->brush )
1111 {
1112 d_data->brush = brush;
1113 invalidateCache();
1114
1115 if ( d_data->style == QwtSymbol::Path )
1116 d_data->path.graphic.reset();
1117 }
1118}
1119
1120/*!
1121 \return Brush
1122 \sa setBrush()
1123*/
1124const QBrush& QwtSymbol::brush() const
1125{
1126 return d_data->brush;
1127}
1128
1129/*!
1130 Build and assign a pen
1131
1132 In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 )
1133 what makes it non cosmetic ( see QPen::isCosmetic() ).
1134 This method has been introduced to hide this incompatibility.
1135
1136 \param color Pen color
1137 \param width Pen width
1138 \param style Pen style
1139
1140 \sa pen(), brush()
1141 */
1142void QwtSymbol::setPen( const QColor &color,
1143 qreal width, Qt::PenStyle style )
1144{
1145 setPen( QPen( color, width, style ) );
1146}
1147
1148/*!
1149 Assign a pen
1150
1151 The pen is used to draw the symbol's outline.
1152
1153 \param pen Pen
1154 \sa pen(), setBrush()
1155*/
1156void QwtSymbol::setPen( const QPen &pen )
1157{
1158 if ( pen != d_data->pen )
1159 {
1160 d_data->pen = pen;
1161 invalidateCache();
1162
1163 if ( d_data->style == QwtSymbol::Path )
1164 d_data->path.graphic.reset();
1165 }
1166}
1167
1168/*!
1169 \return Pen
1170 \sa setPen(), brush()
1171*/
1172const QPen& QwtSymbol::pen() const
1173{
1174 return d_data->pen;
1175}
1176
1177/*!
1178 \brief Set the color of the symbol
1179
1180 Change the color of the brush for symbol types with a filled area.
1181 For all other symbol types the color will be assigned to the pen.
1182
1183 \param color Color
1184
1185 \sa setBrush(), setPen(), brush(), pen()
1186*/
1187void QwtSymbol::setColor( const QColor &color )
1188{
1189 switch ( d_data->style )
1190 {
1191 case QwtSymbol::Ellipse:
1192 case QwtSymbol::Rect:
1193 case QwtSymbol::Diamond:
1194 case QwtSymbol::Triangle:
1195 case QwtSymbol::UTriangle:
1196 case QwtSymbol::DTriangle:
1197 case QwtSymbol::RTriangle:
1198 case QwtSymbol::LTriangle:
1199 case QwtSymbol::Star2:
1200 case QwtSymbol::Hexagon:
1201 {
1202 if ( d_data->brush.color() != color )
1203 {
1204 d_data->brush.setColor( color );
1205 invalidateCache();
1206 }
1207 break;
1208 }
1209 case QwtSymbol::Cross:
1210 case QwtSymbol::XCross:
1211 case QwtSymbol::HLine:
1212 case QwtSymbol::VLine:
1213 case QwtSymbol::Star1:
1214 {
1215 if ( d_data->pen.color() != color )
1216 {
1217 d_data->pen.setColor( color );
1218 invalidateCache();
1219 }
1220 break;
1221 }
1222 default:
1223 {
1224 if ( d_data->brush.color() != color ||
1225 d_data->pen.color() != color )
1226 {
1227 invalidateCache();
1228 }
1229
1230 d_data->brush.setColor( color );
1231 d_data->pen.setColor( color );
1232 }
1233 }
1234}
1235
1236/*!
1237 \brief Set and enable a pin point
1238
1239 The position of a complex symbol is not always aligned to its center
1240 ( f.e an arrow, where the peak points to a position ). The pin point
1241 defines the position inside of a Pixmap, Graphic, SvgDocument
1242 or PainterPath symbol where the represented point has to
1243 be aligned to.
1244
1245 \param pos Position
1246 \param enable En/Disable the pin point alignment
1247
1248 \sa pinPoint(), setPinPointEnabled()
1249 */
1250void QwtSymbol::setPinPoint( const QPointF &pos, bool enable )
1251{
1252 if ( d_data->pinPoint != pos )
1253 {
1254 d_data->pinPoint = pos;
1255 if ( d_data->isPinPointEnabled )
1256 {
1257 invalidateCache();
1258 }
1259 }
1260
1261 setPinPointEnabled( enable );
1262}
1263
1264/*!
1265 \return Pin point
1266 \sa setPinPoint(), setPinPointEnabled()
1267 */
1268QPointF QwtSymbol::pinPoint() const
1269{
1270 return d_data->pinPoint;
1271}
1272
1273/*!
1274 En/Disable the pin point alignment
1275
1276 \param on Enabled, when on is true
1277 \sa setPinPoint(), isPinPointEnabled()
1278 */
1279void QwtSymbol::setPinPointEnabled( bool on )
1280{
1281 if ( d_data->isPinPointEnabled != on )
1282 {
1283 d_data->isPinPointEnabled = on;
1284 invalidateCache();
1285 }
1286}
1287
1288/*!
1289 \return True, when the pin point translation is enabled
1290 \sa setPinPoint(), setPinPointEnabled()
1291 */
1292bool QwtSymbol::isPinPointEnabled() const
1293{
1294 return d_data->isPinPointEnabled;
1295}
1296
1297/*!
1298 Render an array of symbols
1299
1300 Painting several symbols is more effective than drawing symbols
1301 one by one, as a couple of layout calculations and setting of pen/brush
1302 can be done once for the complete array.
1303
1304 \param painter Painter
1305 \param points Array of points
1306 \param numPoints Number of points
1307*/
1308void QwtSymbol::drawSymbols( QPainter *painter,
1309 const QPointF *points, int numPoints ) const
1310{
1311 if ( numPoints <= 0 )
1312 return;
1313
1314 bool useCache = false;
1315
1316 // Don't use the pixmap, when the paint device
1317 // could generate scalable vectors
1318
1319 if ( QwtPainter::roundingAlignment( painter ) &&
1320 !painter->transform().isScaling() )
1321 {
1322 if ( d_data->cache.policy == QwtSymbol::Cache )
1323 {
1324 useCache = true;
1325 }
1326 else if ( d_data->cache.policy == QwtSymbol::AutoCache )
1327 {
1328 if ( painter->paintEngine()->type() == QPaintEngine::Raster )
1329 {
1330 useCache = true;
1331 }
1332 else
1333 {
1334 switch( d_data->style )
1335 {
1336 case QwtSymbol::XCross:
1337 case QwtSymbol::HLine:
1338 case QwtSymbol::VLine:
1339 case QwtSymbol::Cross:
1340 break;
1341
1342 case QwtSymbol::Pixmap:
1343 {
1344 if ( !d_data->size.isEmpty() &&
1345 d_data->size != d_data->pixmap.pixmap.size() )
1346 {
1347 useCache = true;
1348 }
1349 break;
1350 }
1351 default:
1352 useCache = true;
1353 }
1354 }
1355 }
1356 }
1357
1358 if ( useCache )
1359 {
1360 const QRect br = boundingRect();
1361
1362 if ( d_data->cache.pixmap.isNull() )
1363 {
1364 d_data->cache.pixmap = QwtPainter::backingStore( NULL, br.size() );
1365 d_data->cache.pixmap.fill( Qt::transparent );
1366
1367 QPainter p( &d_data->cache.pixmap );
1368 p.setRenderHints( painter->renderHints() );
1369 p.translate( -br.topLeft() );
1370
1371 const QPointF pos;
1372 renderSymbols( &p, &pos, 1 );
1373 }
1374
1375 const int dx = br.left();
1376 const int dy = br.top();
1377
1378 for ( int i = 0; i < numPoints; i++ )
1379 {
1380 const int left = qRound( points[i].x() ) + dx;
1381 const int top = qRound( points[i].y() ) + dy;
1382
1383 painter->drawPixmap( left, top, d_data->cache.pixmap );
1384 }
1385 }
1386 else
1387 {
1388 painter->save();
1389 renderSymbols( painter, points, numPoints );
1390 painter->restore();
1391 }
1392}
1393
1394/*!
1395 \brief Draw the symbol into a rectangle
1396
1397 The symbol is painted centered and scaled into the target rectangle.
1398 It is always painted uncached and the pin point is ignored.
1399
1400 This method is primarily intended for drawing a symbol to
1401 the legend.
1402
1403 \param painter Painter
1404 \param rect Target rectangle for the symbol
1405*/
1406void QwtSymbol::drawSymbol( QPainter *painter, const QRectF &rect ) const
1407{
1408 if ( d_data->style == QwtSymbol::NoSymbol )
1409 return;
1410
1411 if ( d_data->style == QwtSymbol::Graphic )
1412 {
1413 d_data->graphic.graphic.render(
1414 painter, rect, Qt::KeepAspectRatio );
1415 }
1416 else if ( d_data->style == QwtSymbol::Path )
1417 {
1418 if ( d_data->path.graphic.isNull() )
1419 {
1420 d_data->path.graphic = qwtPathGraphic(
1421 d_data->path.path, d_data->pen, d_data->brush );
1422 }
1423
1424 d_data->path.graphic.render(
1425 painter, rect, Qt::KeepAspectRatio );
1426 return;
1427 }
1428 else if ( d_data->style == QwtSymbol::SvgDocument )
1429 {
1430#ifndef QWT_NO_SVG
1431 if ( d_data->svg.renderer )
1432 {
1433 QRectF scaledRect;
1434
1435 QSizeF sz = d_data->svg.renderer->viewBoxF().size();
1436 if ( !sz.isEmpty() )
1437 {
1438 sz.scale( rect.size(), Qt::KeepAspectRatio );
1439 scaledRect.setSize( sz );
1440 scaledRect.moveCenter( rect.center() );
1441 }
1442 else
1443 {
1444 scaledRect = rect;
1445 }
1446
1447 d_data->svg.renderer->render(
1448 painter, scaledRect );
1449 }
1450#endif
1451 }
1452 else
1453 {
1454 const QRect br = boundingRect();
1455
1456 // scale the symbol size to fit into rect.
1457
1458 const double ratio = qMin( rect.width() / br.width(),
1459 rect.height() / br.height() );
1460
1461 painter->save();
1462
1463 painter->translate( rect.center() );
1464 painter->scale( ratio, ratio );
1465
1466 const bool isPinPointEnabled = d_data->isPinPointEnabled;
1467 d_data->isPinPointEnabled = false;
1468
1469 const QPointF pos;
1470 renderSymbols( painter, &pos, 1 );
1471
1472 d_data->isPinPointEnabled = isPinPointEnabled;
1473
1474 painter->restore();
1475 }
1476}
1477
1478/*!
1479 Render the symbol to series of points
1480
1481 \param painter Qt painter
1482 \param points Positions of the symbols
1483 \param numPoints Number of points
1484 */
1485void QwtSymbol::renderSymbols( QPainter *painter,
1486 const QPointF *points, int numPoints ) const
1487{
1488 switch ( d_data->style )
1489 {
1490 case QwtSymbol::Ellipse:
1491 {
1492 qwtDrawEllipseSymbols( painter, points, numPoints, *this );
1493 break;
1494 }
1495 case QwtSymbol::Rect:
1496 {
1497 qwtDrawRectSymbols( painter, points, numPoints, *this );
1498 break;
1499 }
1500 case QwtSymbol::Diamond:
1501 {
1502 qwtDrawDiamondSymbols( painter, points, numPoints, *this );
1503 break;
1504 }
1505 case QwtSymbol::Cross:
1506 {
1507 qwtDrawLineSymbols( painter, Qt::Horizontal | Qt::Vertical,
1508 points, numPoints, *this );
1509 break;
1510 }
1511 case QwtSymbol::XCross:
1512 {
1513 qwtDrawXCrossSymbols( painter, points, numPoints, *this );
1514 break;
1515 }
1516 case QwtSymbol::Triangle:
1517 case QwtSymbol::UTriangle:
1518 {
1519 qwtDrawTriangleSymbols( painter, QwtTriangle::Up,
1520 points, numPoints, *this );
1521 break;
1522 }
1523 case QwtSymbol::DTriangle:
1524 {
1525 qwtDrawTriangleSymbols( painter, QwtTriangle::Down,
1526 points, numPoints, *this );
1527 break;
1528 }
1529 case QwtSymbol::RTriangle:
1530 {
1531 qwtDrawTriangleSymbols( painter, QwtTriangle::Right,
1532 points, numPoints, *this );
1533 break;
1534 }
1535 case QwtSymbol::LTriangle:
1536 {
1537 qwtDrawTriangleSymbols( painter, QwtTriangle::Left,
1538 points, numPoints, *this );
1539 break;
1540 }
1541 case QwtSymbol::HLine:
1542 {
1543 qwtDrawLineSymbols( painter, Qt::Horizontal,
1544 points, numPoints, *this );
1545 break;
1546 }
1547 case QwtSymbol::VLine:
1548 {
1549 qwtDrawLineSymbols( painter, Qt::Vertical,
1550 points, numPoints, *this );
1551 break;
1552 }
1553 case QwtSymbol::Star1:
1554 {
1555 qwtDrawStar1Symbols( painter, points, numPoints, *this );
1556 break;
1557 }
1558 case QwtSymbol::Star2:
1559 {
1560 qwtDrawStar2Symbols( painter, points, numPoints, *this );
1561 break;
1562 }
1563 case QwtSymbol::Hexagon:
1564 {
1565 qwtDrawHexagonSymbols( painter, points, numPoints, *this );
1566 break;
1567 }
1568 case QwtSymbol::Path:
1569 {
1570 if ( d_data->path.graphic.isNull() )
1571 {
1572 d_data->path.graphic = qwtPathGraphic( d_data->path.path,
1573 d_data->pen, d_data->brush );
1574 }
1575
1576 qwtDrawGraphicSymbols( painter, points, numPoints,
1577 d_data->path.graphic, *this );
1578 break;
1579 }
1580 case QwtSymbol::Pixmap:
1581 {
1582 qwtDrawPixmapSymbols( painter, points, numPoints, *this );
1583 break;
1584 }
1585 case QwtSymbol::Graphic:
1586 {
1587 qwtDrawGraphicSymbols( painter, points, numPoints,
1588 d_data->graphic.graphic, *this );
1589 break;
1590 }
1591 case QwtSymbol::SvgDocument:
1592 {
1593#ifndef QWT_NO_SVG
1594 qwtDrawSvgSymbols( painter, points, numPoints,
1595 d_data->svg.renderer, *this );
1596#endif
1597 break;
1598 }
1599 default:;
1600 }
1601}
1602
1603/*!
1604 Calculate the bounding rectangle for a symbol
1605 at position (0,0).
1606
1607 \return Bounding rectangle
1608 */
1609QRect QwtSymbol::boundingRect() const
1610{
1611 QRectF rect;
1612
1613 bool pinPointTranslation = false;
1614
1615 switch ( d_data->style )
1616 {
1617 case QwtSymbol::Ellipse:
1618 case QwtSymbol::Rect:
1619 case QwtSymbol::Hexagon:
1620 {
1621 qreal pw = 0.0;
1622 if ( d_data->pen.style() != Qt::NoPen )
1623 pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) );
1624
1625 rect.setSize( d_data->size + QSizeF( pw, pw ) );
1626 rect.moveCenter( QPointF( 0.0, 0.0 ) );
1627
1628 break;
1629 }
1630 case QwtSymbol::XCross:
1631 case QwtSymbol::Diamond:
1632 case QwtSymbol::Triangle:
1633 case QwtSymbol::UTriangle:
1634 case QwtSymbol::DTriangle:
1635 case QwtSymbol::RTriangle:
1636 case QwtSymbol::LTriangle:
1637 case QwtSymbol::Star1:
1638 case QwtSymbol::Star2:
1639 {
1640 qreal pw = 0.0;
1641 if ( d_data->pen.style() != Qt::NoPen )
1642 pw = qMax( d_data->pen.widthF(), qreal( 1.0 ) );
1643
1644 rect.setSize( d_data->size + QSizeF( 2 * pw, 2 * pw ) );
1645 rect.moveCenter( QPointF( 0.0, 0.0 ) );
1646 break;
1647 }
1648 case QwtSymbol::Path:
1649 {
1650 if ( d_data->path.graphic.isNull() )
1651 {
1652 d_data->path.graphic = qwtPathGraphic(
1653 d_data->path.path, d_data->pen, d_data->brush );
1654 }
1655
1656 rect = qwtScaledBoundingRect(
1657 d_data->path.graphic, d_data->size );
1658 pinPointTranslation = true;
1659
1660 break;
1661 }
1662 case QwtSymbol::Pixmap:
1663 {
1664 if ( d_data->size.isEmpty() )
1665 rect.setSize( d_data->pixmap.pixmap.size() );
1666 else
1667 rect.setSize( d_data->size );
1668
1669 pinPointTranslation = true;
1670
1671 break;
1672 }
1673 case QwtSymbol::Graphic:
1674 {
1675 rect = qwtScaledBoundingRect(
1676 d_data->graphic.graphic, d_data->size );
1677 pinPointTranslation = true;
1678
1679 break;
1680 }
1681#ifndef QWT_NO_SVG
1682 case QwtSymbol::SvgDocument:
1683 {
1684 if ( d_data->svg.renderer )
1685 rect = d_data->svg.renderer->viewBoxF();
1686
1687 if ( d_data->size.isValid() && !rect.isEmpty() )
1688 {
1689 QSizeF sz = rect.size();
1690
1691 const double sx = d_data->size.width() / sz.width();
1692 const double sy = d_data->size.height() / sz.height();
1693
1694 QTransform transform;
1695 transform.scale( sx, sy );
1696
1697 rect = transform.mapRect( rect );
1698 }
1699 pinPointTranslation = true;
1700 break;
1701 }
1702#endif
1703 default:
1704 {
1705 rect.setSize( d_data->size );
1706 rect.moveCenter( QPointF( 0.0, 0.0 ) );
1707 }
1708 }
1709
1710 if ( pinPointTranslation )
1711 {
1712 QPointF pinPoint( 0.0, 0.0 );
1713 if ( d_data->isPinPointEnabled )
1714 pinPoint = rect.center() - d_data->pinPoint;
1715
1716 rect.moveCenter( pinPoint );
1717 }
1718
1719 QRect r;
1720 r.setLeft( qFloor( rect.left() ) );
1721 r.setTop( qFloor( rect.top() ) );
1722 r.setRight( qCeil( rect.right() ) );
1723 r.setBottom( qCeil( rect.bottom() ) );
1724
1725 if ( d_data->style != QwtSymbol::Pixmap )
1726 r.adjust( -1, -1, 1, 1 ); // for antialiasing
1727
1728 return r;
1729}
1730
1731/*!
1732 Invalidate the cached symbol pixmap
1733
1734 The symbol invalidates its cache, whenever an attribute is changed
1735 that has an effect ob how to display a symbol. In case of derived
1736 classes with individual styles ( >= QwtSymbol::UserStyle ) it
1737 might be necessary to call invalidateCache() for attributes
1738 that are relevant for this style.
1739
1740 \sa CachePolicy, setCachePolicy(), drawSymbols()
1741 */
1742void QwtSymbol::invalidateCache()
1743{
1744 if ( !d_data->cache.pixmap.isNull() )
1745 d_data->cache.pixmap = QPixmap();
1746}
1747
1748/*!
1749 Specify the symbol style
1750
1751 \param style Style
1752 \sa style()
1753*/
1754void QwtSymbol::setStyle( QwtSymbol::Style style )
1755{
1756 if ( d_data->style != style )
1757 {
1758 d_data->style = style;
1759 invalidateCache();
1760 }
1761}
1762
1763/*!
1764 \return Current symbol style
1765 \sa setStyle()
1766*/
1767QwtSymbol::Style QwtSymbol::style() const
1768{
1769 return d_data->style;
1770}
Note: See TracBrowser for help on using the repository browser.