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

source code of qtbase/src/gui/painting/qpen.cpp