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