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 <qpainter.h>
11 #include <qapplication.h>
12 #include "qwt_painter.h"
13 #include "qwt_polygon.h"
14 #include "qwt_symbol.h"
15
16 /*!
17 Default Constructor
18
19 The symbol is constructed with gray interior,
20 black outline with zero width, no size and style 'NoSymbol'.
21 */
QwtSymbol()22 QwtSymbol::QwtSymbol():
23 d_brush(Qt::gray),
24 d_pen(Qt::black),
25 d_size(0,0),
26 d_style(QwtSymbol::NoSymbol)
27 {
28 }
29
30 /*!
31 \brief Constructor
32 \param style Symbol Style
33 \param brush brush to fill the interior
34 \param pen outline pen
35 \param size size
36 */
QwtSymbol(QwtSymbol::Style style,const QBrush & brush,const QPen & pen,const QSize & size)37 QwtSymbol::QwtSymbol(QwtSymbol::Style style, const QBrush &brush,
38 const QPen &pen, const QSize &size):
39 d_brush(brush),
40 d_pen(pen),
41 d_size(size),
42 d_style(style)
43 {
44 }
45
46 //! Destructor
~QwtSymbol()47 QwtSymbol::~QwtSymbol()
48 {
49 }
50
51 /*!
52 Allocate and return a symbol with the same attributes
53 \return Cloned symbol
54 */
clone() const55 QwtSymbol *QwtSymbol::clone() const
56 {
57 QwtSymbol *other = new QwtSymbol;
58 *other = *this;
59
60 return other;
61 }
62
63 /*!
64 \brief Specify the symbol's size
65
66 If the 'h' parameter is left out or less than 0,
67 and the 'w' parameter is greater than or equal to 0,
68 the symbol size will be set to (w,w).
69 \param width Width
70 \param height Height (defaults to -1)
71 */
setSize(int width,int height)72 void QwtSymbol::setSize(int width, int height)
73 {
74 if ((width >= 0) && (height < 0))
75 height = width;
76 d_size = QSize(width, height);
77 }
78
79 /*!
80 Set the symbol's size
81 \param size Size
82 */
setSize(const QSize & size)83 void QwtSymbol::setSize(const QSize &size)
84 {
85 if (size.isValid())
86 d_size = size;
87 }
88
89 /*!
90 \brief Assign a brush
91
92 The brush is used to draw the interior of the symbol.
93 \param brush Brush
94 */
setBrush(const QBrush & brush)95 void QwtSymbol::setBrush(const QBrush &brush)
96 {
97 d_brush = brush;
98 }
99
100 /*!
101 Assign a pen
102
103 The pen is used to draw the symbol's outline.
104
105 The width of non cosmetic pens is scaled according to the resolution
106 of the paint device.
107
108 \param pen Pen
109 \sa pen(), setBrush(), QwtPainter::scaledPen()
110 */
setPen(const QPen & pen)111 void QwtSymbol::setPen(const QPen &pen)
112 {
113 d_pen = pen;
114 }
115
116 /*!
117 \brief Draw the symbol at a point (x,y).
118 */
draw(QPainter * painter,int x,int y) const119 void QwtSymbol::draw(QPainter *painter, int x, int y) const
120 {
121 draw(painter, QPoint(x, y));
122 }
123
124
125 /*!
126 \brief Draw the symbol into a bounding rectangle.
127
128 This function assumes that the painter has been initialized with
129 brush and pen before. This allows a much more performant implementation
130 when painting many symbols with the same brush and pen like in curves.
131
132 \param painter Painter
133 \param r Bounding rectangle
134 */
draw(QPainter * painter,const QRect & r) const135 void QwtSymbol::draw(QPainter *painter, const QRect& r) const
136 {
137 switch(d_style)
138 {
139 case QwtSymbol::Ellipse:
140 QwtPainter::drawEllipse(painter, r);
141 break;
142 case QwtSymbol::Rect:
143 QwtPainter::drawRect(painter, r);
144 break;
145 case QwtSymbol::Diamond:
146 {
147 const int w2 = r.width() / 2;
148 const int h2 = r.height() / 2;
149
150 QwtPolygon pa(4);
151 pa.setPoint(0, r.x() + w2, r.y());
152 pa.setPoint(1, r.right(), r.y() + h2);
153 pa.setPoint(2, r.x() + w2, r.bottom());
154 pa.setPoint(3, r.x(), r.y() + h2);
155 QwtPainter::drawPolygon(painter, pa);
156 break;
157 }
158 case QwtSymbol::Cross:
159 {
160 const int w2 = r.width() / 2;
161 const int h2 = r.height() / 2;
162
163 QwtPainter::drawLine(painter, r.x() + w2, r.y(),
164 r.x() + w2, r.bottom());
165 QwtPainter::drawLine(painter, r.x(), r.y() + h2,
166 r.right(), r.y() + h2);
167 break;
168 }
169 case QwtSymbol::XCross:
170 {
171 QwtPainter::drawLine(painter, r.left(), r.top(),
172 r.right(), r.bottom());
173 QwtPainter::drawLine(painter, r.left(), r.bottom(),
174 r.right(), r.top());
175 break;
176 }
177 case QwtSymbol::Triangle:
178 case QwtSymbol::UTriangle:
179 {
180 const int w2 = r.width() / 2;
181
182 QwtPolygon pa(3);
183 pa.setPoint(0, r.x() + w2, r.y());
184 pa.setPoint(1, r.right(), r.bottom());
185 pa.setPoint(2, r.x(), r.bottom());
186 QwtPainter::drawPolygon(painter, pa);
187 break;
188 }
189 case QwtSymbol::DTriangle:
190 {
191 const int w2 = r.width() / 2;
192
193 QwtPolygon pa(3);
194 pa.setPoint(0, r.x(), r.y());
195 pa.setPoint(1, r.right(), r.y());
196 pa.setPoint(2, r.x() + w2, r.bottom());
197 QwtPainter::drawPolygon(painter, pa);
198 break;
199 }
200 case QwtSymbol::RTriangle:
201 {
202 const int h2 = r.height() / 2;
203
204 QwtPolygon pa(3);
205 pa.setPoint(0, r.x(), r.y());
206 pa.setPoint(1, r.right(), r.y() + h2);
207 pa.setPoint(2, r.x(), r.bottom());
208 QwtPainter::drawPolygon(painter, pa);
209 break;
210 }
211 case QwtSymbol::LTriangle:
212 {
213 const int h2 = r.height() / 2;
214
215 QwtPolygon pa(3);
216 pa.setPoint(0, r.right(), r.y());
217 pa.setPoint(1, r.x(), r.y() + h2);
218 pa.setPoint(2, r.right(), r.bottom());
219 QwtPainter::drawPolygon(painter, pa);
220 break;
221 }
222 case QwtSymbol::HLine:
223 {
224 const int h2 = r.height() / 2;
225 QwtPainter::drawLine(painter, r.left(), r.top() + h2,
226 r.right(), r.top() + h2);
227 break;
228 }
229 case QwtSymbol::VLine:
230 {
231 const int w2 = r.width() / 2;
232 QwtPainter::drawLine(painter, r.left() + w2, r.top(),
233 r.left() + w2, r.bottom());
234 break;
235 }
236 case QwtSymbol::Star1:
237 {
238 const double sqrt1_2 = 0.70710678118654752440; /* 1/sqrt(2) */
239
240 const int w2 = r.width() / 2;
241 const int h2 = r.height() / 2;
242 const int d1 = (int)( (double)w2 * (1.0 - sqrt1_2) );
243
244 QwtPainter::drawLine(painter, r.left() + d1, r.top() + d1,
245 r.right() - d1, r.bottom() - d1);
246 QwtPainter::drawLine(painter, r.left() + d1, r.bottom() - d1,
247 r.right() - d1, r.top() + d1);
248 QwtPainter::drawLine(painter, r.left() + w2, r.top(),
249 r.left() + w2, r.bottom());
250 QwtPainter::drawLine(painter, r.left(), r.top() + h2,
251 r.right(), r.top() + h2);
252 break;
253 }
254 case QwtSymbol::Star2:
255 {
256 const int w = r.width();
257 const int side = (int)(((double)r.width() * (1.0 - 0.866025)) /
258 2.0); // 0.866025 = cos(30°)
259 const int h4 = r.height() / 4;
260 const int h2 = r.height() / 2;
261 const int h34 = (r.height() * 3) / 4;
262
263 QwtPolygon pa(12);
264 pa.setPoint(0, r.left() + (w / 2), r.top());
265 pa.setPoint(1, r.right() - (side + (w - 2 * side) / 3),
266 r.top() + h4 );
267 pa.setPoint(2, r.right() - side, r.top() + h4);
268 pa.setPoint(3, r.right() - (side + (w / 2 - side) / 3),
269 r.top() + h2 );
270 pa.setPoint(4, r.right() - side, r.top() + h34);
271 pa.setPoint(5, r.right() - (side + (w - 2 * side) / 3),
272 r.top() + h34 );
273 pa.setPoint(6, r.left() + (w / 2), r.bottom());
274 pa.setPoint(7, r.left() + (side + (w - 2 * side) / 3),
275 r.top() + h34 );
276 pa.setPoint(8, r.left() + side, r.top() + h34);
277 pa.setPoint(9, r.left() + (side + (w / 2 - side) / 3),
278 r.top() + h2 );
279 pa.setPoint(10, r.left() + side, r.top() + h4);
280 pa.setPoint(11, r.left() + (side + (w - 2 * side) / 3),
281 r.top() + h4 );
282 QwtPainter::drawPolygon(painter, pa);
283 break;
284 }
285 case QwtSymbol::Hexagon:
286 {
287 const int w2 = r.width() / 2;
288 const int side = (int)(((double)r.width() * (1.0 - 0.866025)) /
289 2.0); // 0.866025 = cos(30°)
290 const int h4 = r.height() / 4;
291 const int h34 = (r.height() * 3) / 4;
292
293 QwtPolygon pa(6);
294 pa.setPoint(0, r.left() + w2, r.top());
295 pa.setPoint(1, r.right() - side, r.top() + h4);
296 pa.setPoint(2, r.right() - side, r.top() + h34);
297 pa.setPoint(3, r.left() + w2, r.bottom());
298 pa.setPoint(4, r.left() + side, r.top() + h34);
299 pa.setPoint(5, r.left() + side, r.top() + h4);
300 QwtPainter::drawPolygon(painter, pa);
301 break;
302 }
303 default:;
304 }
305 }
306
307 /*!
308 \brief Draw the symbol at a specified point
309
310 \param painter Painter
311 \param pos Center of the symbol
312 */
draw(QPainter * painter,const QPoint & pos) const313 void QwtSymbol::draw(QPainter *painter, const QPoint &pos) const
314 {
315 QRect rect;
316 rect.setSize(QwtPainter::metricsMap().screenToLayout(d_size));
317 rect.moveCenter(pos);
318
319 painter->setBrush(d_brush);
320 painter->setPen(QwtPainter::scaledPen(d_pen));
321
322 draw(painter, rect);
323 }
324
325 /*!
326 \brief Specify the symbol style
327
328 The following styles are defined:<dl>
329 <dt>NoSymbol<dd>No Style. The symbol cannot be drawn.
330 <dt>Ellipse<dd>Ellipse or circle
331 <dt>Rect<dd>Rectangle
332 <dt>Diamond<dd>Diamond
333 <dt>Triangle<dd>Triangle pointing upwards
334 <dt>DTriangle<dd>Triangle pointing downwards
335 <dt>UTriangle<dd>Triangle pointing upwards
336 <dt>LTriangle<dd>Triangle pointing left
337 <dt>RTriangle<dd>Triangle pointing right
338 <dt>Cross<dd>Cross (+)
339 <dt>XCross<dd>Diagonal cross (X)
340 <dt>HLine<dd>Horizontal line
341 <dt>VLine<dd>Vertical line
342 <dt>Star1<dd>X combined with +
343 <dt>Star2<dd>Six-pointed star
344 <dt>Hexagon<dd>Hexagon</dl>
345
346 \param s style
347 */
setStyle(QwtSymbol::Style s)348 void QwtSymbol::setStyle(QwtSymbol::Style s)
349 {
350 d_style = s;
351 }
352
353 //! == operator
operator ==(const QwtSymbol & other) const354 bool QwtSymbol::operator==(const QwtSymbol &other) const
355 {
356 return brush() == other.brush() && pen() == other.pen()
357 && style() == other.style() && size() == other.size();
358 }
359
360 //! != operator
operator !=(const QwtSymbol & other) const361 bool QwtSymbol::operator!=(const QwtSymbol &other) const
362 {
363 return !(*this == other);
364 }
365