source: trunk/src/gui/painting/qpen.cpp@ 120

Last change on this file since 120 was 2, checked in by Dmitry A. Kuminov, 17 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 26.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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
49QT_BEGIN_NAMESPACE
50
51typedef QPenPrivate QPenData;
52
53/*!
54 \class QPen
55 \ingroup multimedia
56 \ingroup shared
57 \mainclass
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 \l{The 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*/
231inline 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
244static const Qt::PenCapStyle qpen_default_cap = Qt::SquareCap;
245static 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
249template <>
250class QGlobalStaticDeleter<QPenPrivate>
251{
252public:
253 QGlobalStatic<QPenPrivate> &globalStatic;
254 QGlobalStaticDeleter(QGlobalStatic<QPenPrivate> &_globalStatic)
255 : globalStatic(_globalStatic)
256 { }
257
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
268Q_GLOBAL_STATIC_WITH_ARGS(QPenData, defaultPenInstance,
269 (Qt::black, 0, Qt::SolidLine, qpen_default_cap, qpen_default_join))
270Q_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
277QPen::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
289QPen::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
306QPen::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
321QPen::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
332QPen::QPen(const QPen &p)
333{
334 d = p.d;
335 d->ref.ref();
336}
337
338
339/*!
340 Destroys the pen.
341*/
342
343QPen::~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
359void 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
379QPen &QPen::operator=(const QPen &p)
380{
381 qAtomicAssign(d, p.d);
382 return *this;
383}
384
385/*!
386 Returns the pen as a QVariant.
387*/
388QPen::operator QVariant() const
389{
390 return QVariant(QVariant::Pen, this);
391}
392
393/*!