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