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

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

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

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