Coverage Report

Created: 2025-07-23 08:13

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