/src/qtbase/src/gui/painting/qpen.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /**************************************************************************** |
2 | | ** |
3 | | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | | ** Contact: https://www.qt.io/licensing/ |
5 | | ** |
6 | | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | | ** |
8 | | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | | ** Commercial License Usage |
10 | | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | | ** accordance with the commercial license agreement provided with the |
12 | | ** Software or, alternatively, in accordance with the terms contained in |
13 | | ** a written agreement between you and The Qt Company. For licensing terms |
14 | | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | | ** information use the contact form at https://www.qt.io/contact-us. |
16 | | ** |
17 | | ** GNU Lesser General Public License Usage |
18 | | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | | ** General Public License version 3 as published by the Free Software |
20 | | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | | ** packaging of this file. Please review the following information to |
22 | | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | | ** |
25 | | ** GNU General Public License Usage |
26 | | ** Alternatively, this file may be used under the terms of the GNU |
27 | | ** General Public License version 2.0 or (at your option) the GNU General |
28 | | ** Public license version 3 or any later version approved by the KDE Free |
29 | | ** Qt Foundation. The licenses are as published by the Free Software |
30 | | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | | ** included in the packaging of this file. Please review the following |
32 | | ** information to ensure the GNU General Public License requirements will |
33 | | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | | ** |
36 | | ** $QT_END_LICENSE$ |
37 | | ** |
38 | | ****************************************************************************/ |
39 | | #include "qpen.h" |
40 | | #include "qpen_p.h" |
41 | | #include "qdatastream.h" |
42 | | #include "qvariant.h" |
43 | | #include "qbrush.h" |
44 | | |
45 | | #include <qdebug.h> |
46 | | |
47 | | QT_BEGIN_NAMESPACE |
48 | | |
49 | | typedef QPenPrivate QPenData; |
50 | | |
51 | | /*! |
52 | | \class QPen |
53 | | \inmodule QtGui |
54 | | \ingroup painting |
55 | | \ingroup shared |
56 | | |
57 | | |
58 | | \brief The QPen class defines how a QPainter should draw lines and outlines |
59 | | of shapes. |
60 | | |
61 | | A pen has a style(), width(), brush(), capStyle() and joinStyle(). |
62 | | |
63 | | The pen style defines the line type. The brush is used to fill |
64 | | strokes generated with the pen. Use the QBrush class to specify |
65 | | fill styles. The cap style determines the line end caps that can |
66 | | be drawn using QPainter, while the join style describes how joins |
67 | | between two lines are drawn. The pen width can be specified in |
68 | | both integer (width()) and floating point (widthF()) precision. A |
69 | | line width of zero indicates a cosmetic pen. This means that the |
70 | | pen width is always drawn one pixel wide, independent of the \l |
71 | | {QPainter#Coordinate Transformations}{transformation} set on the |
72 | | painter. |
73 | | |
74 | | The various settings can easily be modified using the |
75 | | corresponding setStyle(), setWidth(), setBrush(), setCapStyle() |
76 | | and setJoinStyle() functions (note that the painter's pen must be |
77 | | reset when altering the pen's properties). |
78 | | |
79 | | For example: |
80 | | |
81 | | \snippet code/src_gui_painting_qpen.cpp 0 |
82 | | |
83 | | which is equivalent to |
84 | | |
85 | | \snippet code/src_gui_painting_qpen.cpp 1 |
86 | | |
87 | | The default pen is a solid black brush with 1 width, square |
88 | | cap style (Qt::SquareCap), and bevel join style (Qt::BevelJoin). |
89 | | |
90 | | In addition QPen provides the color() and setColor() |
91 | | convenience functions to extract and set the color of the pen's |
92 | | brush, respectively. Pens may also be compared and streamed. |
93 | | |
94 | | For more information about painting in general, see the \l{Paint |
95 | | System} documentation. |
96 | | |
97 | | \tableofcontents |
98 | | |
99 | | \section1 Pen Style |
100 | | |
101 | | Qt provides several built-in styles represented by the |
102 | | Qt::PenStyle enum: |
103 | | |
104 | | \table |
105 | | \row |
106 | | \li \inlineimage qpen-solid.png |
107 | | \li \inlineimage qpen-dash.png |
108 | | \li \inlineimage qpen-dot.png |
109 | | \row |
110 | | \li Qt::SolidLine |
111 | | \li Qt::DashLine |
112 | | \li Qt::DotLine |
113 | | \row |
114 | | \li \inlineimage qpen-dashdot.png |
115 | | \li \inlineimage qpen-dashdotdot.png |
116 | | \li \inlineimage qpen-custom.png |
117 | | \row |
118 | | \li Qt::DashDotLine |
119 | | \li Qt::DashDotDotLine |
120 | | \li Qt::CustomDashLine |
121 | | \endtable |
122 | | |
123 | | Simply use the setStyle() function to convert the pen style to |
124 | | either of the built-in styles, except the Qt::CustomDashLine style |
125 | | which we will come back to shortly. Setting the style to Qt::NoPen |
126 | | tells the painter to not draw lines or outlines. The default pen |
127 | | style is Qt::SolidLine. |
128 | | |
129 | | Since Qt 4.1 it is also possible to specify a custom dash pattern |
130 | | using the setDashPattern() function which implicitly converts the |
131 | | style of the pen to Qt::CustomDashLine. The pattern argument, a |
132 | | QVector, must be specified as an even number of \l qreal entries |
133 | | where the entries 1, 3, 5... are the dashes and 2, 4, 6... are the |
134 | | spaces. For example, the custom pattern shown above is created |
135 | | using the following code: |
136 | | |
137 | | \snippet code/src_gui_painting_qpen.cpp 2 |
138 | | |
139 | | Note that the dash pattern is specified in units of the pens |
140 | | width, e.g. a dash of length 5 in width 10 is 50 pixels long. |
141 | | |
142 | | The currently set dash pattern can be retrieved using the |
143 | | dashPattern() function. Use the isSolid() function to determine |
144 | | whether the pen has a solid fill, or not. |
145 | | |
146 | | \section1 Cap Style |
147 | | |
148 | | The cap style defines how the end points of lines are drawn using |
149 | | QPainter. The cap style only apply to wide lines, i.e. when the |
150 | | width is 1 or greater. The Qt::PenCapStyle enum provides the |
151 | | following styles: |
152 | | |
153 | | \table |
154 | | \row |
155 | | \li \inlineimage qpen-square.png |
156 | | \li \inlineimage qpen-flat.png |
157 | | \li \inlineimage qpen-roundcap.png |
158 | | \row |
159 | | \li Qt::SquareCap |
160 | | \li Qt::FlatCap |
161 | | \li Qt::RoundCap |
162 | | \endtable |
163 | | |
164 | | The Qt::SquareCap style is a square line end that covers the end |
165 | | point and extends beyond it by half the line width. The |
166 | | Qt::FlatCap style is a square line end that does not cover the end |
167 | | point of the line. And the Qt::RoundCap style is a rounded line |
168 | | end covering the end point. |
169 | | |
170 | | The default is Qt::SquareCap. |
171 | | |
172 | | Whether or not end points are drawn when the pen width is 0 or 1 |
173 | | depends on the cap style. Using Qt::SquareCap or Qt::RoundCap they |
174 | | are drawn, using Qt::FlatCap they are not drawn. |
175 | | |
176 | | \section1 Join Style |
177 | | |
178 | | The join style defines how joins between two connected lines can |
179 | | be drawn using QPainter. The join style only apply to wide lines, |
180 | | i.e. when the width is 1 or greater. The Qt::PenJoinStyle enum |
181 | | provides the following styles: |
182 | | |
183 | | \table |
184 | | \row |
185 | | \li \inlineimage qpen-bevel.png |
186 | | \li \inlineimage qpen-miter.png |
187 | | \li \inlineimage qpen-roundjoin.png |
188 | | \row |
189 | | \li Qt::BevelJoin |
190 | | \li Qt::MiterJoin |
191 | | \li Qt::RoundJoin |
192 | | \endtable |
193 | | |
194 | | The Qt::BevelJoin style fills the triangular notch between the two |
195 | | lines. The Qt::MiterJoin style extends the lines to meet at an |
196 | | angle. And the Qt::RoundJoin style fills a circular arc between |
197 | | the two lines. |
198 | | |
199 | | The default is Qt::BevelJoin. |
200 | | |
201 | | \image qpen-miterlimit.png |
202 | | |
203 | | When the Qt::MiterJoin style is applied, it is possible to use the |
204 | | setMiterLimit() function to specify how far the miter join can |
205 | | extend from the join point. The miterLimit() is used to reduce |
206 | | artifacts between line joins where the lines are close to |
207 | | parallel. |
208 | | |
209 | | The miterLimit() must be specified in units of the pens width, |
210 | | e.g. a miter limit of 5 in width 10 is 50 pixels long. The |
211 | | default miter limit is 2, i.e. twice the pen width in pixels. |
212 | | |
213 | | \table 100% |
214 | | \row |
215 | | \li \inlineimage qpen-demo.png |
216 | | \li \b {\l {painting/pathstroke}{The Path Stroking Example}} |
217 | | |
218 | | The Path Stroking example shows Qt's built-in dash patterns and shows |
219 | | how custom patterns can be used to extend the range of available |
220 | | patterns. |
221 | | \endtable |
222 | | |
223 | | \sa QPainter, QBrush, {painting/pathstroke}{Path Stroking Example}, |
224 | | {Scribble Example} |
225 | | */ |
226 | | |
227 | | /*! |
228 | | \internal |
229 | | */ |
230 | | inline QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle penStyle, |
231 | | Qt::PenCapStyle _capStyle, Qt::PenJoinStyle _joinStyle, bool _defaultWidth) |
232 | 2 | : ref(1), dashOffset(0), miterLimit(2), |
233 | 2 | cosmetic(false), defaultWidth(_defaultWidth) |
234 | 2 | { |
235 | 2 | width = _width; |
236 | 2 | brush = _brush; |
237 | 2 | style = penStyle; |
238 | 2 | capStyle = _capStyle; |
239 | 2 | joinStyle = _joinStyle; |
240 | 2 | } |
241 | | |
242 | | static const Qt::PenCapStyle qpen_default_cap = Qt::SquareCap; |
243 | | static const Qt::PenJoinStyle qpen_default_join = Qt::BevelJoin; |
244 | | |
245 | | class QPenDataHolder |
246 | | { |
247 | | public: |
248 | | QPenData *pen; |
249 | | QPenDataHolder(const QBrush &brush, qreal width, Qt::PenStyle penStyle, |
250 | | Qt::PenCapStyle penCapStyle, Qt::PenJoinStyle _joinStyle) |
251 | 2 | : pen(new QPenData(brush, width, penStyle, penCapStyle, _joinStyle)) |
252 | 2 | { } |
253 | | ~QPenDataHolder() |
254 | 2 | { |
255 | 2 | if (!pen->ref.deref()) |
256 | 2 | delete pen; |
257 | 2 | pen = nullptr; |
258 | 2 | } |
259 | | }; |
260 | | |
261 | | Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, defaultPenInstance, |
262 | | (Qt::black, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join)) |
263 | | Q_GLOBAL_STATIC_WITH_ARGS(QPenDataHolder, nullPenInstance, |
264 | | (Qt::black, 1, Qt::NoPen, qpen_default_cap, qpen_default_join)) |
265 | | |
266 | | /*! |
267 | | Constructs a default black solid line pen with 1 width. |
268 | | */ |
269 | | |
270 | | QPen::QPen() |
271 | 3.16k | { |
272 | 3.16k | d = defaultPenInstance()->pen; |
273 | 3.16k | d->ref.ref(); |
274 | 3.16k | } |
275 | | |
276 | | /*! |
277 | | Constructs a black pen with 1 width and the given \a style. |
278 | | |
279 | | \sa setStyle() |
280 | | */ |
281 | | |
282 | | QPen::QPen(Qt::PenStyle style) |
283 | 1.58k | { |
284 | 1.58k | if (style == Qt::NoPen) { |
285 | 1.58k | d = nullPenInstance()->pen; |
286 | 1.58k | d->ref.ref(); |
287 | 1.58k | } else { |
288 | 0 | d = new QPenData(Qt::black, 1, style, qpen_default_cap, qpen_default_join); |
289 | 0 | } |
290 | 1.58k | } |
291 | | |
292 | | |
293 | | /*! |
294 | | Constructs a solid line pen with 1 width and the given \a color. |
295 | | |
296 | | \sa setBrush(), setColor() |
297 | | */ |
298 | | |
299 | | QPen::QPen(const QColor &color) |
300 | 0 | { |
301 | 0 | d = new QPenData(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join); |
302 | 0 | } |
303 | | |
304 | | |
305 | | /*! |
306 | | \fn QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle style, Qt::PenCapStyle cap, Qt::PenJoinStyle join) |
307 | | |
308 | | Constructs a pen with the specified \a brush, \a width, pen \a style, |
309 | | \a cap style and \a join style. |
310 | | |
311 | | \sa setBrush(), setWidth(), setStyle(), setCapStyle(), setJoinStyle() |
312 | | */ |
313 | | |
314 | | QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c, Qt::PenJoinStyle j) |
315 | 0 | { |
316 | 0 | d = new QPenData(brush, width, s, c, j, false); |
317 | 0 | } |
318 | | |
319 | | /*! |
320 | | \fn QPen::QPen(const QPen &pen) |
321 | | |
322 | | Constructs a pen that is a copy of the given \a pen. |
323 | | */ |
324 | | |
325 | | QPen::QPen(const QPen &p) noexcept |
326 | 1.58k | { |
327 | 1.58k | d = p.d; |
328 | 1.58k | if (d) |
329 | 1.58k | d->ref.ref(); |
330 | 1.58k | } |
331 | | |
332 | | |
333 | | /*! |
334 | | \fn QPen::QPen(QPen &&pen) |
335 | | \since 5.4 |
336 | | |
337 | | Constructs a pen that is moved from the given \a pen. |
338 | | |
339 | | The moved-from pen can only be assigned to, copied, or |
340 | | destroyed. Any other operation (prior to assignment) leads to |
341 | | undefined behavior. |
342 | | */ |
343 | | |
344 | | /*! |
345 | | Destroys the pen. |
346 | | */ |
347 | | |
348 | | QPen::~QPen() |
349 | 6.32k | { |
350 | 6.32k | if (d && !d->ref.deref()) |
351 | 0 | delete d; |
352 | 6.32k | } |
353 | | |
354 | | /*! |
355 | | \fn void QPen::detach() |
356 | | Detaches from shared pen data to make sure that this pen is the |
357 | | only one referring the data. |
358 | | |
359 | | If multiple pens share common data, this pen dereferences the data |
360 | | and gets a copy of the data. Nothing is done if there is just a |
361 | | single reference. |
362 | | */ |
363 | | |
364 | | void QPen::detach() |
365 | 0 | { |
366 | 0 | if (d->ref.loadRelaxed() == 1) |
367 | 0 | return; |
368 | | |
369 | 0 | QPenData *x = new QPenData(*static_cast<QPenData *>(d)); |
370 | 0 | if (!d->ref.deref()) |
371 | 0 | delete d; |
372 | 0 | x->ref.storeRelaxed(1); |
373 | 0 | d = x; |
374 | 0 | } |
375 | | |
376 | | |
377 | | /*! |
378 | | \fn QPen &QPen::operator=(const QPen &pen) |
379 | | |
380 | | Assigns the given \a pen to this pen and returns a reference to |
381 | | this pen. |
382 | | */ |
383 | | |
384 | | QPen &QPen::operator=(const QPen &p) noexcept |
385 | 1.58k | { |
386 | 1.58k | QPen(p).swap(*this); |
387 | 1.58k | return *this; |
388 | 1.58k | } |
389 | | |
390 | | /*! |
391 | | \fn QPen &QPen::operator=(QPen &&other) |
392 | | |
393 | | Move-assigns \a other to this QPen instance. |
394 | | |
395 | | \since 5.2 |
396 | | */ |
397 | | |
398 | | /*! |
399 | | \fn void QPen::swap(QPen &other) |
400 | | \since 4.8 |
401 | | |
402 | | Swaps pen \a other with this pen. This operation is very |
403 | | fast and never fails. |
404 | | */ |
405 | | |
406 | | /*! |
407 | | Returns the pen as a QVariant. |
408 | | */ |
409 | | QPen::operator QVariant() const |
410 | 0 | { |
411 | 0 | return QVariant(QMetaType::QPen, this); |
412 | 0 | } |
413 | | |
414 | | /*! |
415 | | \fn Qt::PenStyle QPen::style() const |
416 | | |
417 | | Returns the pen style. |
418 | | |
419 | | \sa setStyle(), {QPen#Pen Style}{Pen Style} |
420 | | */ |
421 | | Qt::PenStyle QPen::style() const |
422 | 1.58k | { |
423 | 1.58k | return d->style; |
424 | 1.58k | } |
425 | | /*! |
426 | | \fn void QPen::setStyle(Qt::PenStyle style) |
427 | | |
428 | | Sets the pen style to the given \a style. |
429 | | |
430 | | See the \l Qt::PenStyle documentation for a list of the available |
431 | | styles. Since Qt 4.1 it is also possible to specify a custom dash |
432 | | pattern using the setDashPattern() function which implicitly |
433 | | converts the style of the pen to Qt::CustomDashLine. |
434 | | |
435 | | \note This function resets the dash offset to zero. |
436 | | |
437 | | \sa style(), {QPen#Pen Style}{Pen Style} |
438 | | */ |
439 | | |
440 | | void QPen::setStyle(Qt::PenStyle s) |
441 | 0 | { |
442 | 0 | if (d->style == s) |
443 | 0 | return; |
444 | 0 | detach(); |
445 | 0 | d->style = s; |
446 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
447 | 0 | dd->dashPattern.clear(); |
448 | 0 | dd->dashOffset = 0; |
449 | 0 | } |
450 | | |
451 | | /*! |
452 | | Returns the dash pattern of this pen. |
453 | | |
454 | | \sa style(), isSolid() |
455 | | */ |
456 | | QVector<qreal> QPen::dashPattern() const |
457 | 1.58k | { |
458 | 1.58k | QPenData *dd = static_cast<QPenData *>(d); |
459 | 1.58k | if (d->style == Qt::SolidLine || d->style == Qt::NoPen) { |
460 | 1.58k | return QVector<qreal>(); |
461 | 1.58k | } else if (dd->dashPattern.isEmpty()) { |
462 | 0 | const qreal space = 2; |
463 | 0 | const qreal dot = 1; |
464 | 0 | const qreal dash = 4; |
465 | |
|
466 | 0 | switch (d->style) { |
467 | 0 | case Qt::DashLine: |
468 | 0 | dd->dashPattern.reserve(2); |
469 | 0 | dd->dashPattern << dash << space; |
470 | 0 | break; |
471 | 0 | case Qt::DotLine: |
472 | 0 | dd->dashPattern.reserve(2); |
473 | 0 | dd->dashPattern << dot << space; |
474 | 0 | break; |
475 | 0 | case Qt::DashDotLine: |
476 | 0 | dd->dashPattern.reserve(4); |
477 | 0 | dd->dashPattern << dash << space << dot << space; |
478 | 0 | break; |
479 | 0 | case Qt::DashDotDotLine: |
480 | 0 | dd->dashPattern.reserve(6); |
481 | 0 | dd->dashPattern << dash << space << dot << space << dot << space; |
482 | 0 | break; |
483 | 0 | default: |
484 | 0 | break; |
485 | 0 | } |
486 | 0 | } |
487 | 0 | return dd->dashPattern; |
488 | 1.58k | } |
489 | | |
490 | | /*! |
491 | | Sets the dash pattern for this pen to the given \a pattern. This |
492 | | implicitly converts the style of the pen to Qt::CustomDashLine. |
493 | | |
494 | | The pattern must be specified as an even number of positive entries |
495 | | where the entries 1, 3, 5... are the dashes and 2, 4, 6... are the |
496 | | spaces. For example: |
497 | | |
498 | | \table 100% |
499 | | \row |
500 | | \li \inlineimage qpen-custom.png |
501 | | \li |
502 | | \snippet code/src_gui_painting_qpen.cpp 3 |
503 | | \endtable |
504 | | |
505 | | The dash pattern is specified in units of the pens width; e.g. a |
506 | | dash of length 5 in width 10 is 50 pixels long. Note that a pen |
507 | | with zero width is equivalent to a cosmetic pen with a width of 1 |
508 | | pixel. |
509 | | |
510 | | Each dash is also subject to cap styles so a dash of 1 with square |
511 | | cap set will extend 0.5 pixels out in each direction resulting in |
512 | | a total width of 2. |
513 | | |
514 | | Note that the default cap style is Qt::SquareCap, meaning that a |
515 | | square line end covers the end point and extends beyond it by half |
516 | | the line width. |
517 | | |
518 | | \sa setStyle(), dashPattern(), setCapStyle(), setCosmetic() |
519 | | */ |
520 | | void QPen::setDashPattern(const QVector<qreal> &pattern) |
521 | 0 | { |
522 | 0 | if (pattern.isEmpty()) |
523 | 0 | return; |
524 | 0 | detach(); |
525 | |
|
526 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
527 | 0 | dd->dashPattern = pattern; |
528 | 0 | d->style = Qt::CustomDashLine; |
529 | |
|
530 | 0 | if ((dd->dashPattern.size() % 2) == 1) { |
531 | 0 | qWarning("QPen::setDashPattern: Pattern not of even length"); |
532 | 0 | dd->dashPattern << 1; |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | | |
537 | | /*! |
538 | | Returns the dash offset for the pen. |
539 | | |
540 | | \sa setDashOffset() |
541 | | */ |
542 | | qreal QPen::dashOffset() const |
543 | 1.58k | { |
544 | 1.58k | QPenData *dd = static_cast<QPenData *>(d); |
545 | 1.58k | return dd->dashOffset; |
546 | 1.58k | } |
547 | | /*! |
548 | | Sets the dash offset (the starting point on the dash pattern) for this pen |
549 | | to the \a offset specified. The offset is measured in terms of the units used |
550 | | to specify the dash pattern. |
551 | | |
552 | | \table |
553 | | \row \li \inlineimage qpen-dashpattern.png |
554 | | \li For example, a pattern where each stroke is four units long, followed by a gap |
555 | | of two units, will begin with the stroke when drawn as a line. |
556 | | |
557 | | However, if the dash offset is set to 4.0, any line drawn will begin with the gap. |
558 | | Values of the offset up to 4.0 will cause part of the stroke to be drawn first, |
559 | | and values of the offset between 4.0 and 6.0 will cause the line to begin with |
560 | | part of the gap. |
561 | | \endtable |
562 | | |
563 | | \note This implicitly converts the style of the pen to Qt::CustomDashLine. |
564 | | */ |
565 | | void QPen::setDashOffset(qreal offset) |
566 | 0 | { |
567 | 0 | if (qFuzzyCompare(offset, static_cast<QPenData *>(d)->dashOffset)) |
568 | 0 | return; |
569 | 0 | detach(); |
570 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
571 | 0 | dd->dashOffset = offset; |
572 | 0 | if (d->style != Qt::CustomDashLine) { |
573 | 0 | dd->dashPattern = dashPattern(); |
574 | 0 | d->style = Qt::CustomDashLine; |
575 | 0 | } |
576 | 0 | } |
577 | | |
578 | | /*! |
579 | | Returns the miter limit of the pen. The miter limit is only |
580 | | relevant when the join style is set to Qt::MiterJoin. |
581 | | |
582 | | \sa setMiterLimit(), {QPen#Join Style}{Join Style} |
583 | | */ |
584 | | qreal QPen::miterLimit() const |
585 | 1.58k | { |
586 | 1.58k | const QPenData *dd = static_cast<QPenData *>(d); |
587 | 1.58k | return dd->miterLimit; |
588 | 1.58k | } |
589 | | |
590 | | /*! |
591 | | Sets the miter limit of this pen to the given \a limit. |
592 | | |
593 | | \image qpen-miterlimit.png |
594 | | |
595 | | The miter limit describes how far a miter join can extend from the |
596 | | join point. This is used to reduce artifacts between line joins |
597 | | where the lines are close to parallel. |
598 | | |
599 | | This value does only have effect when the pen style is set to |
600 | | Qt::MiterJoin. The value is specified in units of the pen's width, |
601 | | e.g. a miter limit of 5 in width 10 is 50 pixels long. The default |
602 | | miter limit is 2, i.e. twice the pen width in pixels. |
603 | | |
604 | | \sa miterLimit(), setJoinStyle(), {QPen#Join Style}{Join Style} |
605 | | */ |
606 | | void QPen::setMiterLimit(qreal limit) |
607 | 0 | { |
608 | 0 | detach(); |
609 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
610 | 0 | dd->miterLimit = limit; |
611 | 0 | } |
612 | | |
613 | | |
614 | | /*! |
615 | | \fn qreal QPen::width() const |
616 | | |
617 | | Returns the pen width with integer precision. |
618 | | |
619 | | \sa setWidth(), widthF() |
620 | | */ |
621 | | |
622 | | int QPen::width() const |
623 | 0 | { |
624 | 0 | return qRound(d->width); |
625 | 0 | } |
626 | | |
627 | | /*! |
628 | | \fn qreal QPen::widthF() const |
629 | | |
630 | | Returns the pen width with floating point precision. |
631 | | |
632 | | \sa setWidthF(), width() |
633 | | */ |
634 | | qreal QPen::widthF() const |
635 | 1.58k | { |
636 | 1.58k | return d->width; |
637 | 1.58k | } |
638 | | |
639 | | /*! |
640 | | \fn QPen::setWidth(int width) |
641 | | |
642 | | Sets the pen width to the given \a width in pixels with integer |
643 | | precision. |
644 | | |
645 | | A line width of zero indicates a cosmetic pen. This means that the |
646 | | pen width is always drawn one pixel wide, independent of the \l |
647 | | {QPainter#Coordinate Transformations}{transformation} set on the |
648 | | painter. |
649 | | |
650 | | Setting a pen width with a negative value is not supported. |
651 | | |
652 | | \sa setWidthF(), width() |
653 | | */ |
654 | | void QPen::setWidth(int width) |
655 | 0 | { |
656 | 0 | if (width < 0 || width >= (1 << 15)) { |
657 | 0 | qWarning("QPen::setWidth: Setting a pen width that is out of range"); |
658 | 0 | return; |
659 | 0 | } |
660 | 0 | if ((qreal)width == d->width) |
661 | 0 | return; |
662 | 0 | detach(); |
663 | 0 | d->width = width; |
664 | 0 | d->defaultWidth = false; |
665 | 0 | } |
666 | | |
667 | | /*! |
668 | | Sets the pen width to the given \a width in pixels with floating point |
669 | | precision. |
670 | | |
671 | | A line width of zero indicates a cosmetic pen. This means that the |
672 | | pen width is always drawn one pixel wide, independent of the \l |
673 | | {QPainter#Coordinate Transformations}{transformation} on the |
674 | | painter. |
675 | | |
676 | | Setting a pen width with a negative value is not supported. |
677 | | |
678 | | \sa setWidth(), widthF() |
679 | | */ |
680 | | |
681 | | void QPen::setWidthF(qreal width) |
682 | 0 | { |
683 | 0 | if (width < 0.f || width >= (1 << 15)) { |
684 | 0 | qWarning("QPen::setWidthF: Setting a pen width that is out of range"); |
685 | 0 | return; |
686 | 0 | } |
687 | 0 | if (qAbs(d->width - width) < 0.00000001f) |
688 | 0 | return; |
689 | 0 | detach(); |
690 | 0 | d->width = width; |
691 | 0 | d->defaultWidth = false; |
692 | 0 | } |
693 | | |
694 | | |
695 | | /*! |
696 | | Returns the pen's cap style. |
697 | | |
698 | | \sa setCapStyle(), {QPen#Cap Style}{Cap Style} |
699 | | */ |
700 | | Qt::PenCapStyle QPen::capStyle() const |
701 | 1.58k | { |
702 | 1.58k | return d->capStyle; |
703 | 1.58k | } |
704 | | |
705 | | /*! |
706 | | \fn void QPen::setCapStyle(Qt::PenCapStyle style) |
707 | | |
708 | | Sets the pen's cap style to the given \a style. The default value |
709 | | is Qt::SquareCap. |
710 | | |
711 | | \sa capStyle(), {QPen#Cap Style}{Cap Style} |
712 | | */ |
713 | | |
714 | | void QPen::setCapStyle(Qt::PenCapStyle c) |
715 | 0 | { |
716 | 0 | if (d->capStyle == c) |
717 | 0 | return; |
718 | 0 | detach(); |
719 | 0 | d->capStyle = c; |
720 | 0 | } |
721 | | |
722 | | /*! |
723 | | Returns the pen's join style. |
724 | | |
725 | | \sa setJoinStyle(), {QPen#Join Style}{Join Style} |
726 | | */ |
727 | | Qt::PenJoinStyle QPen::joinStyle() const |
728 | 0 | { |
729 | 0 | return d->joinStyle; |
730 | 0 | } |
731 | | |
732 | | /*! |
733 | | \fn void QPen::setJoinStyle(Qt::PenJoinStyle style) |
734 | | |
735 | | Sets the pen's join style to the given \a style. The default value |
736 | | is Qt::BevelJoin. |
737 | | |
738 | | \sa joinStyle(), {QPen#Join Style}{Join Style} |
739 | | */ |
740 | | |
741 | | void QPen::setJoinStyle(Qt::PenJoinStyle j) |
742 | 0 | { |
743 | 0 | if (d->joinStyle == j) |
744 | 0 | return; |
745 | 0 | detach(); |
746 | 0 | d->joinStyle = j; |
747 | 0 | } |
748 | | |
749 | | /*! |
750 | | \fn const QColor &QPen::color() const |
751 | | |
752 | | Returns the color of this pen's brush. |
753 | | |
754 | | \sa brush(), setColor() |
755 | | */ |
756 | | QColor QPen::color() const |
757 | 0 | { |
758 | 0 | return d->brush.color(); |
759 | 0 | } |
760 | | |
761 | | /*! |
762 | | \fn void QPen::setColor(const QColor &color) |
763 | | |
764 | | Sets the color of this pen's brush to the given \a color. |
765 | | |
766 | | \sa setBrush(), color() |
767 | | */ |
768 | | |
769 | | void QPen::setColor(const QColor &c) |
770 | 0 | { |
771 | 0 | detach(); |
772 | 0 | d->brush = QBrush(c); |
773 | 0 | } |
774 | | |
775 | | |
776 | | /*! |
777 | | Returns the brush used to fill strokes generated with this pen. |
778 | | */ |
779 | | QBrush QPen::brush() const |
780 | 6.32k | { |
781 | 6.32k | return d->brush; |
782 | 6.32k | } |
783 | | |
784 | | /*! |
785 | | Sets the brush used to fill strokes generated with this pen to the given |
786 | | \a brush. |
787 | | |
788 | | \sa brush(), setColor() |
789 | | */ |
790 | | void QPen::setBrush(const QBrush &brush) |
791 | 0 | { |
792 | 0 | detach(); |
793 | 0 | d->brush = brush; |
794 | 0 | } |
795 | | |
796 | | |
797 | | /*! |
798 | | Returns \c true if the pen has a solid fill, otherwise false. |
799 | | |
800 | | \sa style(), dashPattern() |
801 | | */ |
802 | | bool QPen::isSolid() const |
803 | 0 | { |
804 | 0 | return d->brush.style() == Qt::SolidPattern; |
805 | 0 | } |
806 | | |
807 | | |
808 | | /*! |
809 | | Returns \c true if the pen is cosmetic; otherwise returns \c false. |
810 | | |
811 | | Cosmetic pens are used to draw strokes that have a constant width |
812 | | regardless of any transformations applied to the QPainter they are |
813 | | used with. Drawing a shape with a cosmetic pen ensures that its |
814 | | outline will have the same thickness at different scale factors. |
815 | | |
816 | | A zero width pen is cosmetic by default. |
817 | | |
818 | | \sa setCosmetic(), widthF() |
819 | | */ |
820 | | |
821 | | bool QPen::isCosmetic() const |
822 | 3.16k | { |
823 | 3.16k | QPenData *dd = static_cast<QPenData *>(d); |
824 | 3.16k | return (dd->cosmetic == true) || d->width == 0; |
825 | 3.16k | } |
826 | | |
827 | | |
828 | | /*! |
829 | | Sets this pen to cosmetic or non-cosmetic, depending on the value of |
830 | | \a cosmetic. |
831 | | |
832 | | \sa isCosmetic() |
833 | | */ |
834 | | |
835 | | void QPen::setCosmetic(bool cosmetic) |
836 | 0 | { |
837 | 0 | detach(); |
838 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
839 | 0 | dd->cosmetic = cosmetic; |
840 | 0 | } |
841 | | |
842 | | |
843 | | |
844 | | /*! |
845 | | \fn bool QPen::operator!=(const QPen &pen) const |
846 | | |
847 | | Returns \c true if the pen is different from the given \a pen; |
848 | | otherwise false. Two pens are different if they have different |
849 | | styles, widths or colors. |
850 | | |
851 | | \sa operator==() |
852 | | */ |
853 | | |
854 | | /*! |
855 | | \fn bool QPen::operator==(const QPen &pen) const |
856 | | |
857 | | Returns \c true if the pen is equal to the given \a pen; otherwise |
858 | | false. Two pens are equal if they have equal styles, widths and |
859 | | colors. |
860 | | |
861 | | \sa operator!=() |
862 | | */ |
863 | | |
864 | | bool QPen::operator==(const QPen &p) const |
865 | 0 | { |
866 | 0 | QPenData *dd = static_cast<QPenData *>(d); |
867 | 0 | QPenData *pdd = static_cast<QPenData *>(p.d); |
868 | 0 | return (p.d == d) |
869 | 0 | || (p.d->style == d->style |
870 | 0 | && p.d->capStyle == d->capStyle |
871 | 0 | && p.d->joinStyle == d->joinStyle |
872 | 0 | && p.d->width == d->width |
873 | 0 | && pdd->miterLimit == dd->miterLimit |
874 | 0 | && (d->style != Qt::CustomDashLine |
875 | 0 | || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) && |
876 | 0 | pdd->dashPattern == dd->dashPattern)) |
877 | 0 | && p.d->brush == d->brush |
878 | 0 | && pdd->cosmetic == dd->cosmetic |
879 | 0 | && pdd->defaultWidth == dd->defaultWidth); |
880 | 0 | } |
881 | | |
882 | | |
883 | | /*! |
884 | | \fn bool QPen::isDetached() |
885 | | |
886 | | \internal |
887 | | */ |
888 | | |
889 | | bool QPen::isDetached() |
890 | 0 | { |
891 | 0 | return d->ref.loadRelaxed() == 1; |
892 | 0 | } |
893 | | |
894 | | |
895 | | /***************************************************************************** |
896 | | QPen stream functions |
897 | | *****************************************************************************/ |
898 | | #ifndef QT_NO_DATASTREAM |
899 | | /*! |
900 | | \fn QDataStream &operator<<(QDataStream &stream, const QPen &pen) |
901 | | \relates QPen |
902 | | |
903 | | Writes the given \a pen to the given \a stream and returns a reference to |
904 | | the \a stream. |
905 | | |
906 | | \sa {Serializing Qt Data Types} |
907 | | */ |
908 | | |
909 | | QDataStream &operator<<(QDataStream &s, const QPen &p) |
910 | 0 | { |
911 | 0 | QPenData *dd = static_cast<QPenData *>(p.d); |
912 | 0 | if (s.version() < 3) { |
913 | 0 | s << (quint8)p.style(); |
914 | 0 | } else if (s.version() < QDataStream::Qt_4_3) { |
915 | 0 | s << (quint8)(p.style() | p.capStyle() | p.joinStyle()); |
916 | 0 | } else { |
917 | 0 | s << (quint16)(p.style() | p.capStyle() | p.joinStyle()); |
918 | 0 | s << (bool)(dd->cosmetic); |
919 | 0 | } |
920 | |
|
921 | 0 | if (s.version() < 7) { |
922 | 0 | s << (quint8)p.width(); |
923 | 0 | s << p.color(); |
924 | 0 | } else { |
925 | 0 | s << double(p.widthF()); |
926 | 0 | s << p.brush(); |
927 | 0 | s << double(p.miterLimit()); |
928 | 0 | if (sizeof(qreal) == sizeof(double)) { |
929 | 0 | s << p.dashPattern(); |
930 | 0 | } else { |
931 | | // ensure that we write doubles here instead of streaming the pattern |
932 | | // directly; otherwise, platforms that redefine qreal might generate |
933 | | // data that cannot be read on other platforms. |
934 | 0 | QVector<qreal> pattern = p.dashPattern(); |
935 | 0 | s << quint32(pattern.size()); |
936 | 0 | for (int i = 0; i < pattern.size(); ++i) |
937 | 0 | s << double(pattern.at(i)); |
938 | 0 | } |
939 | 0 | if (s.version() >= 9) |
940 | 0 | s << double(p.dashOffset()); |
941 | 0 | if (s.version() >= QDataStream::Qt_5_0) |
942 | 0 | s << bool(dd->defaultWidth); |
943 | 0 | } |
944 | 0 | return s; |
945 | 0 | } |
946 | | |
947 | | /*! |
948 | | \fn QDataStream &operator>>(QDataStream &stream, QPen &pen) |
949 | | \relates QPen |
950 | | |
951 | | Reads a pen from the given \a stream into the given \a pen and |
952 | | returns a reference to the \a stream. |
953 | | |
954 | | \sa {Serializing Qt Data Types} |
955 | | */ |
956 | | |
957 | | QDataStream &operator>>(QDataStream &s, QPen &p) |
958 | 0 | { |
959 | 0 | quint16 style; |
960 | 0 | quint8 width8 = 0; |
961 | 0 | double width = 0; |
962 | 0 | QColor color; |
963 | 0 | QBrush brush; |
964 | 0 | double miterLimit = 2; |
965 | 0 | QVector<qreal> dashPattern; |
966 | 0 | double dashOffset = 0; |
967 | 0 | bool cosmetic = false; |
968 | 0 | bool defaultWidth = false; |
969 | 0 | if (s.version() < QDataStream::Qt_4_3) { |
970 | 0 | quint8 style8; |
971 | 0 | s >> style8; |
972 | 0 | style = style8; |
973 | 0 | } else { |
974 | 0 | s >> style; |
975 | 0 | s >> cosmetic; |
976 | 0 | } |
977 | 0 | if (s.version() < 7) { |
978 | 0 | s >> width8; |
979 | 0 | s >> color; |
980 | 0 | brush = color; |
981 | 0 | width = width8; |
982 | 0 | } else { |
983 | 0 | s >> width; |
984 | 0 | s >> brush; |
985 | 0 | s >> miterLimit; |
986 | 0 | if (sizeof(qreal) == sizeof(double)) { |
987 | 0 | s >> dashPattern; |
988 | 0 | } else { |
989 | 0 | quint32 numDashes; |
990 | 0 | s >> numDashes; |
991 | 0 | double dash; |
992 | 0 | dashPattern.reserve(numDashes); |
993 | 0 | for (quint32 i = 0; i < numDashes; ++i) { |
994 | 0 | s >> dash; |
995 | 0 | dashPattern << dash; |
996 | 0 | } |
997 | 0 | } |
998 | 0 | if (s.version() >= 9) |
999 | 0 | s >> dashOffset; |
1000 | 0 | } |
1001 | |
|
1002 | 0 | if (s.version() >= QDataStream::Qt_5_0) { |
1003 | 0 | s >> defaultWidth; |
1004 | 0 | } else { |
1005 | | // best we can do for legacy pens |
1006 | 0 | defaultWidth = qFuzzyIsNull(width); |
1007 | 0 | } |
1008 | |
|
1009 | 0 | p.detach(); |
1010 | 0 | QPenData *dd = static_cast<QPenData *>(p.d); |
1011 | 0 | dd->width = width; |
1012 | 0 | dd->brush = brush; |
1013 | 0 | dd->style = Qt::PenStyle(style & Qt::MPenStyle); |
1014 | 0 | dd->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle); |
1015 | 0 | dd->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle); |
1016 | 0 | dd->dashPattern = dashPattern; |
1017 | 0 | dd->miterLimit = miterLimit; |
1018 | 0 | dd->dashOffset = dashOffset; |
1019 | 0 | dd->cosmetic = cosmetic; |
1020 | 0 | dd->defaultWidth = defaultWidth; |
1021 | |
|
1022 | 0 | return s; |
1023 | 0 | } |
1024 | | #endif //QT_NO_DATASTREAM |
1025 | | |
1026 | | #ifndef QT_NO_DEBUG_STREAM |
1027 | | QDebug operator<<(QDebug dbg, const QPen &p) |
1028 | 0 | { |
1029 | 0 | const char *PEN_STYLES[] = { |
1030 | 0 | "NoPen", |
1031 | 0 | "SolidLine", |
1032 | 0 | "DashLine", |
1033 | 0 | "DotLine", |
1034 | 0 | "DashDotLine", |
1035 | 0 | "DashDotDotLine", |
1036 | 0 | "CustomDashLine" |
1037 | 0 | }; |
1038 | |
|
1039 | 0 | QDebugStateSaver saver(dbg); |
1040 | 0 | dbg.nospace() << "QPen(" << p.width() << ',' << p.brush() |
1041 | 0 | << ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle()) |
1042 | 0 | << ',' << int(p.joinStyle()) << ',' << p.dashPattern() |
1043 | 0 | << ',' << p.dashOffset() |
1044 | 0 | << ',' << p.miterLimit() << ')'; |
1045 | 0 | return dbg; |
1046 | 0 | } |
1047 | | #endif |
1048 | | |
1049 | | /*! |
1050 | | \fn DataPtr &QPen::data_ptr() |
1051 | | \internal |
1052 | | */ |
1053 | | |
1054 | | /*! |
1055 | | \typedef QPen::DataPtr |
1056 | | |
1057 | | \internal |
1058 | | */ |
1059 | | |
1060 | | QT_END_NAMESPACE |
1061 | | |
1062 | | #undef QT_COMPILING_QPEN |