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

Last change on this file since 846 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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