source: trunk/src/gui/painting/qbrush.cpp@ 284

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

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

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