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

Last change on this file since 8963 was 8127, checked in by stoecker, 7 years ago

update qwt and qwtpolar, many QT5 fixes (unfinished)

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 The following code defines a symbol drawing an arrow:
930
931 \verbatim
932#include <qwt_symbol.h>
933
934QwtSymbol *symbol = new QwtSymbol();
935
936QPen pen( Qt::black, 2 );
937pen.setJoinStyle( Qt::MiterJoin );
938
939symbol->setPen( pen );
940symbol->setBrush( Qt::red );
941
942QPainterPath path;
943path.moveTo( 0, 8 );
944path.lineTo( 0, 5 );
945path.lineTo( -3, 5 );
946path.lineTo( 0, 0 );
947path.lineTo( 3, 5 );
948path.lineTo( 0, 5 );
949
950QTransform transform;
951transform.rotate( -30.0 );
952path = transform.map( path );
953
954symbol->setPath( path );
955symbol->setPinPoint( QPointF( 0.0, 0.0 ) );
956
957setSize( 10, 14 );
958\endverbatim
959
960 \param path Painter path
961
962 \note The style is implicitely set to QwtSymbol::Path.
963 \sa path(), setSize()
964 */
965void QwtSymbol::setPath( const QPainterPath &path )
966{
967 d_data->style = QwtSymbol::Path;
968 d_data->path.path = path;
969 d_data->path.graphic.reset();
970}
971
972/*!
973 \return Painter path for displaying the symbol
974 \sa setPath()
975*/
976const QPainterPath &QwtSymbol::path() const
977{
978 return d_data->path.path;
979}
980
981/*!
982 Set a pixmap as symbol
983
984 \param pixmap Pixmap
985
986 \sa pixmap(), setGraphic()
987
988 \note the style() is set to QwtSymbol::Pixmap
989 \note brush() and pen() have no effect
990 */
991void QwtSymbol::setPixmap( const QPixmap &pixmap )
992{
993 d_data->style = QwtSymbol::Pixmap;
994 d_data->pixmap.pixmap = pixmap;
995}
996
997/*!
998 \return Assigned pixmap
999 \sa setPixmap()
1000 */
1001const QPixmap &QwtSymbol::pixmap() const
1002{
1003 return d_data->pixmap.pixmap;
1004}
1005
1006/*!
1007 Set a graphic as symbol
1008
1009 \param graphic Graphic
1010
1011 \sa graphic(), setPixmap()
1012
1013 \note the style() is set to QwtSymbol::Graphic
1014 \note brush() and pen() have no effect
1015 */
1016void QwtSymbol::setGraphic( const QwtGraphic &graphic )
1017{
1018 d_data->style = QwtSymbol::Graphic;
1019 d_data->graphic.graphic = graphic;
1020}
1021
1022/*!
1023 \return Assigned graphic
1024 \sa setGraphic()
1025 */
1026const QwtGraphic &QwtSymbol::graphic() const
1027{
1028 return d_data->graphic.graphic;
1029}
1030
1031#ifndef QWT_NO_SVG
1032
1033/*!
1034 Set a SVG icon as symbol
1035
1036 \param svgDocument SVG icon
1037
1038 \sa setGraphic(), setPixmap()
1039
1040 \note the style() is set to QwtSymbol::SvgDocument
1041 \note brush() and pen() have no effect
1042 */
1043void QwtSymbol::setSvgDocument( const QByteArray &svgDocument )
1044{
1045 d_data->style = QwtSymbol::SvgDocument;
1046 if ( d_data->svg.renderer == NULL )
1047 d_data->svg.renderer = new QSvgRenderer();
1048
1049 d_data->svg.renderer->load( svgDocument );
1050}
1051
1052#endif
1053
1054/*!
1055 \brief Specify the symbol's size
1056
1057 If the 'h' parameter is left out or less than 0,
1058 and the 'w' parameter is greater than or equal to 0,
1059 the symbol size will be set to (w,w).
1060
1061 \param width Width
1062 \param height Height (defaults to -1)
1063
1064 \sa size()
1065*/
1066void QwtSymbol::setSize( int width, int height )
1067{
1068 if ( ( width >= 0 ) && ( height < 0 ) )
1069 height = width;
1070
1071 setSize( QSize( width, height ) );
1072}
1073
1074/*!
1075 Set the symbol's size
1076 \param size Size
1077
1078 \sa size()
1079*/
1080void QwtSymbol::setSize( const QSize &size )
1081{
1082 if ( size.isValid() && size != d_data->size )
1083 {
1084 d_data->size = size;
1085 invalidateCache();
1086 }
1087}
1088
1089/*!
1090 \return Size
1091 \sa setSize()
1092*/
1093const QSize& QwtSymbol::size() const
1094{
1095 return d_data->size;
1096}
1097
1098/*!
1099 \brief Assign a brush
1100
1101 The brush is used to draw the interior of the symbol.
1102 \param brush Brush
1103
1104 \sa brush()
1105*/
1106void QwtSymbol::setBrush( const QBrush &brush )
1107{
1108 if ( brush != d_data->brush )
1109 {
1110 d_data->brush = brush;
1111 invalidateCache();
1112
1113 if ( d_data->style == QwtSymbol::Path )
1114 d_data->path.graphic.reset();
1115 }
1116}
1117
1118/*!
1119 \return Brush
1120 \sa setBrush()
1121*/
1122const QBrush& QwtSymbol::brush() const
1123{
1124 return d_data->brush;
1125}
1126
1127/*!
1128 Build and assign a pen
1129
1130 In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 )
1131 what makes it non cosmetic ( see QPen::isCosmetic() ).
1132 This method has been introduced to hide this incompatibility.
1133
1134 \param color Pen color
1135 \param width Pen width
1136 \param style Pen style
1137
1138 \sa pen(), brush()
1139 */
1140void QwtSymbol::setPen( const QColor &color,
1141 qreal width, Qt::PenStyle style )
1142{
1143 setPen( QPen( color, width, style ) );
1144}
1145
1146/*!
1147 Assign a pen
1148
1149 The pen is used to draw the symbol's outline.
1150
1151 \param pen Pen
1152 \sa pen(), setBrush()
1153*/
1154void QwtSymbol::setPen( const QPen &pen )
1155{
1156 if ( pen != d_data->pen )
1157 {
1158 d_data->pen = pen;
1159 invalidateCache();
1160
1161 if ( d_data->style == QwtSymbol::Path )
1162 d_data->path.graphic.reset();
1163 }
1164}
1165
1166/*!
1167 \return Pen
1168 \sa setPen(), brush()
1169*/
1170const QPen& QwtSymbol::pen() const
1171{
1172 return d_data->pen;
1173}
1174
1175/*!
1176 \brief Set the color of the symbol
1177
1178 Change the color of the brush for symbol types with a filled area.
1179 For all other symbol types the color will be assigned to the pen.
1180
1181 \param color Color
1182
1183 \sa setBrush(), setPen(), brush(), pen()
1184*/
1185void QwtSymbol::setColor( const QColor &color )
1186{
1187 switch ( d_data->style )
1188 {
1189 case QwtSymbol::Ellipse:
1190 case QwtSymbol::Rect:
1191 case QwtSymbol::Diamond:
1192 case QwtSymbol::Triangle:
1193 case QwtSymbol::UTriangle:
1194 case QwtSymbol::DTriangle:
1195 case QwtSymbol::RTriangle:
1196 case QwtSymbol::LTriangle:
1197 case QwtSymbol::Star2:
1198 case QwtSymbol::Hexagon:
1199 {
1200 if ( d_data->brush.color() != color )
1201 {
1202 d_data->brush.setColor( color );
1203 invalidateCache();
1204 }
1205 break;
1206 }
1207 case QwtSymbol::Cross:
1208 case QwtSymbol::XCross:
1209 case QwtSymbol::HLine:
1210 case QwtSymbol::VLine:
1211 case QwtSymbol::Star1:
1212 {
1213 if ( d_data->pen.color() != color )
1214 {
1215 d_data->pen.setColor( color );
1216 invalidateCache();
1217 }
1218 break;
1219 }
1220 default:
1221 {
1222 if ( d_data->brush.color() != color ||
1223 d_data->pen.color() != color )
1224 {
1225 invalidateCache();
1226 }
1227
1228 d_data->brush.setColor( color );
1229 d_data->pen.setColor( color );
1230 }
1231 }
1232}
1233
1234/*!
1235 \brief Set and enable a pin point
1236
1237 The position of a complex symbol is not always aligned to its center
1238 ( f.e an arrow, where the peak points to a position ). The pin point
1239 defines the position inside of a Pixmap, Graphic, SvgDocument
1240 or PainterPath symbol where the represented point has to
1241 be aligned to.
1242
1243 \param pos Position
1244 \param enable En/Disable the pin point alignment
1245
1246 \sa pinPoint(), setPinPointEnabled()
1247 */
1248void QwtSymbol::setPinPoint( const QPointF &pos, bool enable )
1249{
1250 if ( d_data->pinPoint != pos )
1251 {
1252 d_data->pinPoint = pos;
1253 if ( d_data->isPinPointEnabled )
1254 {
1255 invalidateCache();
1256 }
1257 }
1258
1259 setPinPointEnabled( enable );
1260}
1261
1262/*!
1263 \return Pin point
1264 \sa setPinPoint(), setPinPointEnabled()
1265 */
1266QPointF QwtSymbol::pinPoint() const
1267{
1268 return d_data->pinPoint;
1269}
1270
1271/*!
1272 En/Disable the pin point alignment
1273
1274 \param on Enabled, when on is true
1275 \sa setPinPoint(), isPinPointEnabled()
1276 */
1277void QwtSymbol::setPinPointEnabled( bool on )
1278{
1279 if ( d_data->isPinPointEnabled != on )
1280 {
1281 d_data->isPinPointEnabled = on;
1282 invalidateCache();
1283 }
1284}
1285
1286/*!
1287 \return True, when the pin point translation is enabled
1288 \sa setPinPoint(), setPinPointEnabled()
1289 */
1290bool QwtSymbol::isPinPointEnabled() const
1291{
1292 return d_data->isPinPointEnabled;
1293}
1294
1295/*!
1296 Render an array of symbols
1297
1298 Painting several symbols is more effective than drawing symbols
1299 one by one, as a couple of layout calculations and setting of pen/brush
1300 can be done once for the complete array.
1301
1302 \param painter Painter
1303 \param points Array of points
1304 \param numPoints Number of points
1305*/
1306void QwtSymbol::drawSymbols( QPainter *painter,
1307 const QPointF *points, int numPoints ) const
1308{
1309 if ( numPoints <= 0 )
1310 return;
1311
1312 bool useCache = false;
1313
1314 // Don't use the pixmap, when the paint device
1315 // could generate scalable vectors
1316
1317 if ( QwtPainter::roundingAlignment( painter ) &&
1318 !painter->transform().isScaling() )
1319 {
1320 if ( d_data->cache.policy == QwtSymbol::Cache )
1321 {
1322 useCache = true;
1323 }
1324 else if ( d_data->cache.policy == QwtSymbol::AutoCache )
1325 {
1326 if ( painter->paintEngine()->type() == QPaintEngine::Raster )
1327 {
1328 useCache = true;
1329 }
1330 else
1331 {
1332 switch( d_data->style )
1333 {
1334 case QwtSymbol::XCross:
1335 case QwtSymbol::HLine:
1336 case QwtSymbol::VLine:
1337 case QwtSymbol::Cross:
1338 break;
1339
1340 case QwtSymbol::Pixmap:
1341 {
1342 if ( !d_data->size.isEmpty() &&
1343 d_data->size != d_data->pixmap.pixmap.size() )
1344 {
1345 useCache = true;
1346 }
1347 break;
1348 }
1349 default:
1350 useCache = true;
1351 }
1352 }
1353 }
1354 }
1355
1356 if ( useCache )
1357 {
1358 const QRect br = boundingRect();
1359
1360 const QRect rect( 0, 0, br.width(), br.height() );
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.