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