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 */
QPenPrivate(const QBrush & _brush,qreal _width,Qt::PenStyle penStyle,Qt::PenCapStyle _capStyle,Qt::PenJoinStyle _joinStyle,bool _defaultWidth)230 inline QPenPrivate::QPenPrivate(const QBrush &_brush, qreal _width, Qt::PenStyle penStyle,
231                                 Qt::PenCapStyle _capStyle, Qt::PenJoinStyle _joinStyle, bool _defaultWidth)
232     : ref(1), dashOffset(0), miterLimit(2),
233       cosmetic(false), defaultWidth(_defaultWidth)
234 {
235     width = _width;
236     brush = _brush;
237     style = penStyle;
238     capStyle = _capStyle;
239     joinStyle = _joinStyle;
240 }
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;
QPenDataHolder(const QBrush & brush,qreal width,Qt::PenStyle penStyle,Qt::PenCapStyle penCapStyle,Qt::PenJoinStyle _joinStyle)249     QPenDataHolder(const QBrush &brush, qreal width, Qt::PenStyle penStyle,
250                    Qt::PenCapStyle penCapStyle, Qt::PenJoinStyle _joinStyle)
251         : pen(new QPenData(brush, width, penStyle, penCapStyle, _joinStyle))
252     { }
~QPenDataHolder()253     ~QPenDataHolder()
254     {
255         if (!pen->ref.deref())
256             delete pen;
257         pen = nullptr;
258     }
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 
QPen()270 QPen::QPen()
271 {
272     d = defaultPenInstance()->pen;
273     d->ref.ref();
274 }
275 
276 /*!
277     Constructs a black pen with 1 width and the given \a style.
278 
279     \sa setStyle()
280 */
281 
QPen(Qt::PenStyle style)282 QPen::QPen(Qt::PenStyle style)
283 {
284     if (style == Qt::NoPen) {
285         d = nullPenInstance()->pen;
286         d->ref.ref();
287     } else {
288         d = new QPenData(Qt::black, 1, style, qpen_default_cap, qpen_default_join);
289     }
290 }
291 
292 
293 /*!
294     Constructs a solid line pen with 1 width and the given \a color.
295 
296     \sa setBrush(), setColor()
297 */
298 
QPen(const QColor & color)299 QPen::QPen(const QColor &color)
300 {
301     d = new QPenData(color, 1, Qt::SolidLine, qpen_default_cap, qpen_default_join);
302 }
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 
QPen(const QBrush & brush,qreal width,Qt::PenStyle s,Qt::PenCapStyle c,Qt::PenJoinStyle j)314 QPen::QPen(const QBrush &brush, qreal width, Qt::PenStyle s, Qt::PenCapStyle c, Qt::PenJoinStyle j)
315 {
316     d = new QPenData(brush, width, s, c, j, false);
317 }
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 
QPen(const QPen & p)325 QPen::QPen(const QPen &p) noexcept
326 {
327     d = p.d;
328     if (d)
329         d->ref.ref();
330 }
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 
~QPen()348 QPen::~QPen()
349 {
350     if (d && !d->ref.deref())
351         delete d;
352 }
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 
detach()364 void QPen::detach()
365 {
366     if (d->ref.loadRelaxed() == 1)
367         return;
368 
369     QPenData *x = new QPenData(*static_cast<QPenData *>(d));
370     if (!d->ref.deref())
371         delete d;
372     x->ref.storeRelaxed(1);
373     d = x;
374 }
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 
operator =(const QPen & p)384 QPen &QPen::operator=(const QPen &p) noexcept
385 {
386     QPen(p).swap(*this);
387     return *this;
388 }
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 */
operator QVariant() const409 QPen::operator QVariant() const
410 {
411     return QVariant(QMetaType::QPen, this);
412 }
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 */
style() const421 Qt::PenStyle QPen::style() const
422 {
423     return d->style;
424 }
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 
setStyle(Qt::PenStyle s)440 void QPen::setStyle(Qt::PenStyle s)
441 {
442     if (d->style == s)
443         return;
444     detach();
445     d->style = s;
446     QPenData *dd = static_cast<QPenData *>(d);
447     dd->dashPattern.clear();
448     dd->dashOffset = 0;
449 }
450 
451 /*!
452     Returns the dash pattern of this pen.
453 
454     \sa style(), isSolid()
455  */
dashPattern() const456 QVector<qreal> QPen::dashPattern() const
457 {
458     QPenData *dd = static_cast<QPenData *>(d);
459     if (d->style == Qt::SolidLine || d->style == Qt::NoPen) {
460         return QVector<qreal>();
461     } else if (dd->dashPattern.isEmpty()) {
462         const qreal space = 2;
463         const qreal dot = 1;
464         const qreal dash = 4;
465 
466         switch (d->style) {
467         case Qt::DashLine:
468             dd->dashPattern.reserve(2);
469             dd->dashPattern << dash << space;
470             break;
471         case Qt::DotLine:
472             dd->dashPattern.reserve(2);
473             dd->dashPattern << dot << space;
474             break;
475         case Qt::DashDotLine:
476             dd->dashPattern.reserve(4);
477             dd->dashPattern << dash << space << dot << space;
478             break;
479         case Qt::DashDotDotLine:
480             dd->dashPattern.reserve(6);
481             dd->dashPattern << dash << space << dot << space << dot << space;
482             break;
483         default:
484             break;
485         }
486     }
487     return dd->dashPattern;
488 }
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  */
setDashPattern(const QVector<qreal> & pattern)520 void QPen::setDashPattern(const QVector<qreal> &pattern)
521 {
522     if (pattern.isEmpty())
523         return;
524     detach();
525 
526     QPenData *dd = static_cast<QPenData *>(d);
527     dd->dashPattern = pattern;
528     d->style = Qt::CustomDashLine;
529 
530     if ((dd->dashPattern.size() % 2) == 1) {
531         qWarning("QPen::setDashPattern: Pattern not of even length");
532         dd->dashPattern << 1;
533     }
534 }
535 
536 
537 /*!
538     Returns the dash offset for the pen.
539 
540     \sa setDashOffset()
541 */
dashOffset() const542 qreal QPen::dashOffset() const
543 {
544     QPenData *dd = static_cast<QPenData *>(d);
545     return dd->dashOffset;
546 }
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 */
setDashOffset(qreal offset)565 void QPen::setDashOffset(qreal offset)
566 {
567     if (qFuzzyCompare(offset, static_cast<QPenData *>(d)->dashOffset))
568         return;
569     detach();
570     QPenData *dd = static_cast<QPenData *>(d);
571     dd->dashOffset = offset;
572     if (d->style != Qt::CustomDashLine) {
573         dd->dashPattern = dashPattern();
574         d->style = Qt::CustomDashLine;
575     }
576 }
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 */
miterLimit() const584 qreal QPen::miterLimit() const
585 {
586     const QPenData *dd = static_cast<QPenData *>(d);
587     return dd->miterLimit;
588 }
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 */
setMiterLimit(qreal limit)606 void QPen::setMiterLimit(qreal limit)
607 {
608     detach();
609     QPenData *dd = static_cast<QPenData *>(d);
610     dd->miterLimit = limit;
611 }
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 
width() const622 int QPen::width() const
623 {
624     return qRound(d->width);
625 }
626 
627 /*!
628     \fn qreal QPen::widthF() const
629 
630     Returns the pen width with floating point precision.
631 
632     \sa setWidthF(), width()
633 */
widthF() const634 qreal QPen::widthF() const
635 {
636     return d->width;
637 }
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 */
setWidth(int width)654 void QPen::setWidth(int width)
655 {
656     if (width < 0 || width >= (1 << 15)) {
657         qWarning("QPen::setWidth: Setting a pen width that is out of range");
658         return;
659     }
660     if ((qreal)width == d->width)
661         return;
662     detach();
663     d->width = width;
664     d->defaultWidth = false;
665 }
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 
setWidthF(qreal width)681 void QPen::setWidthF(qreal width)
682 {
683     if (width < 0.f || width >= (1 << 15)) {
684         qWarning("QPen::setWidthF: Setting a pen width that is out of range");
685         return;
686     }
687     if (qAbs(d->width - width) < 0.00000001f)
688         return;
689     detach();
690     d->width = width;
691     d->defaultWidth = false;
692 }
693 
694 
695 /*!
696     Returns the pen's cap style.
697 
698     \sa setCapStyle(), {QPen#Cap Style}{Cap Style}
699 */
capStyle() const700 Qt::PenCapStyle QPen::capStyle() const
701 {
702     return d->capStyle;
703 }
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 
setCapStyle(Qt::PenCapStyle c)714 void QPen::setCapStyle(Qt::PenCapStyle c)
715 {
716     if (d->capStyle == c)
717         return;
718     detach();
719     d->capStyle = c;
720 }
721 
722 /*!
723     Returns the pen's join style.
724 
725     \sa setJoinStyle(), {QPen#Join Style}{Join Style}
726 */
joinStyle() const727 Qt::PenJoinStyle QPen::joinStyle() const
728 {
729     return d->joinStyle;
730 }
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 
setJoinStyle(Qt::PenJoinStyle j)741 void QPen::setJoinStyle(Qt::PenJoinStyle j)
742 {
743     if (d->joinStyle == j)
744         return;
745     detach();
746     d->joinStyle = j;
747 }
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 */
color() const756 QColor QPen::color() const
757 {
758     return d->brush.color();
759 }
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 
setColor(const QColor & c)769 void QPen::setColor(const QColor &c)
770 {
771     detach();
772     d->brush = QBrush(c);
773 }
774 
775 
776 /*!
777     Returns the brush used to fill strokes generated with this pen.
778 */
brush() const779 QBrush QPen::brush() const
780 {
781     return d->brush;
782 }
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 */
setBrush(const QBrush & brush)790 void QPen::setBrush(const QBrush &brush)
791 {
792     detach();
793     d->brush = brush;
794 }
795 
796 
797 /*!
798     Returns \c true if the pen has a solid fill, otherwise false.
799 
800     \sa style(), dashPattern()
801 */
isSolid() const802 bool QPen::isSolid() const
803 {
804     return d->brush.style() == Qt::SolidPattern;
805 }
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 
isCosmetic() const821 bool QPen::isCosmetic() const
822 {
823     QPenData *dd = static_cast<QPenData *>(d);
824     return (dd->cosmetic == true) || d->width == 0;
825 }
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 
setCosmetic(bool cosmetic)835 void QPen::setCosmetic(bool cosmetic)
836 {
837     detach();
838     QPenData *dd = static_cast<QPenData *>(d);
839     dd->cosmetic = cosmetic;
840 }
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 
operator ==(const QPen & p) const864 bool QPen::operator==(const QPen &p) const
865 {
866     QPenData *dd = static_cast<QPenData *>(d);
867     QPenData *pdd = static_cast<QPenData *>(p.d);
868     return (p.d == d)
869         || (p.d->style == d->style
870             && p.d->capStyle == d->capStyle
871             && p.d->joinStyle == d->joinStyle
872             && p.d->width == d->width
873             && pdd->miterLimit == dd->miterLimit
874             && (d->style != Qt::CustomDashLine
875                 || (qFuzzyCompare(pdd->dashOffset, dd->dashOffset) &&
876                     pdd->dashPattern == dd->dashPattern))
877             && p.d->brush == d->brush
878             && pdd->cosmetic == dd->cosmetic
879             && pdd->defaultWidth == dd->defaultWidth);
880 }
881 
882 
883 /*!
884     \fn bool QPen::isDetached()
885 
886     \internal
887 */
888 
isDetached()889 bool QPen::isDetached()
890 {
891     return d->ref.loadRelaxed() == 1;
892 }
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 
operator <<(QDataStream & s,const QPen & p)909 QDataStream &operator<<(QDataStream &s, const QPen &p)
910 {
911     QPenData *dd = static_cast<QPenData *>(p.d);
912     if (s.version() < 3) {
913         s << (quint8)p.style();
914     } else if (s.version() < QDataStream::Qt_4_3) {
915         s << (quint8)(p.style() | p.capStyle() | p.joinStyle());
916     } else {
917         s << (quint16)(p.style() | p.capStyle() | p.joinStyle());
918         s << (bool)(dd->cosmetic);
919     }
920 
921     if (s.version() < 7) {
922         s << (quint8)p.width();
923         s << p.color();
924     } else {
925         s << double(p.widthF());
926         s << p.brush();
927         s << double(p.miterLimit());
928         if (sizeof(qreal) == sizeof(double)) {
929             s << p.dashPattern();
930         } 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             QVector<qreal> pattern = p.dashPattern();
935             s << quint32(pattern.size());
936             for (int i = 0; i < pattern.size(); ++i)
937                 s << double(pattern.at(i));
938         }
939         if (s.version() >= 9)
940             s << double(p.dashOffset());
941         if (s.version() >= QDataStream::Qt_5_0)
942             s << bool(dd->defaultWidth);
943     }
944     return s;
945 }
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 
operator >>(QDataStream & s,QPen & p)957 QDataStream &operator>>(QDataStream &s, QPen &p)
958 {
959     quint16 style;
960     quint8 width8 = 0;
961     double width = 0;
962     QColor color;
963     QBrush brush;
964     double miterLimit = 2;
965     QVector<qreal> dashPattern;
966     double dashOffset = 0;
967     bool cosmetic = false;
968     bool defaultWidth = false;
969     if (s.version() < QDataStream::Qt_4_3) {
970         quint8 style8;
971         s >> style8;
972         style = style8;
973     } else {
974         s >> style;
975         s >> cosmetic;
976     }
977     if (s.version() < 7) {
978         s >> width8;
979         s >> color;
980         brush = color;
981         width = width8;
982     } else {
983         s >> width;
984         s >> brush;
985         s >> miterLimit;
986         if (sizeof(qreal) == sizeof(double)) {
987             s >> dashPattern;
988         } else {
989             quint32 numDashes;
990             s >> numDashes;
991             double dash;
992             dashPattern.reserve(numDashes);
993             for (quint32 i = 0; i < numDashes; ++i) {
994                 s >> dash;
995                 dashPattern << dash;
996             }
997         }
998         if (s.version() >= 9)
999             s >> dashOffset;
1000     }
1001 
1002     if (s.version() >= QDataStream::Qt_5_0) {
1003         s >> defaultWidth;
1004     } else {
1005         // best we can do for legacy pens
1006         defaultWidth = qFuzzyIsNull(width);
1007     }
1008 
1009     p.detach();
1010     QPenData *dd = static_cast<QPenData *>(p.d);
1011     dd->width = width;
1012     dd->brush = brush;
1013     dd->style = Qt::PenStyle(style & Qt::MPenStyle);
1014     dd->capStyle = Qt::PenCapStyle(style & Qt::MPenCapStyle);
1015     dd->joinStyle = Qt::PenJoinStyle(style & Qt::MPenJoinStyle);
1016     dd->dashPattern = dashPattern;
1017     dd->miterLimit = miterLimit;
1018     dd->dashOffset = dashOffset;
1019     dd->cosmetic = cosmetic;
1020     dd->defaultWidth = defaultWidth;
1021 
1022     return s;
1023 }
1024 #endif //QT_NO_DATASTREAM
1025 
1026 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug dbg,const QPen & p)1027 QDebug operator<<(QDebug dbg, const QPen &p)
1028 {
1029     const char *PEN_STYLES[] = {
1030         "NoPen",
1031         "SolidLine",
1032         "DashLine",
1033         "DotLine",
1034         "DashDotLine",
1035         "DashDotDotLine",
1036         "CustomDashLine"
1037     };
1038 
1039     QDebugStateSaver saver(dbg);
1040     dbg.nospace() << "QPen(" << p.width() << ',' << p.brush()
1041                   << ',' << PEN_STYLES[p.style()] << ',' << int(p.capStyle())
1042                   << ',' << int(p.joinStyle()) << ',' << p.dashPattern()
1043                   << ',' << p.dashOffset()
1044                   << ',' << p.miterLimit() << ')';
1045     return dbg;
1046 }
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
1063