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
42 #include "qbrush.h"
43 #include "qpixmap.h"
44 #include "qbitmap.h"
45 #include "qpixmapcache.h"
46 #include "qdatastream.h"
47 #include "qvariant.h"
48 #include "qline.h"
49 #include "qdebug.h"
50 #include <QtCore/qcoreapplication.h>
51 #include "private/qstylehelper_p.h"
52 #include <QtCore/qnumeric.h>
53
54 QT_BEGIN_NAMESPACE
55
qt_patternForBrush(int brushStyle,bool invert)56 const uchar *qt_patternForBrush(int brushStyle, bool invert)
57 {
58 Q_ASSERT(brushStyle > Qt::SolidPattern && brushStyle < Qt::LinearGradientPattern);
59 if(invert) {
60 static const uchar dense1_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
61 static const uchar dense2_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
62 static const uchar dense3_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
63 static const uchar dense4_pat[] = { 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 };
64 static const uchar dense5_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
65 static const uchar dense6_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
66 static const uchar dense7_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
67 static const uchar hor_pat[] = { 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 };
68 static const uchar ver_pat[] = { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 };
69 static const uchar cross_pat[] = { 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0x10 };
70 static const uchar bdiag_pat[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
71 static const uchar fdiag_pat[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
72 static const uchar dcross_pat[] = { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 };
73 static const uchar *const pat_tbl[] = {
74 dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
75 dense6_pat, dense7_pat,
76 hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
77 return pat_tbl[brushStyle - Qt::Dense1Pattern];
78 }
79 static const uchar dense1_pat[] = { 0x00, 0x44, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00 };
80 static const uchar dense2_pat[] = { 0x88, 0x00, 0x22, 0x00, 0x88, 0x00, 0x22, 0x00 };
81 static const uchar dense3_pat[] = { 0xaa, 0x44, 0xaa, 0x11, 0xaa, 0x44, 0xaa, 0x11 };
82 static const uchar dense4_pat[] = { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa };
83 static const uchar dense5_pat[] = { 0x55, 0xbb, 0x55, 0xee, 0x55, 0xbb, 0x55, 0xee };
84 static const uchar dense6_pat[] = { 0x77, 0xff, 0xdd, 0xff, 0x77, 0xff, 0xdd, 0xff };
85 static const uchar dense7_pat[] = { 0xff, 0xbb, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xff };
86 static const uchar hor_pat[] = { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff };
87 static const uchar ver_pat[] = { 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef };
88 static const uchar cross_pat[] = { 0xef, 0xef, 0xef, 0x00, 0xef, 0xef, 0xef, 0xef };
89 static const uchar bdiag_pat[] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
90 static const uchar fdiag_pat[] = { 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f };
91 static const uchar dcross_pat[] = { 0x7e, 0xbd, 0xdb, 0xe7, 0xe7, 0xdb, 0xbd, 0x7e };
92 static const uchar *const pat_tbl[] = {
93 dense1_pat, dense2_pat, dense3_pat, dense4_pat, dense5_pat,
94 dense6_pat, dense7_pat,
95 hor_pat, ver_pat, cross_pat, bdiag_pat, fdiag_pat, dcross_pat };
96 return pat_tbl[brushStyle - Qt::Dense1Pattern];
97 }
98
qt_pixmapForBrush(int brushStyle,bool invert)99 QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
100 {
101
102 QPixmap pm;
103 QString key = QLatin1Literal("$qt-brush$")
104 % HexString<uint>(brushStyle)
105 % QLatin1Char(invert ? '1' : '0');
106 if (!QPixmapCache::find(key, pm)) {
107 pm = QBitmap::fromData(QSize(8, 8), qt_patternForBrush(brushStyle, invert),
108 QImage::Format_MonoLSB);
109 QPixmapCache::insert(key, pm);
110 }
111
112 return pm;
113 }
114
115 class QBrushPatternImageCache
116 {
117 public:
QBrushPatternImageCache()118 QBrushPatternImageCache()
119 : m_initialized(false)
120 {
121 init();
122 }
123
init()124 void init()
125 {
126 for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) {
127 int i = style - Qt::Dense1Pattern;
128 m_images[i][0] = QImage(qt_patternForBrush(style, 0), 8, 8, 1, QImage::Format_MonoLSB);
129 m_images[i][1] = QImage(qt_patternForBrush(style, 1), 8, 8, 1, QImage::Format_MonoLSB);
130 }
131 m_initialized = true;
132 }
133
getImage(int brushStyle,bool invert) const134 QImage getImage(int brushStyle, bool invert) const
135 {
136 Q_ASSERT(brushStyle >= Qt::Dense1Pattern && brushStyle <= Qt::DiagCrossPattern);
137 if (!m_initialized)
138 const_cast<QBrushPatternImageCache*>(this)->init();
139 return m_images[brushStyle - Qt::Dense1Pattern][invert];
140 }
141
cleanup()142 void cleanup() {
143 for (int style = Qt::Dense1Pattern; style <= Qt::DiagCrossPattern; ++style) {
144 int i = style - Qt::Dense1Pattern;
145 m_images[i][0] = QImage();
146 m_images[i][1] = QImage();
147 }
148 m_initialized = false;
149 }
150
151 private:
152 QImage m_images[Qt::DiagCrossPattern - Qt::Dense1Pattern + 1][2];
153 bool m_initialized;
154 };
155
156 static void qt_cleanup_brush_pattern_image_cache();
157 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushPatternImageCache, qt_brushPatternImageCache,
158 {
159 qAddPostRoutine(qt_cleanup_brush_pattern_image_cache);
160 })
161
qt_cleanup_brush_pattern_image_cache()162 static void qt_cleanup_brush_pattern_image_cache()
163 {
164 qt_brushPatternImageCache()->cleanup();
165 }
166
qt_imageForBrush(int brushStyle,bool invert)167 Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert)
168 {
169 return qt_brushPatternImageCache()->getImage(brushStyle, invert);
170 }
171
172 struct QTexturedBrushData : public QBrushData
173 {
QTexturedBrushDataQTexturedBrushData174 QTexturedBrushData() {
175 m_has_pixmap_texture = false;
176 m_pixmap = 0;
177 }
~QTexturedBrushDataQTexturedBrushData178 ~QTexturedBrushData() {
179 delete m_pixmap;
180 }
181
setPixmapQTexturedBrushData182 void setPixmap(const QPixmap &pm) {
183 delete m_pixmap;
184
185 if (pm.isNull()) {
186 m_pixmap = 0;
187 m_has_pixmap_texture = false;
188 } else {
189 m_pixmap = new QPixmap(pm);
190 m_has_pixmap_texture = true;
191 }
192
193 m_image = QImage();
194 }
195
setImageQTexturedBrushData196 void setImage(const QImage &image) {
197 m_image = image;
198 delete m_pixmap;
199 m_pixmap = 0;
200 m_has_pixmap_texture = false;
201 }
202
pixmapQTexturedBrushData203 QPixmap &pixmap() {
204 if (!m_pixmap) {
205 m_pixmap = new QPixmap(QPixmap::fromImage(m_image));
206 }
207 return *m_pixmap;
208 }
209
imageQTexturedBrushData210 QImage &image() {
211 if (m_image.isNull() && m_pixmap)
212 m_image = m_pixmap->toImage();
213 return m_image;
214 }
215
216 QPixmap *m_pixmap;
217 QImage m_image;
218 bool m_has_pixmap_texture;
219 };
220
221 // returns true if the brush has a pixmap (or bitmap) set as the
222 // brush texture, false otherwise
qHasPixmapTexture(const QBrush & brush)223 bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
224 {
225 if (brush.style() != Qt::TexturePattern)
226 return false;
227 QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data());
228 return tx_data->m_has_pixmap_texture;
229 }
230
231 struct QGradientBrushData : public QBrushData
232 {
233 QGradient gradient;
234 };
235
236 struct QBrushDataPointerDeleter
237 {
deleteDataQBrushDataPointerDeleter238 static inline void deleteData(QBrushData *d)
239 {
240 switch (d->style) {
241 case Qt::TexturePattern:
242 delete static_cast<QTexturedBrushData*>(d);
243 break;
244 case Qt::LinearGradientPattern:
245 case Qt::RadialGradientPattern:
246 case Qt::ConicalGradientPattern:
247 delete static_cast<QGradientBrushData*>(d);
248 break;
249 default:
250 delete d;
251 }
252 }
253
cleanupQBrushDataPointerDeleter254 static inline void cleanup(QBrushData *d)
255 {
256 if (d && !d->ref.deref()) {
257 deleteData(d);
258 }
259 }
260 };
261
262 /*!
263 \class QBrush
264 \ingroup painting
265 \ingroup shared
266
267 \brief The QBrush class defines the fill pattern of shapes drawn
268 by QPainter.
269
270 A brush has a style, a color, a gradient and a texture.
271
272 The brush style() defines the fill pattern using the
273 Qt::BrushStyle enum. The default brush style is Qt::NoBrush
274 (depending on how you construct a brush). This style tells the
275 painter to not fill shapes. The standard style for filling is
276 Qt::SolidPattern. The style can be set when the brush is created
277 using the appropriate constructor, and in addition the setStyle()
278 function provides means for altering the style once the brush is
279 constructed.
280
281 \image brush-styles.png Brush Styles
282
283 The brush color() defines the color of the fill pattern. The color
284 can either be one of Qt's predefined colors, Qt::GlobalColor, or
285 any other custom QColor. The currently set color can be retrieved
286 and altered using the color() and setColor() functions,
287 respectively.
288
289 The gradient() defines the gradient fill used when the current
290 style is either Qt::LinearGradientPattern,
291 Qt::RadialGradientPattern or Qt::ConicalGradientPattern. Gradient
292 brushes are created by giving a QGradient as a constructor
293 argument when creating the QBrush. Qt provides three different
294 gradients: QLinearGradient, QConicalGradient, and QRadialGradient
295 - all of which inherit QGradient.
296
297 \snippet doc/src/snippets/brush/gradientcreationsnippet.cpp 0
298
299 The texture() defines the pixmap used when the current style is
300 Qt::TexturePattern. You can create a brush with a texture by
301 providing the pixmap when the brush is created or by using
302 setTexture().
303
304 Note that applying setTexture() makes style() ==
305 Qt::TexturePattern, regardless of previous style
306 settings. Also, calling setColor() will not make a difference if
307 the style is a gradient. The same is the case if the style is
308 Qt::TexturePattern style unless the current texture is a QBitmap.
309
310 The isOpaque() function returns true if the brush is fully opaque
311 otherwise false. A brush is considered opaque if:
312
313 \list
314 \o The alpha component of the color() is 255.
315 \o Its texture() does not have an alpha channel and is not a QBitmap.
316 \o The colors in the gradient() all have an alpha component that is 255.
317 \endlist
318
319 \table 100%
320 \row
321 \o \inlineimage brush-outline.png Outlines
322 \o
323
324 To specify the style and color of lines and outlines, use the
325 QPainter's \l {QPen}{pen} combined with Qt::PenStyle and
326 Qt::GlobalColor:
327
328 \snippet doc/src/snippets/code/src_gui_painting_qbrush.cpp 0
329
330 Note that, by default, QPainter renders the outline (using the
331 currently set pen) when drawing shapes. Use \l {Qt::NoPen}{\c
332 painter.setPen(Qt::NoPen)} to disable this behavior.
333
334 \endtable
335
336 For more information about painting in general, see the \l{Paint
337 System}.
338
339 \sa Qt::BrushStyle, QPainter, QColor
340 */
341
342 #ifndef QT_NO_THREAD
343 // Special deleter that only deletes if the ref-count goes to zero
344 template <>
345 class QGlobalStaticDeleter<QBrushData>
346 {
347 public:
348 QGlobalStatic<QBrushData> &globalStatic;
QGlobalStaticDeleter(QGlobalStatic<QBrushData> & _globalStatic)349 QGlobalStaticDeleter(QGlobalStatic<QBrushData> &_globalStatic)
350 : globalStatic(_globalStatic)
351 { }
352
~QGlobalStaticDeleter()353 inline ~QGlobalStaticDeleter()
354 {
355 if (!globalStatic.pointer->ref.deref())
356 delete globalStatic.pointer;
357 globalStatic.pointer = 0;
358 globalStatic.destroyed = true;
359 }
360 };
361 #endif
362
363 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushData, nullBrushInstance,
364 {
365 x->ref = 1;
366 x->style = Qt::BrushStyle(0);
367 x->color = Qt::black;
368 })
369
qbrush_check_type(Qt::BrushStyle style)370 static bool qbrush_check_type(Qt::BrushStyle style) {
371 switch (style) {
372 case Qt::TexturePattern:
373 qWarning("QBrush: Incorrect use of TexturePattern");
374 break;
375 case Qt::LinearGradientPattern:
376 case Qt::RadialGradientPattern:
377 case Qt::ConicalGradientPattern:
378 qWarning("QBrush: Wrong use of a gradient pattern");
379 break;
380 default:
381 return true;
382 }
383 return false;
384 }
385
386 /*!
387 \internal
388 Initializes the brush.
389 */
390
init(const QColor & color,Qt::BrushStyle style)391 void QBrush::init(const QColor &color, Qt::BrushStyle style)
392 {
393 switch(style) {
394 case Qt::NoBrush:
395 d.reset(nullBrushInstance());
396 d->ref.ref();
397 if (d->color != color) setColor(color);
398 return;
399 case Qt::TexturePattern:
400 d.reset(new QTexturedBrushData);
401 break;
402 case Qt::LinearGradientPattern:
403 case Qt::RadialGradientPattern:
404 case Qt::ConicalGradientPattern:
405 d.reset(new QGradientBrushData);
406 break;
407 default:
408 d.reset(new QBrushData);
409 break;
410 }
411 d->ref = 1;
412 d->style = style;
413 d->color = color;
414 }
415
416 /*!
417 Constructs a default black brush with the style Qt::NoBrush
418 (i.e. this brush will not fill shapes).
419 */
420
QBrush()421 QBrush::QBrush()
422 : d(nullBrushInstance())
423 {
424 Q_ASSERT(d);
425 d->ref.ref();
426 }
427
428 /*!
429 Constructs a brush with a black color and a texture set to the
430 given \a pixmap. The style is set to Qt::TexturePattern.
431
432 \sa setTexture()
433 */
434
QBrush(const QPixmap & pixmap)435 QBrush::QBrush(const QPixmap &pixmap)
436 {
437 init(Qt::black, Qt::TexturePattern);
438 setTexture(pixmap);
439 }
440
441
442 /*!
443 Constructs a brush with a black color and a texture set to the
444 given \a image. The style is set to Qt::TexturePattern.
445
446 \sa setTextureImage()
447 */
448
QBrush(const QImage & image)449 QBrush::QBrush(const QImage &image)
450 {
451 init(Qt::black, Qt::TexturePattern);
452 setTextureImage(image);
453 }
454
455 /*!
456 Constructs a black brush with the given \a style.
457
458 \sa setStyle()
459 */
460
QBrush(Qt::BrushStyle style)461 QBrush::QBrush(Qt::BrushStyle style)
462 {
463 if (qbrush_check_type(style))
464 init(Qt::black, style);
465 else {
466 d.reset(nullBrushInstance());
467 d->ref.ref();
468 }
469 }
470
471 /*!
472 Constructs a brush with the given \a color and \a style.
473
474 \sa setColor(), setStyle()
475 */
476
QBrush(const QColor & color,Qt::BrushStyle style)477 QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
478 {
479 if (qbrush_check_type(style))
480 init(color, style);
481 else {
482 d.reset(nullBrushInstance());
483 d->ref.ref();
484 }
485 }
486
487 /*!
488 \fn QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
489
490 Constructs a brush with the given \a color and \a style.
491
492 \sa setColor(), setStyle()
493 */
QBrush(Qt::GlobalColor color,Qt::BrushStyle style)494 QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
495 {
496 if (qbrush_check_type(style))
497 init(color, style);
498 else {
499 d.reset(nullBrushInstance());
500 d->ref.ref();
501 }
502 }
503
504 /*!
505 Constructs a brush with the given \a color and the custom pattern
506 stored in \a pixmap.
507
508 The style is set to Qt::TexturePattern. The color will only have
509 an effect for QBitmaps.
510
511 \sa setColor(), setPixmap()
512 */
513
QBrush(const QColor & color,const QPixmap & pixmap)514 QBrush::QBrush(const QColor &color, const QPixmap &pixmap)
515 {
516 init(color, Qt::TexturePattern);
517 setTexture(pixmap);
518 }
519
520 /*!
521
522 Constructs a brush with the given \a color and the custom pattern
523 stored in \a pixmap.
524
525 The style is set to Qt::TexturePattern. The color will only have
526 an effect for QBitmaps.
527
528 \sa setColor(), setPixmap()
529 */
QBrush(Qt::GlobalColor color,const QPixmap & pixmap)530 QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap)
531 {
532 init(color, Qt::TexturePattern);
533 setTexture(pixmap);
534 }
535
536 /*!
537 Constructs a copy of \a other.
538 */
539
QBrush(const QBrush & other)540 QBrush::QBrush(const QBrush &other)
541 : d(other.d.data())
542 {
543 d->ref.ref();
544 }
545
546 /*!
547 Constructs a brush based on the given \a gradient.
548
549 The brush style is set to the corresponding gradient style (either
550 Qt::LinearGradientPattern, Qt::RadialGradientPattern or
551 Qt::ConicalGradientPattern).
552 */
QBrush(const QGradient & gradient)553 QBrush::QBrush(const QGradient &gradient)
554 {
555 Q_ASSERT_X(gradient.type() != QGradient::NoGradient, "QBrush::QBrush",
556 "QGradient should not be used directly, use the linear, radial\n"
557 "or conical gradients instead");
558
559 const Qt::BrushStyle enum_table[] = {
560 Qt::LinearGradientPattern,
561 Qt::RadialGradientPattern,
562 Qt::ConicalGradientPattern
563 };
564
565 init(QColor(), enum_table[gradient.type()]);
566 QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data());
567 grad->gradient = gradient;
568 }
569
570 /*!
571 Destroys the brush.
572 */
573
~QBrush()574 QBrush::~QBrush()
575 {
576 }
577
cleanUp(QBrushData * x)578 void QBrush::cleanUp(QBrushData *x)
579 {
580 QBrushDataPointerDeleter::deleteData(x);
581 }
582
583
detach(Qt::BrushStyle newStyle)584 void QBrush::detach(Qt::BrushStyle newStyle)
585 {
586 if (newStyle == d->style && d->ref == 1)
587 return;
588
589 QScopedPointer<QBrushData> x;
590 switch(newStyle) {
591 case Qt::TexturePattern: {
592 QTexturedBrushData *tbd = new QTexturedBrushData;
593 if (d->style == Qt::TexturePattern) {
594 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
595 if (data->m_has_pixmap_texture)
596 tbd->setPixmap(data->pixmap());
597 else
598 tbd->setImage(data->image());
599 }
600 x.reset(tbd);
601 break;
602 }
603 case Qt::LinearGradientPattern:
604 case Qt::RadialGradientPattern:
605 case Qt::ConicalGradientPattern:
606 x.reset(new QGradientBrushData);
607 static_cast<QGradientBrushData *>(x.data())->gradient =
608 static_cast<QGradientBrushData *>(d.data())->gradient;
609 break;
610 default:
611 x.reset(new QBrushData);
612 break;
613 }
614 x->ref = 1;
615 x->style = newStyle;
616 x->color = d->color;
617 x->transform = d->transform;
618 d.reset(x.take());
619 }
620
621
622 /*!
623 \fn QBrush &QBrush::operator=(const QBrush &brush)
624
625 Assigns the given \a brush to \e this brush and returns a
626 reference to \e this brush.
627 */
628
operator =(const QBrush & b)629 QBrush &QBrush::operator=(const QBrush &b)
630 {
631 if (d == b.d)
632 return *this;
633
634 b.d->ref.ref();
635 d.reset(b.d.data());
636 return *this;
637 }
638
639
640 /*!
641 \fn void QBrush::swap(QBrush &other)
642 \since 4.8
643
644 Swaps brush \a other with this brush. This operation is very
645 fast and never fails.
646 */
647
648 /*!
649 Returns the brush as a QVariant
650 */
operator QVariant() const651 QBrush::operator QVariant() const
652 {
653 return QVariant(QVariant::Brush, this);
654 }
655
656 /*!
657 \fn Qt::BrushStyle QBrush::style() const
658
659 Returns the brush style.
660
661 \sa setStyle()
662 */
663
664 /*!
665 Sets the brush style to \a style.
666
667 \sa style()
668 */
669
setStyle(Qt::BrushStyle style)670 void QBrush::setStyle(Qt::BrushStyle style)
671 {
672 if (d->style == style)
673 return;
674
675 if (qbrush_check_type(style)) {
676 detach(style);
677 d->style = style;
678 }
679 }
680
681
682 /*!
683 \fn const QColor &QBrush::color() const
684
685 Returns the brush color.
686
687 \sa setColor()
688 */
689
690 /*!
691 \fn void QBrush::setColor(const QColor &color)
692
693 Sets the brush color to the given \a color.
694
695 Note that calling setColor() will not make a difference if the
696 style is a gradient. The same is the case if the style is
697 Qt::TexturePattern style unless the current texture is a QBitmap.
698
699 \sa color()
700 */
701
setColor(const QColor & c)702 void QBrush::setColor(const QColor &c)
703 {
704 detach(d->style);
705 d->color = c;
706 }
707
708 /*!
709 \fn void QBrush::setColor(Qt::GlobalColor color)
710 \overload
711
712 Sets the brush color to the given \a color.
713 */
714
715
716 #ifdef QT3_SUPPORT
717
718 /*!
719 \fn void QBrush::setPixmap(const QPixmap &pixmap)
720
721 \compat
722
723 Sets a custom pattern for this brush.
724
725 Use setTexture() instead.
726 */
727
728 /*!
729 \fn QPixmap *QBrush::pixmap() const
730
731 Returns a pointer to the custom brush pattern.
732
733 Use texture() instead.
734 */
pixmap() const735 QPixmap *QBrush::pixmap() const
736 {
737 if (d->style != Qt::TexturePattern)
738 return 0;
739 QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data());
740 QPixmap &pixmap = data->pixmap();
741 return pixmap.isNull() ? 0 : &pixmap;
742 }
743 #endif
744
745 /*!
746 \fn QPixmap QBrush::texture() const
747
748 Returns the custom brush pattern, or a null pixmap if no custom brush pattern
749 has been set.
750
751 \sa setTexture()
752 */
texture() const753 QPixmap QBrush::texture() const
754 {
755 return d->style == Qt::TexturePattern
756 ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap()
757 : QPixmap();
758 }
759
760 /*!
761 Sets the brush pixmap to \a pixmap. The style is set to
762 Qt::TexturePattern.
763
764 The current brush color will only have an effect for monochrome
765 pixmaps, i.e. for QPixmap::depth() == 1 (\l {QBitmap}{QBitmaps}).
766
767 \sa texture()
768 */
769
setTexture(const QPixmap & pixmap)770 void QBrush::setTexture(const QPixmap &pixmap)
771 {
772 if (!pixmap.isNull()) {
773 detach(Qt::TexturePattern);
774 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
775 data->setPixmap(pixmap);
776 } else {
777 detach(Qt::NoBrush);
778 }
779 }
780
781
782 /*!
783 \since 4.2
784
785 Returns the custom brush pattern, or a null image if no custom
786 brush pattern has been set.
787
788 If the texture was set as a QPixmap it will be converted to a
789 QImage.
790
791 \sa setTextureImage()
792 */
793
textureImage() const794 QImage QBrush::textureImage() const
795 {
796 return d->style == Qt::TexturePattern
797 ? (static_cast<QTexturedBrushData *>(d.data()))->image()
798 : QImage();
799 }
800
801
802 /*!
803 \since 4.2
804
805 Sets the brush image to \a image. The style is set to
806 Qt::TexturePattern.
807
808 Note the current brush color will \e not have any affect on
809 monochrome images, as opposed to calling setTexture() with a
810 QBitmap. If you want to change the color of monochrome image
811 brushes, either convert the image to QBitmap with \c
812 QBitmap::fromImage() and set the resulting QBitmap as a texture,
813 or change the entries in the color table for the image.
814
815 \sa textureImage(), setTexture()
816 */
817
setTextureImage(const QImage & image)818 void QBrush::setTextureImage(const QImage &image)
819 {
820 if (!image.isNull()) {
821 detach(Qt::TexturePattern);
822 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
823 data->setImage(image);
824 } else {
825 detach(Qt::NoBrush);
826 }
827 }
828
829
830 /*!
831 Returns the gradient describing this brush.
832 */
gradient() const833 const QGradient *QBrush::gradient() const
834 {
835 if (d->style == Qt::LinearGradientPattern
836 || d->style == Qt::RadialGradientPattern
837 || d->style == Qt::ConicalGradientPattern) {
838 return &static_cast<const QGradientBrushData *>(d.data())->gradient;
839 }
840 return 0;
841 }
842
qt_isExtendedRadialGradient(const QBrush & brush)843 Q_GUI_EXPORT bool qt_isExtendedRadialGradient(const QBrush &brush)
844 {
845 if (brush.style() == Qt::RadialGradientPattern) {
846 const QGradient *g = brush.gradient();
847 const QRadialGradient *rg = static_cast<const QRadialGradient *>(g);
848
849 if (!qFuzzyIsNull(rg->focalRadius()))
850 return true;
851
852 QPointF delta = rg->focalPoint() - rg->center();
853 if (delta.x() * delta.x() + delta.y() * delta.y() > rg->radius() * rg->radius())
854 return true;
855 }
856
857 return false;
858 }
859
860 /*!
861 Returns true if the brush is fully opaque otherwise false. A brush
862 is considered opaque if:
863
864 \list
865 \i The alpha component of the color() is 255.
866 \i Its texture() does not have an alpha channel and is not a QBitmap.
867 \i The colors in the gradient() all have an alpha component that is 255.
868 \i It is an extended radial gradient.
869 \endlist
870 */
871
isOpaque() const872 bool QBrush::isOpaque() const
873 {
874 bool opaqueColor = d->color.alpha() == 255;
875
876 // Test awfully simple case first
877 if (d->style == Qt::SolidPattern)
878 return opaqueColor;
879
880 if (qt_isExtendedRadialGradient(*this))
881 return false;
882
883 if (d->style == Qt::LinearGradientPattern
884 || d->style == Qt::RadialGradientPattern
885 || d->style == Qt::ConicalGradientPattern) {
886 QGradientStops stops = gradient()->stops();
887 for (int i=0; i<stops.size(); ++i)
888 if (stops.at(i).second.alpha() != 255)
889 return false;
890 return true;
891 } else if (d->style == Qt::TexturePattern) {
892 return qHasPixmapTexture(*this)
893 ? !texture().hasAlphaChannel() && !texture().isQBitmap()
894 : !textureImage().hasAlphaChannel();
895 }
896
897 return false;
898 }
899
900
901 /*!
902 \since 4.2
903
904 Sets \a matrix as an explicit transformation matrix on the
905 current brush. The brush transformation matrix is merged with
906 QPainter transformation matrix to produce the final result.
907
908 \sa matrix()
909 */
setMatrix(const QMatrix & matrix)910 void QBrush::setMatrix(const QMatrix &matrix)
911 {
912 setTransform(QTransform(matrix));
913 }
914
915 /*!
916 \since 4.3
917
918 Sets \a matrix as an explicit transformation matrix on the
919 current brush. The brush transformation matrix is merged with
920 QPainter transformation matrix to produce the final result.
921
922 \sa transform()
923 */
setTransform(const QTransform & matrix)924 void QBrush::setTransform(const QTransform &matrix)
925 {
926 detach(d->style);
927 d->transform = matrix;
928 }
929
930
931 /*!
932 \fn void QBrush::matrix() const
933 \since 4.2
934
935 Returns the current transformation matrix for the brush.
936
937 \sa setMatrix()
938 */
939
940 /*!
941 \fn bool QBrush::operator!=(const QBrush &brush) const
942
943 Returns true if the brush is different from the given \a brush;
944 otherwise returns false.
945
946 Two brushes are different if they have different styles, colors or
947 transforms or different pixmaps or gradients depending on the style.
948
949 \sa operator==()
950 */
951
952 /*!
953 \fn bool QBrush::operator==(const QBrush &brush) const
954
955 Returns true if the brush is equal to the given \a brush;
956 otherwise returns false.
957
958 Two brushes are equal if they have equal styles, colors and
959 transforms and equal pixmaps or gradients depending on the style.
960
961 \sa operator!=()
962 */
963
operator ==(const QBrush & b) const964 bool QBrush::operator==(const QBrush &b) const
965 {
966 if (b.d == d)
967 return true;
968 if (b.d->style != d->style || b.d->color != d->color || b.d->transform != d->transform)
969 return false;
970 switch (d->style) {
971 case Qt::TexturePattern:
972 {
973 const QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
974 const QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
975 return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
976 }
977 case Qt::LinearGradientPattern:
978 case Qt::RadialGradientPattern:
979 case Qt::ConicalGradientPattern:
980 {
981 const QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
982 const QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
983 return d1->gradient == d2->gradient;
984 }
985 default:
986 return true;
987 }
988 }
989
990 /*!
991 \fn QBrush::operator const QColor&() const
992
993 Returns the brush's color.
994
995 Use color() instead.
996 */
997
998 #ifndef QT_NO_DEBUG_STREAM
999 /*!
1000 \internal
1001 */
operator <<(QDebug dbg,const QBrush & b)1002 QDebug operator<<(QDebug dbg, const QBrush &b)
1003 {
1004 #ifndef Q_BROKEN_DEBUG_STREAM
1005 static const char *BRUSH_STYLES[] = {
1006 "NoBrush",
1007 "SolidPattern",
1008 "Dense1Pattern",
1009 "Dense2Pattern",
1010 "Dense3Pattern",
1011 "Dense4Pattern",
1012 "Dense5Pattern",
1013 "Dense6Pattern",
1014 "Dense7Pattern",
1015 "HorPattern",
1016 "VerPattern",
1017 "CrossPattern",
1018 "BDiagPattern",
1019 "FDiagPattern",
1020 "DiagCrossPattern",
1021 "LinearGradientPattern",
1022 "RadialGradientPattern",
1023 "ConicalGradientPattern",
1024 0, 0, 0, 0, 0, 0,
1025 "TexturePattern" // 24
1026 };
1027
1028 dbg.nospace() << "QBrush(" << b.color() << ',' << BRUSH_STYLES[b.style()] << ')';
1029 return dbg.space();
1030 #else
1031 qWarning("This compiler doesn't support streaming QBrush to QDebug");
1032 return dbg;
1033 Q_UNUSED(b);
1034 #endif
1035 }
1036 #endif
1037
1038 /*****************************************************************************
1039 QBrush stream functions
1040 *****************************************************************************/
1041 #ifndef QT_NO_DATASTREAM
1042 /*!
1043 \fn QDataStream &operator<<(QDataStream &stream, const QBrush &brush)
1044 \relates QBrush
1045
1046 Writes the given \a brush to the given \a stream and returns a
1047 reference to the \a stream.
1048
1049 \sa {Serializing Qt Data Types}
1050 */
1051
operator <<(QDataStream & s,const QBrush & b)1052 QDataStream &operator<<(QDataStream &s, const QBrush &b)
1053 {
1054 quint8 style = (quint8) b.style();
1055 bool gradient_style = false;
1056
1057 if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern
1058 || style == Qt::ConicalGradientPattern)
1059 gradient_style = true;
1060
1061 if (s.version() < QDataStream::Qt_4_0 && gradient_style)
1062 style = Qt::NoBrush;
1063
1064 s << style << b.color();
1065 if (b.style() == Qt::TexturePattern) {
1066 s << b.texture();
1067 } else if (s.version() >= QDataStream::Qt_4_0 && gradient_style) {
1068 const QGradient *gradient = b.gradient();
1069 int type_as_int = int(gradient->type());
1070 s << type_as_int;
1071 if (s.version() >= QDataStream::Qt_4_3) {
1072 s << int(gradient->spread());
1073 s << int(gradient->coordinateMode());
1074 }
1075
1076 if (s.version() >= QDataStream::Qt_4_5)
1077 s << int(gradient->interpolationMode());
1078
1079 if (sizeof(qreal) == sizeof(double)) {
1080 s << gradient->stops();
1081 } else {
1082 // ensure that we write doubles here instead of streaming the stops
1083 // directly; otherwise, platforms that redefine qreal might generate
1084 // data that cannot be read on other platforms.
1085 QVector<QGradientStop> stops = gradient->stops();
1086 s << quint32(stops.size());
1087 for (int i = 0; i < stops.size(); ++i) {
1088 const QGradientStop &stop = stops.at(i);
1089 s << QPair<double, QColor>(double(stop.first), stop.second);
1090 }
1091 }
1092
1093 if (gradient->type() == QGradient::LinearGradient) {
1094 s << static_cast<const QLinearGradient *>(gradient)->start();
1095 s << static_cast<const QLinearGradient *>(gradient)->finalStop();
1096 } else if (gradient->type() == QGradient::RadialGradient) {
1097 s << static_cast<const QRadialGradient *>(gradient)->center();
1098 s << static_cast<const QRadialGradient *>(gradient)->focalPoint();
1099 s << (double) static_cast<const QRadialGradient *>(gradient)->radius();
1100 } else { // type == Conical
1101 s << static_cast<const QConicalGradient *>(gradient)->center();
1102 s << (double) static_cast<const QConicalGradient *>(gradient)->angle();
1103 }
1104 }
1105 if (s.version() >= QDataStream::Qt_4_3)
1106 s << b.transform();
1107 return s;
1108 }
1109
1110 /*!
1111 \fn QDataStream &operator>>(QDataStream &stream, QBrush &brush)
1112 \relates QBrush
1113
1114 Reads the given \a brush from the given \a stream and returns a
1115 reference to the \a stream.
1116
1117 \sa {Serializing Qt Data Types}
1118 */
1119
operator >>(QDataStream & s,QBrush & b)1120 QDataStream &operator>>(QDataStream &s, QBrush &b)
1121 {
1122 quint8 style;
1123 QColor color;
1124 s >> style;
1125 s >> color;
1126 if (style == Qt::TexturePattern) {
1127 QPixmap pm;
1128 s >> pm;
1129 b = QBrush(color, pm);
1130 } else if (style == Qt::LinearGradientPattern
1131 || style == Qt::RadialGradientPattern
1132 || style == Qt::ConicalGradientPattern) {
1133
1134 int type_as_int;
1135 QGradient::Type type;
1136 QGradientStops stops;
1137 QGradient::CoordinateMode cmode = QGradient::LogicalMode;
1138 QGradient::Spread spread = QGradient::PadSpread;
1139 QGradient::InterpolationMode imode = QGradient::ColorInterpolation;
1140
1141 s >> type_as_int;
1142 type = QGradient::Type(type_as_int);
1143 if (s.version() >= QDataStream::Qt_4_3) {
1144 s >> type_as_int;
1145 spread = QGradient::Spread(type_as_int);
1146 s >> type_as_int;
1147 cmode = QGradient::CoordinateMode(type_as_int);
1148 }
1149
1150 if (s.version() >= QDataStream::Qt_4_5) {
1151 s >> type_as_int;
1152 imode = QGradient::InterpolationMode(type_as_int);
1153 }
1154
1155 if (sizeof(qreal) == sizeof(double)) {
1156 s >> stops;
1157 } else {
1158 quint32 numStops;
1159 double n;
1160 QColor c;
1161
1162 s >> numStops;
1163 for (quint32 i = 0; i < numStops; ++i) {
1164 s >> n >> c;
1165 stops << QPair<qreal, QColor>(n, c);
1166 }
1167 }
1168
1169 if (type == QGradient::LinearGradient) {
1170 QPointF p1, p2;
1171 s >> p1;
1172 s >> p2;
1173 QLinearGradient lg(p1, p2);
1174 lg.setStops(stops);
1175 lg.setSpread(spread);
1176 lg.setCoordinateMode(cmode);
1177 lg.setInterpolationMode(imode);
1178 b = QBrush(lg);
1179 } else if (type == QGradient::RadialGradient) {
1180 QPointF center, focal;
1181 double radius;
1182 s >> center;
1183 s >> focal;
1184 s >> radius;
1185 QRadialGradient rg(center, radius, focal);
1186 rg.setStops(stops);
1187 rg.setSpread(spread);
1188 rg.setCoordinateMode(cmode);
1189 rg.setInterpolationMode(imode);
1190 b = QBrush(rg);
1191 } else { // type == QGradient::ConicalGradient
1192 QPointF center;
1193 double angle;
1194 s >> center;
1195 s >> angle;
1196 QConicalGradient cg(center, angle);
1197 cg.setStops(stops);
1198 cg.setSpread(spread);
1199 cg.setCoordinateMode(cmode);
1200 cg.setInterpolationMode(imode);
1201 b = QBrush(cg);
1202 }
1203 } else {
1204 b = QBrush(color, (Qt::BrushStyle)style);
1205 }
1206 if (s.version() >= QDataStream::Qt_4_3) {
1207 QTransform transform;
1208 s >> transform;
1209 b.setTransform(transform);
1210 }
1211 return s;
1212 }
1213 #endif // QT_NO_DATASTREAM
1214
1215 /*******************************************************************************
1216 * QGradient implementations
1217 */
1218
1219
1220 /*!
1221 \class QGradient
1222 \ingroup painting
1223 \ingroup shared
1224
1225 \brief The QGradient class is used in combination with QBrush to
1226 specify gradient fills.
1227
1228 Qt currently supports three types of gradient fills:
1229
1230 \list
1231 \o \e Linear gradients interpolate colors between start and end points.
1232 \o \e Simple radial gradients interpolate colors between a focal point
1233 and end points on a circle surrounding it.
1234 \o \e Extended radial gradients interpolate colors between a center and
1235 a focal circle.
1236 \o \e Conical gradients interpolate colors around a center point.
1237 \endlist
1238
1239 A gradient's type can be retrieved using the type() function.
1240 Each of the types is represented by a subclass of QGradient:
1241
1242 \table
1243 \header
1244 \o QLinearGradient
1245 \o QRadialGradient
1246 \o QConicalGradient
1247 \row
1248 \o \inlineimage qgradient-linear.png
1249 \o \inlineimage qgradient-radial.png
1250 \o \inlineimage qgradient-conical.png
1251 \endtable
1252
1253 The colors in a gradient are defined using stop points of the
1254 QGradientStop type; i.e., a position and a color. Use the setColorAt()
1255 function to define a single stop point. Alternatively, use the
1256 setStops() function to define several stop points in one go. Note that
1257 the latter function \e replaces the current set of stop points.
1258
1259 It is the gradient's complete set of stop points (accessible
1260 through the stops() function) that describes how the gradient area
1261 should be filled. If no stop points have been specified, a gradient
1262 of black at 0 to white at 1 is used.
1263
1264 A diagonal linear gradient from black at (100, 100) to white at
1265 (200, 200) could be specified like this:
1266
1267 \snippet doc/src/snippets/brush/brush.cpp 0
1268
1269 A gradient can have an arbitrary number of stop points. The
1270 following would create a radial gradient starting with
1271 red in the center, blue and then green on the edges:
1272
1273 \snippet doc/src/snippets/brush/brush.cpp 1
1274
1275 It is possible to repeat or reflect the gradient outside its area
1276 by specifiying the \l {QGradient::Spread}{spread method} using the
1277 setSpread() function. The default is to pad the outside area with
1278 the color at the closest stop point. The currently set \l
1279 {QGradient::Spread}{spread method} can be retrieved using the
1280 spread() function. The QGradient::Spread enum defines three
1281 different methods:
1282
1283 \table
1284 \row
1285 \o \inlineimage qradialgradient-pad.png
1286 \o \inlineimage qradialgradient-repeat.png
1287 \o \inlineimage qradialgradient-reflect.png
1288 \row
1289 \o \l {QGradient::PadSpread}{PadSpread}
1290 \o \l {QGradient::RepeatSpread}{RepeatSpread}
1291 \o \l {QGradient::ReflectSpread}{ReflectSpread}
1292 \endtable
1293
1294 Note that the setSpread() function only has effect for linear and
1295 radial gradients. The reason is that the conical gradient is
1296 closed by definition, i.e. the \e conical gradient fills the
1297 entire circle from 0 - 360 degrees, while the boundary of a radial
1298 or a linear gradient can be specified through its radius or final
1299 stop points, respectively.
1300
1301 The gradient coordinates can be specified in logical coordinates,
1302 relative to device coordinates, or relative to object bounding box coordinates.
1303 The \l {QGradient::CoordinateMode}{coordinate mode} can be set using the
1304 setCoordinateMode() function. The default is LogicalMode, where the
1305 gradient coordinates are specified in the same way as the object
1306 coordinates. To retrieve the currently set \l {QGradient::CoordinateMode}
1307 {coordinate mode} use coordinateMode().
1308
1309
1310 \sa {demos/gradients}{The Gradients Demo}, QBrush
1311 */
1312
1313 /*!
1314 \internal
1315 */
QGradient()1316 QGradient::QGradient()
1317 : m_type(NoGradient), dummy(0)
1318 {
1319 }
1320
1321
1322 /*!
1323 \enum QGradient::Type
1324
1325 Specifies the type of gradient.
1326
1327 \value LinearGradient Interpolates colors between start and end points
1328 (QLinearGradient).
1329
1330 \value RadialGradient Interpolate colors between a focal point and end
1331 points on a circle surrounding it (QRadialGradient).
1332
1333 \value ConicalGradient Interpolate colors around a center point (QConicalGradient).
1334 \value NoGradient No gradient is used.
1335
1336 \sa type()
1337 */
1338
1339 /*!
1340 \enum QGradient::Spread
1341
1342 Specifies how the area outside the gradient area should be
1343 filled.
1344
1345 \value PadSpread The area is filled with the closest stop
1346 color. This is the default.
1347
1348 \value RepeatSpread The gradient is repeated outside the gradient
1349 area.
1350
1351 \value ReflectSpread The gradient is reflected outside the
1352 gradient area.
1353
1354 \sa spread(), setSpread()
1355 */
1356
1357 /*!
1358 \fn void QGradient::setSpread(Spread method)
1359
1360 Specifies the spread \a method that should be used for this
1361 gradient.
1362
1363 Note that this function only has effect for linear and radial
1364 gradients.
1365
1366 \sa spread()
1367 */
1368
1369 /*!
1370 \fn QGradient::Spread QGradient::spread() const
1371
1372 Returns the spread method use by this gradient. The default is
1373 PadSpread.
1374
1375 \sa setSpread()
1376 */
1377
1378 /*!
1379 \fn QGradient::Type QGradient::type() const
1380
1381 Returns the type of gradient.
1382 */
1383
1384 /*!
1385 \fn void QGradient::setColorAt(qreal position, const QColor &color)
1386
1387 Creates a stop point at the given \a position with the given \a
1388 color. The given \a position must be in the range 0 to 1.
1389
1390 \sa setStops(), stops()
1391 */
1392
setColorAt(qreal pos,const QColor & color)1393 void QGradient::setColorAt(qreal pos, const QColor &color)
1394 {
1395 if ((pos > 1 || pos < 0) && !qIsNaN(pos)) {
1396 qWarning("QGradient::setColorAt: Color position must be specified in the range 0 to 1");
1397 return;
1398 }
1399
1400 int index = 0;
1401 if (!qIsNaN(pos))
1402 while (index < m_stops.size() && m_stops.at(index).first < pos) ++index;
1403
1404 if (index < m_stops.size() && m_stops.at(index).first == pos)
1405 m_stops[index].second = color;
1406 else
1407 m_stops.insert(index, QGradientStop(pos, color));
1408 }
1409
1410 /*!
1411 \fn void QGradient::setStops(const QGradientStops &stopPoints)
1412
1413 Replaces the current set of stop points with the given \a
1414 stopPoints. The positions of the points must be in the range 0 to
1415 1, and must be sorted with the lowest point first.
1416
1417 \sa setColorAt(), stops()
1418 */
setStops(const QGradientStops & stops)1419 void QGradient::setStops(const QGradientStops &stops)
1420 {
1421 m_stops.clear();
1422 for (int i=0; i<stops.size(); ++i)
1423 setColorAt(stops.at(i).first, stops.at(i).second);
1424 }
1425
1426
1427 /*!
1428 Returns the stop points for this gradient.
1429
1430 If no stop points have been specified, a gradient of black at 0 to white
1431 at 1 is used.
1432
1433 \sa setStops(), setColorAt()
1434 */
stops() const1435 QGradientStops QGradient::stops() const
1436 {
1437 if (m_stops.isEmpty()) {
1438 QGradientStops tmp;
1439 tmp << QGradientStop(0, Qt::black) << QGradientStop(1, Qt::white);
1440 return tmp;
1441 }
1442 return m_stops;
1443 }
1444
1445 #define Q_DUMMY_ACCESSOR union {void *p; uint i;}; p = dummy;
1446
1447 /*!
1448 \enum QGradient::CoordinateMode
1449 \since 4.4
1450
1451 This enum specifies how gradient coordinates map to the paint
1452 device on which the gradient is used.
1453
1454 \value LogicalMode This is the default mode. The gradient coordinates
1455 are specified logical space just like the object coordinates.
1456 \value StretchToDeviceMode In this mode the gradient coordinates
1457 are relative to the bounding rectangle of the paint device,
1458 with (0,0) in the top left corner, and (1,1) in the bottom right
1459 corner of the paint device.
1460 \value ObjectBoundingMode In this mode the gradient coordinates are
1461 relative to the bounding rectangle of the object being drawn, with
1462 (0,0) in the top left corner, and (1,1) in the bottom right corner
1463 of the object's bounding rectangle.
1464 */
1465
1466 /*!
1467 \since 4.4
1468
1469 Returns the coordinate mode of this gradient. The default mode is
1470 LogicalMode.
1471 */
coordinateMode() const1472 QGradient::CoordinateMode QGradient::coordinateMode() const
1473 {
1474 Q_DUMMY_ACCESSOR
1475 return CoordinateMode(i & 0x03);
1476 }
1477
1478 /*!
1479 \since 4.4
1480
1481 Sets the coordinate mode of this gradient to \a mode. The default
1482 mode is LogicalMode.
1483 */
setCoordinateMode(CoordinateMode mode)1484 void QGradient::setCoordinateMode(CoordinateMode mode)
1485 {
1486 Q_DUMMY_ACCESSOR
1487 i &= ~0x03;
1488 i |= uint(mode);
1489 dummy = p;
1490 }
1491
1492 /*!
1493 \enum QGradient::InterpolationMode
1494 \since 4.5
1495 \internal
1496
1497 \value ComponentInterpolation The color components and the alpha component are
1498 independently linearly interpolated.
1499 \value ColorInterpolation The colors are linearly interpolated in
1500 premultiplied color space.
1501 */
1502
1503 /*!
1504 \since 4.5
1505 \internal
1506
1507 Returns the interpolation mode of this gradient. The default mode is
1508 ColorInterpolation.
1509 */
interpolationMode() const1510 QGradient::InterpolationMode QGradient::interpolationMode() const
1511 {
1512 Q_DUMMY_ACCESSOR
1513 return InterpolationMode((i >> 2) & 0x01);
1514 }
1515
1516 /*!
1517 \since 4.5
1518 \internal
1519
1520 Sets the interpolation mode of this gradient to \a mode. The default
1521 mode is ColorInterpolation.
1522 */
setInterpolationMode(InterpolationMode mode)1523 void QGradient::setInterpolationMode(InterpolationMode mode)
1524 {
1525 Q_DUMMY_ACCESSOR
1526 i &= ~(1 << 2);
1527 i |= (uint(mode) << 2);
1528 dummy = p;
1529 }
1530
1531 /*!
1532 \fn bool QGradient::operator!=(const QGradient &gradient) const
1533 \since 4.2
1534
1535 Returns true if the gradient is the same as the other \a gradient
1536 specified; otherwise returns false.
1537
1538 \sa operator==()
1539 */
1540
1541 /*!
1542 Returns true if the gradient is the same as the other \a gradient
1543 specified; otherwise returns false.
1544
1545 \sa operator!=()
1546 */
operator ==(const QGradient & gradient) const1547 bool QGradient::operator==(const QGradient &gradient) const
1548 {
1549 if (gradient.m_type != m_type
1550 || gradient.m_spread != m_spread
1551 || gradient.dummy != dummy) return false;
1552
1553 if (m_type == LinearGradient) {
1554 if (m_data.linear.x1 != gradient.m_data.linear.x1
1555 || m_data.linear.y1 != gradient.m_data.linear.y1
1556 || m_data.linear.x2 != gradient.m_data.linear.x2
1557 || m_data.linear.y2 != gradient.m_data.linear.y2)
1558 return false;
1559 } else if (m_type == RadialGradient) {
1560 if (m_data.radial.cx != gradient.m_data.radial.cx
1561 || m_data.radial.cy != gradient.m_data.radial.cy
1562 || m_data.radial.fx != gradient.m_data.radial.fx
1563 || m_data.radial.fy != gradient.m_data.radial.fy
1564 || m_data.radial.cradius != gradient.m_data.radial.cradius)
1565 return false;
1566 } else { // m_type == ConicalGradient
1567 if (m_data.conical.cx != gradient.m_data.conical.cx
1568 || m_data.conical.cy != gradient.m_data.conical.cy
1569 || m_data.conical.angle != gradient.m_data.conical.angle)
1570 return false;
1571 }
1572
1573 return stops() == gradient.stops();
1574 }
1575
1576 /*!
1577 \internal
1578 */
operator ==(const QGradient & gradient)1579 bool QGradient::operator==(const QGradient &gradient)
1580 {
1581 return const_cast<const QGradient *>(this)->operator==(gradient);
1582 }
1583
1584 /*!
1585 \class QLinearGradient
1586 \ingroup painting
1587
1588 \brief The QLinearGradient class is used in combination with QBrush to
1589 specify a linear gradient brush.
1590
1591 Linear gradients interpolate colors between start and end
1592 points. Outside these points the gradient is either padded,
1593 reflected or repeated depending on the currently set \l
1594 {QGradient::Spread}{spread} method:
1595
1596 \table
1597 \row
1598 \o \inlineimage qlineargradient-pad.png
1599 \o \inlineimage qlineargradient-reflect.png
1600 \o \inlineimage qlineargradient-repeat.png
1601 \row
1602 \o \l {QGradient::PadSpread}{PadSpread} (default)
1603 \o \l {QGradient::ReflectSpread}{ReflectSpread}
1604 \o \l {QGradient::RepeatSpread}{RepeatSpread}
1605 \endtable
1606
1607 The colors in a gradient is defined using stop points of the
1608 QGradientStop type, i.e. a position and a color. Use the
1609 QGradient::setColorAt() or the QGradient::setStops() function to
1610 define the stop points. It is the gradient's complete set of stop
1611 points that describes how the gradient area should be filled. If
1612 no stop points have been specified, a gradient of black at 0 to
1613 white at 1 is used.
1614
1615 In addition to the functions inherited from QGradient, the
1616 QLinearGradient class provides the finalStop() function which
1617 returns the final stop point of the gradient, and the start()
1618 function returning the start point of the gradient.
1619
1620 \sa QRadialGradient, QConicalGradient, {demos/gradients}{The
1621 Gradients Demo}
1622 */
1623
1624
1625 /*!
1626 Constructs a default linear gradient with interpolation area
1627 between (0, 0) and (1, 1).
1628
1629 \sa QGradient::setColorAt(), setStart(), setFinalStop()
1630 */
1631
QLinearGradient()1632 QLinearGradient::QLinearGradient()
1633 {
1634 m_type = LinearGradient;
1635 m_spread = PadSpread;
1636 m_data.linear.x1 = 0;
1637 m_data.linear.y1 = 0;
1638 m_data.linear.x2 = 1;
1639 m_data.linear.y2 = 1;
1640 }
1641
1642
1643 /*!
1644 Constructs a linear gradient with interpolation area between the
1645 given \a start point and \a finalStop.
1646
1647 \note The expected parameter values are in pixels.
1648
1649 \sa QGradient::setColorAt(), QGradient::setStops()
1650 */
QLinearGradient(const QPointF & start,const QPointF & finalStop)1651 QLinearGradient::QLinearGradient(const QPointF &start, const QPointF &finalStop)
1652 {
1653 m_type = LinearGradient;
1654 m_spread = PadSpread;
1655 m_data.linear.x1 = start.x();
1656 m_data.linear.y1 = start.y();
1657 m_data.linear.x2 = finalStop.x();
1658 m_data.linear.y2 = finalStop.y();
1659 }
1660
1661 /*!
1662 \fn QLinearGradient::QLinearGradient(qreal x1, qreal y1, qreal x2, qreal y2)
1663
1664 Constructs a linear gradient with interpolation area between (\a
1665 x1, \a y1) and (\a x2, \a y2).
1666
1667 \note The expected parameter values are in pixels.
1668
1669 \sa QGradient::setColorAt(), QGradient::setStops()
1670 */
QLinearGradient(qreal xStart,qreal yStart,qreal xFinalStop,qreal yFinalStop)1671 QLinearGradient::QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, qreal yFinalStop)
1672 {
1673 m_type = LinearGradient;
1674 m_spread = PadSpread;
1675 m_data.linear.x1 = xStart;
1676 m_data.linear.y1 = yStart;
1677 m_data.linear.x2 = xFinalStop;
1678 m_data.linear.y2 = yFinalStop;
1679 }
1680
1681
1682 /*!
1683 Returns the start point of this linear gradient in logical coordinates.
1684
1685 \sa QGradient::stops()
1686 */
1687
start() const1688 QPointF QLinearGradient::start() const
1689 {
1690 Q_ASSERT(m_type == LinearGradient);
1691 return QPointF(m_data.linear.x1, m_data.linear.y1);
1692 }
1693
1694 /*!
1695 \fn void QLinearGradient::setStart(qreal x, qreal y)
1696 \overload
1697 \since 4.2
1698
1699 Sets the start point of this linear gradient in logical
1700 coordinates to \a x, \a y.
1701
1702 \sa start()
1703 */
1704
1705 /*!
1706 \since 4.2
1707
1708 Sets the start point of this linear gradient in logical
1709 coordinates to \a start.
1710
1711 \sa start()
1712 */
1713
setStart(const QPointF & start)1714 void QLinearGradient::setStart(const QPointF &start)
1715 {
1716 Q_ASSERT(m_type == LinearGradient);
1717 m_data.linear.x1 = start.x();
1718 m_data.linear.y1 = start.y();
1719 }
1720
1721
1722 /*!
1723 \fn void QLinearGradient::setFinalStop(qreal x, qreal y)
1724 \overload
1725 \since 4.2
1726
1727 Sets the final stop point of this linear gradient in logical
1728 coordinates to \a x, \a y.
1729
1730 \sa start()
1731 */
1732
1733 /*!
1734 Returns the final stop point of this linear gradient in logical coordinates.
1735
1736 \sa QGradient::stops()
1737 */
1738
finalStop() const1739 QPointF QLinearGradient::finalStop() const
1740 {
1741 Q_ASSERT(m_type == LinearGradient);
1742 return QPointF(m_data.linear.x2, m_data.linear.y2);
1743 }
1744
1745
1746 /*!
1747 \since 4.2
1748
1749 Sets the final stop point of this linear gradient in logical
1750 coordinates to \a stop.
1751
1752 \sa finalStop()
1753 */
1754
setFinalStop(const QPointF & stop)1755 void QLinearGradient::setFinalStop(const QPointF &stop)
1756 {
1757 Q_ASSERT(m_type == LinearGradient);
1758 m_data.linear.x2 = stop.x();
1759 m_data.linear.y2 = stop.y();
1760 }
1761
1762
1763 /*!
1764 \class QRadialGradient
1765 \ingroup painting
1766
1767 \brief The QRadialGradient class is used in combination with QBrush to
1768 specify a radial gradient brush.
1769
1770 Qt supports both simple and extended radial gradients.
1771
1772 Simple radial gradients interpolate colors between a focal point and end
1773 points on a circle surrounding it. Extended radial gradients interpolate
1774 colors between a focal circle and a center circle. Points outside the cone
1775 defined by the two circles will be transparent. For simple radial gradients
1776 the focal point is adjusted to lie inside the center circle, whereas the
1777 focal point can have any position in an extended radial gradient.
1778
1779 Outside the end points the gradient is either padded, reflected or repeated
1780 depending on the currently set \l {QGradient::Spread}{spread} method:
1781
1782 \table
1783 \row
1784 \o \inlineimage qradialgradient-pad.png
1785 \o \inlineimage qradialgradient-reflect.png
1786 \o \inlineimage qradialgradient-repeat.png
1787 \row
1788 \o \l {QGradient::PadSpread}{PadSpread} (default)
1789 \o \l {QGradient::ReflectSpread}{ReflectSpread}
1790 \o \l {QGradient::RepeatSpread}{RepeatSpread}
1791 \endtable
1792
1793 The colors in a gradient is defined using stop points of the
1794 QGradientStop type, i.e. a position and a color. Use the
1795 QGradient::setColorAt() or the QGradient::setStops() function to
1796 define the stop points. It is the gradient's complete set of stop
1797 points that describes how the gradient area should be filled. If
1798 no stop points have been specified, a gradient of black at 0 to
1799 white at 1 is used.
1800
1801 In addition to the functions inherited from QGradient, the
1802 QRadialGradient class provides the center(), focalPoint() and
1803 radius() functions returning the gradient's center, focal point
1804 and radius respectively.
1805
1806 \sa QLinearGradient, QConicalGradient, {demos/gradients}{The
1807 Gradients Demo}
1808 */
1809
qt_radial_gradient_adapt_focal_point(const QPointF & center,qreal radius,const QPointF & focalPoint)1810 static QPointF qt_radial_gradient_adapt_focal_point(const QPointF ¢er,
1811 qreal radius,
1812 const QPointF &focalPoint)
1813 {
1814 // We have a one pixel buffer zone to avoid numerical instability on the
1815 // circle border
1816 //### this is hacky because technically we should adjust based on current matrix
1817 const qreal compensated_radius = radius - radius * qreal(0.001);
1818 QLineF line(center, focalPoint);
1819 if (line.length() > (compensated_radius))
1820 line.setLength(compensated_radius);
1821 return line.p2();
1822 }
1823
1824 /*!
1825 Constructs a simple radial gradient with the given \a center, \a
1826 radius and \a focalPoint.
1827
1828 \note If the given focal point is outside the circle defined by the
1829 \a center point and \a radius, it will be re-adjusted to lie at a point on
1830 the circle where it intersects with the line from \a center to
1831 \a focalPoint.
1832
1833 \sa QGradient::setColorAt(), QGradient::setStops()
1834 */
1835
QRadialGradient(const QPointF & center,qreal radius,const QPointF & focalPoint)1836 QRadialGradient::QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint)
1837 {
1838 m_type = RadialGradient;
1839 m_spread = PadSpread;
1840 m_data.radial.cx = center.x();
1841 m_data.radial.cy = center.y();
1842 m_data.radial.cradius = radius;
1843
1844 QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(center, radius, focalPoint);
1845 m_data.radial.fx = adapted_focal.x();
1846 m_data.radial.fy = adapted_focal.y();
1847 }
1848
1849 /*!
1850 Constructs a simple radial gradient with the given \a center, \a
1851 radius and the focal point in the circle center.
1852
1853 \sa QGradient::setColorAt(), QGradient::setStops()
1854 */
QRadialGradient(const QPointF & center,qreal radius)1855 QRadialGradient::QRadialGradient(const QPointF ¢er, qreal radius)
1856 {
1857 m_type = RadialGradient;
1858 m_spread = PadSpread;
1859 m_data.radial.cx = center.x();
1860 m_data.radial.cy = center.y();
1861 m_data.radial.cradius = radius;
1862 m_data.radial.fx = center.x();
1863 m_data.radial.fy = center.y();
1864 }
1865
1866
1867 /*!
1868 Constructs a simple radial gradient with the given center (\a cx, \a cy),
1869 \a radius and focal point (\a fx, \a fy).
1870
1871 \note If the given focal point is outside the circle defined by the
1872 center (\a cx, \a cy) and the \a radius it will be re-adjusted to
1873 the intersection between the line from the center to the focal point
1874 and the circle.
1875
1876 \sa QGradient::setColorAt(), QGradient::setStops()
1877 */
1878
QRadialGradient(qreal cx,qreal cy,qreal radius,qreal fx,qreal fy)1879 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qreal fy)
1880 {
1881 m_type = RadialGradient;
1882 m_spread = PadSpread;
1883 m_data.radial.cx = cx;
1884 m_data.radial.cy = cy;
1885 m_data.radial.cradius = radius;
1886
1887 QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(QPointF(cx, cy),
1888 radius,
1889 QPointF(fx, fy));
1890
1891 m_data.radial.fx = adapted_focal.x();
1892 m_data.radial.fy = adapted_focal.y();
1893 }
1894
1895 /*!
1896 Constructs a simple radial gradient with the center at (\a cx, \a cy) and the
1897 specified \a radius. The focal point lies at the center of the circle.
1898
1899 \sa QGradient::setColorAt(), QGradient::setStops()
1900 */
QRadialGradient(qreal cx,qreal cy,qreal radius)1901 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius)
1902 {
1903 m_type = RadialGradient;
1904 m_spread = PadSpread;
1905 m_data.radial.cx = cx;
1906 m_data.radial.cy = cy;
1907 m_data.radial.cradius = radius;
1908 m_data.radial.fx = cx;
1909 m_data.radial.fy = cy;
1910 }
1911
1912
1913 /*!
1914 Constructs a simple radial gradient with the center and focal point at
1915 (0, 0) with a radius of 1.
1916 */
QRadialGradient()1917 QRadialGradient::QRadialGradient()
1918 {
1919 m_type = RadialGradient;
1920 m_spread = PadSpread;
1921 m_data.radial.cx = 0;
1922 m_data.radial.cy = 0;
1923 m_data.radial.cradius = 1;
1924 m_data.radial.fx = 0;
1925 m_data.radial.fy = 0;
1926 }
1927
1928 /*!
1929 \since 4.8
1930
1931 Constructs an extended radial gradient with the given \a center, \a
1932 centerRadius, \a focalPoint, and \a focalRadius.
1933 */
QRadialGradient(const QPointF & center,qreal centerRadius,const QPointF & focalPoint,qreal focalRadius)1934 QRadialGradient::QRadialGradient(const QPointF ¢er, qreal centerRadius, const QPointF &focalPoint, qreal focalRadius)
1935 {
1936 m_type = RadialGradient;
1937 m_spread = PadSpread;
1938 m_data.radial.cx = center.x();
1939 m_data.radial.cy = center.y();
1940 m_data.radial.cradius = centerRadius;
1941
1942 m_data.radial.fx = focalPoint.x();
1943 m_data.radial.fy = focalPoint.y();
1944 setFocalRadius(focalRadius);
1945 }
1946
1947 /*!
1948 \since 4.8
1949
1950 Constructs an extended radial gradient with the given center
1951 (\a cx, \a cy), center radius, \a centerRadius, focal point, (\a fx, \a fy),
1952 and focal radius \a focalRadius.
1953 */
QRadialGradient(qreal cx,qreal cy,qreal centerRadius,qreal fx,qreal fy,qreal focalRadius)1954 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal centerRadius, qreal fx, qreal fy, qreal focalRadius)
1955 {
1956 m_type = RadialGradient;
1957 m_spread = PadSpread;
1958 m_data.radial.cx = cx;
1959 m_data.radial.cy = cy;
1960 m_data.radial.cradius = centerRadius;
1961
1962 m_data.radial.fx = fx;
1963 m_data.radial.fy = fy;
1964 setFocalRadius(focalRadius);
1965 }
1966
1967 /*!
1968 Returns the center of this radial gradient in logical coordinates.
1969
1970 \sa QGradient::stops()
1971 */
1972
center() const1973 QPointF QRadialGradient::center() const
1974 {
1975 Q_ASSERT(m_type == RadialGradient);
1976 return QPointF(m_data.radial.cx, m_data.radial.cy);
1977 }
1978
1979 /*!
1980 \fn void QRadialGradient::setCenter(qreal x, qreal y)
1981 \overload
1982 \since 4.2
1983
1984 Sets the center of this radial gradient in logical coordinates
1985 to (\a x, \a y).
1986
1987 \sa center()
1988 */
1989
1990 /*!
1991 \since 4.2
1992
1993 Sets the center of this radial gradient in logical coordinates
1994 to \a center.
1995
1996 \sa center()
1997 */
1998
setCenter(const QPointF & center)1999 void QRadialGradient::setCenter(const QPointF ¢er)
2000 {
2001 Q_ASSERT(m_type == RadialGradient);
2002 m_data.radial.cx = center.x();
2003 m_data.radial.cy = center.y();
2004 }
2005
2006
2007 /*!
2008 Returns the radius of this radial gradient in logical coordinates.
2009
2010 Equivalent to centerRadius()
2011
2012 \sa QGradient::stops()
2013 */
2014
radius() const2015 qreal QRadialGradient::radius() const
2016 {
2017 Q_ASSERT(m_type == RadialGradient);
2018 return m_data.radial.cradius;
2019 }
2020
2021
2022 /*!
2023 \since 4.2
2024
2025 Sets the radius of this radial gradient in logical coordinates
2026 to \a radius
2027
2028 Equivalent to setCenterRadius()
2029 */
setRadius(qreal radius)2030 void QRadialGradient::setRadius(qreal radius)
2031 {
2032 Q_ASSERT(m_type == RadialGradient);
2033 m_data.radial.cradius = radius;
2034 }
2035
2036 /*!
2037 \since 4.8
2038
2039 Returns the center radius of this radial gradient in logical
2040 coordinates.
2041
2042 \sa QGradient::stops()
2043 */
centerRadius() const2044 qreal QRadialGradient::centerRadius() const
2045 {
2046 Q_ASSERT(m_type == RadialGradient);
2047 return m_data.radial.cradius;
2048 }
2049
2050 /*!
2051 \since 4.8
2052
2053 Sets the center radius of this radial gradient in logical coordinates
2054 to \a radius
2055 */
setCenterRadius(qreal radius)2056 void QRadialGradient::setCenterRadius(qreal radius)
2057 {
2058 Q_ASSERT(m_type == RadialGradient);
2059 m_data.radial.cradius = radius;
2060 }
2061
2062 /*!
2063 \since 4.8
2064
2065 Returns the focal radius of this radial gradient in logical
2066 coordinates.
2067
2068 \sa QGradient::stops()
2069 */
focalRadius() const2070 qreal QRadialGradient::focalRadius() const
2071 {
2072 Q_ASSERT(m_type == RadialGradient);
2073 Q_DUMMY_ACCESSOR
2074
2075 // mask away low three bits
2076 union { float f; quint32 i; } u;
2077 u.i = i & ~0x07;
2078 return u.f;
2079 }
2080
2081 /*!
2082 \since 4.8
2083
2084 Sets the focal radius of this radial gradient in logical coordinates
2085 to \a radius
2086 */
setFocalRadius(qreal radius)2087 void QRadialGradient::setFocalRadius(qreal radius)
2088 {
2089 Q_ASSERT(m_type == RadialGradient);
2090 Q_DUMMY_ACCESSOR
2091
2092 // Since there's no QGradientData, we only have the dummy void * to
2093 // store additional data in. The three lowest bits are already
2094 // taken, thus we cut the three lowest bits from the significand
2095 // and store the radius as a float.
2096 union { float f; quint32 i; } u;
2097 u.f = float(radius);
2098 // add 0x04 to round up when we drop the three lowest bits
2099 i |= (u.i + 0x04) & ~0x07;
2100 dummy = p;
2101 }
2102
2103 /*!
2104 Returns the focal point of this radial gradient in logical
2105 coordinates.
2106
2107 \sa QGradient::stops()
2108 */
2109
focalPoint() const2110 QPointF QRadialGradient::focalPoint() const
2111 {
2112 Q_ASSERT(m_type == RadialGradient);
2113 return QPointF(m_data.radial.fx, m_data.radial.fy);
2114 }
2115
2116 /*!
2117 \fn void QRadialGradient::setFocalPoint(qreal x, qreal y)
2118 \overload
2119 \since 4.2
2120
2121 Sets the focal point of this radial gradient in logical
2122 coordinates to (\a x, \a y).
2123
2124 \sa focalPoint()
2125 */
2126
2127 /*!
2128 \since 4.2
2129
2130 Sets the focal point of this radial gradient in logical
2131 coordinates to \a focalPoint.
2132
2133 \sa focalPoint()
2134 */
2135
setFocalPoint(const QPointF & focalPoint)2136 void QRadialGradient::setFocalPoint(const QPointF &focalPoint)
2137 {
2138 Q_ASSERT(m_type == RadialGradient);
2139 m_data.radial.fx = focalPoint.x();
2140 m_data.radial.fy = focalPoint.y();
2141 }
2142
2143
2144
2145 /*!
2146 \class QConicalGradient
2147 \ingroup painting
2148
2149 \brief The QConicalGradient class is used in combination with QBrush to
2150 specify a conical gradient brush.
2151
2152 Conical gradients interpolate interpolate colors counter-clockwise
2153 around a center point.
2154
2155 \image qconicalgradient.png
2156
2157 The colors in a gradient is defined using stop points of the
2158 QGradientStop type, i.e. a position and a color. Use the
2159 QGradient::setColorAt() or the QGradient::setStops() function to
2160 define the stop points. It is the gradient's complete set of stop
2161 points that describes how the gradient area should be filled. If
2162 no stop points have been specified, a gradient of black at 0 to
2163 white at 1 is used.
2164
2165 In addition to the functions inherited from QGradient, the
2166 QConicalGradient class provides the angle() and center() functions
2167 returning the start angle and center of the gradient.
2168
2169 Note that the setSpread() function has no effect for conical
2170 gradients. The reason is that the conical gradient is closed by
2171 definition, i.e. the conical gradient fills the entire circle from
2172 0 - 360 degrees, while the boundary of a radial or a linear
2173 gradient can be specified through its radius or final stop points,
2174 respectively.
2175
2176 \sa QLinearGradient, QRadialGradient, {demos/gradients}{The
2177 Gradients Demo}
2178 */
2179
2180
2181 /*!
2182 Constructs a conical gradient with the given \a center, starting
2183 the interpolation at the given \a angle. The \a angle must be
2184 specified in degrees between 0 and 360.
2185
2186 \sa QGradient::setColorAt(), QGradient::setStops()
2187 */
2188
QConicalGradient(const QPointF & center,qreal angle)2189 QConicalGradient::QConicalGradient(const QPointF ¢er, qreal angle)
2190 {
2191 m_type = ConicalGradient;
2192 m_spread = PadSpread;
2193 m_data.conical.cx = center.x();
2194 m_data.conical.cy = center.y();
2195 m_data.conical.angle = angle;
2196 }
2197
2198
2199 /*!
2200 Constructs a conical gradient with the given center (\a cx, \a
2201 cy), starting the interpolation at the given \a angle. The angle
2202 must be specified in degrees between 0 and 360.
2203
2204 \sa QGradient::setColorAt(), QGradient::setStops()
2205 */
2206
QConicalGradient(qreal cx,qreal cy,qreal angle)2207 QConicalGradient::QConicalGradient(qreal cx, qreal cy, qreal angle)
2208 {
2209 m_type = ConicalGradient;
2210 m_spread = PadSpread;
2211 m_data.conical.cx = cx;
2212 m_data.conical.cy = cy;
2213 m_data.conical.angle = angle;
2214 }
2215
2216
2217 /*!
2218 Constructs a conical with center at (0, 0) starting the
2219 interpolation at angle 0.
2220
2221 \sa QGradient::setColorAt(), setCenter(), setAngle()
2222 */
2223
QConicalGradient()2224 QConicalGradient::QConicalGradient()
2225 {
2226 m_type = ConicalGradient;
2227 m_spread = PadSpread;
2228 m_data.conical.cx = 0;
2229 m_data.conical.cy = 0;
2230 m_data.conical.angle = 0;
2231 }
2232
2233
2234 /*!
2235 Returns the center of the conical gradient in logical
2236 coordinates.
2237
2238 \sa stops()
2239 */
2240
center() const2241 QPointF QConicalGradient::center() const
2242 {
2243 Q_ASSERT(m_type == ConicalGradient);
2244 return QPointF(m_data.conical.cx, m_data.conical.cy);
2245 }
2246
2247
2248 /*!
2249 \fn void QConicalGradient::setCenter(qreal x, qreal y)
2250
2251 \overload
2252
2253 Sets the center of this conical gradient in logical coordinates to
2254 (\a x, \a y).
2255
2256 \sa center()
2257 */
2258
2259 /*!
2260 Sets the center of this conical gradient in logical coordinates to
2261 \a center.
2262
2263 \sa center()
2264 */
2265
setCenter(const QPointF & center)2266 void QConicalGradient::setCenter(const QPointF ¢er)
2267 {
2268 Q_ASSERT(m_type == ConicalGradient);
2269 m_data.conical.cx = center.x();
2270 m_data.conical.cy = center.y();
2271 }
2272
2273 /*!
2274 Returns the start angle of the conical gradient in logical
2275 coordinates.
2276
2277 \sa stops()
2278 */
2279
angle() const2280 qreal QConicalGradient::angle() const
2281 {
2282 Q_ASSERT(m_type == ConicalGradient);
2283 return m_data.conical.angle;
2284 }
2285
2286
2287 /*!
2288 \since 4.2
2289
2290 Sets \a angle to be the start angle for this conical gradient in
2291 logical coordinates.
2292
2293 \sa angle()
2294 */
2295
setAngle(qreal angle)2296 void QConicalGradient::setAngle(qreal angle)
2297 {
2298 Q_ASSERT(m_type == ConicalGradient);
2299 m_data.conical.angle = angle;
2300 }
2301
2302 /*!
2303 \typedef QGradientStop
2304 \relates QGradient
2305
2306 Typedef for QPair<\l qreal, QColor>.
2307 */
2308
2309 /*!
2310 \typedef QGradientStops
2311 \relates QGradient
2312
2313 Typedef for QVector<QGradientStop>.
2314 */
2315
2316 /*!
2317 \typedef QBrush::DataPtr
2318 \internal
2319 */
2320
2321 /*!
2322 \fn DataPtr &QBrush::data_ptr()
2323 \internal
2324 */
2325
2326
2327 /*!
2328 \fn bool QBrush::isDetached() const
2329 \internal
2330 */
2331
2332 /*!
2333 \fn QTransform QBrush::transform() const
2334 \since 4.3
2335
2336 Returns the current transformation matrix for the brush.
2337
2338 \sa setTransform()
2339 */
2340
2341 #undef Q_DUMMY_ACCESSOR
2342
2343 QT_END_NAMESPACE
2344