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

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

trunk: Merged in qt 4.6.2 sources.

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
164QImage qt_imageForBrush(int brushStyle, bool invert)
165{
166 return qt_brushPatternImageCache()->getImage(brushStyle, invert);
167}
168
169struct QTexturedBrushData : public QBrushData
170{
171 QTexturedBrushData() {
172 m_has_pixmap_texture = false;
173 m_pixmap = 0;
174 }
175 ~QTexturedBrushData() {
176 delete m_pixmap;
177 }
178
179 void setPixmap(const QPixmap &pm) {
180 delete m_pixmap;
181
182 if (pm.isNull()) {
183 m_pixmap = 0;
184 m_has_pixmap_texture = false;
185 } else {
186 m_pixmap = new QPixmap(pm);
187 m_has_pixmap_texture = true;
188 }
189
190 m_image = QImage();
191 }
192
193 void setImage(const QImage &image) {
194 m_image = image;
195 delete m_pixmap;
196 m_pixmap = 0;
197 m_has_pixmap_texture = false;
198 }
199
200 QPixmap &pixmap() {
201 if (!m_pixmap) {
202 m_pixmap = new QPixmap(QPixmap::fromImage(m_image));
203 }
204 return *m_pixmap;
205 }
206
207 QImage &image() {
208 if (m_image.isNull() && m_pixmap)
209 m_image = m_pixmap->toImage();
210 return m_image;
211 }
212
213 QPixmap *m_pixmap;
214 QImage m_image;
215 bool m_has_pixmap_texture;
216};
217
218// returns true if the brush has a pixmap (or bitmap) set as the
219// brush texture, false otherwise
220bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
221{
222 if (brush.style() != Qt::TexturePattern)
223 return false;
224 QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data());
225 return tx_data->m_has_pixmap_texture;
226}
227
228struct QGradientBrushData : public QBrushData
229{
230 QGradient gradient;
231};
232
233struct QBrushDataPointerDeleter
234{
235 static inline void deleteData(QBrushData *d)
236 {
237 switch (d->style) {
238 case Qt::TexturePattern:
239 delete static_cast<QTexturedBrushData*>(d);
240 break;
241 case Qt::LinearGradientPattern:
242 case Qt::RadialGradientPattern:
243 case Qt::ConicalGradientPattern:
244 delete static_cast<QGradientBrushData*>(d);
245 break;
246 default:
247 delete d;
248 }
249 }
250
251 static inline void cleanup(QBrushData *d)
252 {
253 if (d && !d->ref.deref()) {
254 deleteData(d);
255 }
256 }
257};
258
259/*!
260 \class QBrush
261 \ingroup painting
262 \ingroup shared
263
264 \brief The QBrush class defines the fill pattern of shapes drawn
265 by QPainter.
266
267 A brush has a style, a color, a gradient and a texture.
268
269 The brush style() defines the fill pattern using the
270 Qt::BrushStyle enum. The default brush style is Qt::NoBrush
271 (depending on how you construct a brush). This style tells the
272 painter to not fill shapes. The standard style for filling is
273 Qt::SolidPattern. The style can be set when the brush is created
274 using the appropriate constructor, and in addition the setStyle()
275 function provides means for altering the style once the brush is
276 constructed.
277
278 \image brush-styles.png Brush Styles
279
280 The brush color() defines the color of the fill pattern. The color
281 can either be one of Qt's predefined colors, Qt::GlobalColor, or
282 any other custom QColor. The currently set color can be retrieved
283 and altered using the color() and setColor() functions,
284 respectively.
285
286 The gradient() defines the gradient fill used when the current
287 style is either Qt::LinearGradientPattern,
288 Qt::RadialGradientPattern or Qt::ConicalGradientPattern. Gradient
289 brushes are created by giving a QGradient as a constructor
290 argument when creating the QBrush. Qt provides three different
291 gradients: QLinearGradient, QConicalGradient, and QRadialGradient
292 - all of which inherit QGradient.
293
294 \snippet doc/src/snippets/brush/gradientcreationsnippet.cpp 0
295
296 The texture() defines the pixmap used when the current style is
297 Qt::TexturePattern. You can create a brush with a texture by
298 providing the pixmap when the brush is created or by using
299 setTexture().
300
301 Note that applying setTexture() makes style() ==
302 Qt::TexturePattern, regardless of previous style
303 settings. Also, calling setColor() will not make a difference if
304 the style is a gradient. The same is the case if the style is
305 Qt::TexturePattern style unless the current texture is a QBitmap.
306
307 The isOpaque() function returns true if the brush is fully opaque
308 otherwise false. A brush is considered opaque if:
309
310 \list
311 \o The alpha component of the color() is 255.
312 \o Its texture() does not have an alpha channel and is not a QBitmap.
313 \o The colors in the gradient() all have an alpha component that is 255.
314 \endlist
315
316 \table 100%
317 \row
318 \o \inlineimage brush-outline.png Outlines
319 \o
320
321 To specify the style and color of lines and outlines, use the
322 QPainter's \l {QPen}{pen} combined with Qt::PenStyle and
323 Qt::GlobalColor:
324
325 \snippet doc/src/snippets/code/src_gui_painting_qbrush.cpp 0
326
327 Note that, by default, QPainter renders the outline (using the
328 currently set pen) when drawing shapes. Use \l {Qt::NoPen}{\c
329 painter.setPen(Qt::NoPen)} to disable this behavior.
330
331 \endtable
332
333 For more information about painting in general, see \l{The Paint
334 System} documentation.
335
336 \sa Qt::BrushStyle, QPainter, QColor
337*/
338
339#ifndef QT_NO_THREAD
340// Special deleter that only deletes if the ref-count goes to zero
341template <>
342class QGlobalStaticDeleter<QBrushData>
343{
344public:
345 QGlobalStatic<QBrushData> &globalStatic;
346 QGlobalStaticDeleter(QGlobalStatic<QBrushData> &_globalStatic)
347 : globalStatic(_globalStatic)
348 { }
349
350 inline ~QGlobalStaticDeleter()
351 {
352 if (!globalStatic.pointer->ref.deref())
353 delete globalStatic.pointer;
354 globalStatic.pointer = 0;
355 globalStatic.destroyed = true;
356 }
357};
358#endif
359
360Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushData, nullBrushInstance,
361 {
362 x->ref = 1;
363 x->style = Qt::BrushStyle(0);
364 x->color = Qt::black;
365 })
366
367static bool qbrush_check_type(Qt::BrushStyle style) {
368 switch (style) {
369 case Qt::TexturePattern:
370 qWarning("QBrush: Incorrect use of TexturePattern");
371 break;
372 case Qt::LinearGradientPattern:
373 case Qt::RadialGradientPattern:
374 case Qt::ConicalGradientPattern:
375 qWarning("QBrush: Wrong use of a gradient pattern");
376 break;
377 default:
378 return true;
379 }
380 return false;
381}
382
383/*!
384 \internal
385 Initializes the brush.
386*/
387
388void QBrush::init(const QColor &color, Qt::BrushStyle style)
389{
390 switch(style) {
391 case Qt::NoBrush:
392 d.reset(nullBrushInstance());
393 d->ref.ref();
394 if (d->color != color) setColor(color);
395 return;
396 case Qt::TexturePattern:
397 d.reset(new QTexturedBrushData);
398 break;
399 case Qt::LinearGradientPattern:
400 case Qt::RadialGradientPattern:
401 case Qt::ConicalGradientPattern:
402 d.reset(new QGradientBrushData);
403 break;
404 default:
405 d.reset(new QBrushData);
406 break;
407 }
408 d->ref = 1;
409 d->style = style;
410 d->color = color;
411}
412
413/*!
414 Constructs a default black brush with the style Qt::NoBrush
415 (i.e. this brush will not fill shapes).
416*/
417
418QBrush::QBrush()
419 : d(nullBrushInstance())
420{
421 Q_ASSERT(d);
422 d->ref.ref();
423}
424
425/*!
426 Constructs a brush with a black color and a texture set to the
427 given \a pixmap. The style is set to Qt::TexturePattern.
428
429 \sa setTexture()
430*/
431
432QBrush::QBrush(const QPixmap &pixmap)
433{
434 init(Qt::black, Qt::TexturePattern);
435 setTexture(pixmap);
436}
437
438
439/*!
440 Constructs a brush with a black color and a texture set to the
441 given \a image. The style is set to Qt::TexturePattern.
442
443 \sa setTextureImage()
444*/
445
446QBrush::QBrush(const QImage &image)
447{
448 init(Qt::black, Qt::TexturePattern);
449 setTextureImage(image);
450}
451
452/*!
453 Constructs a black brush with the given \a style.
454
455 \sa setStyle()
456*/
457
458QBrush::QBrush(Qt::BrushStyle style)
459{
460 if (qbrush_check_type(style))
461 init(Qt::black, style);
462 else {
463 d.reset(nullBrushInstance());
464 d->ref.ref();
465 }
466}
467
468/*!
469 Constructs a brush with the given \a color and \a style.
470
471 \sa setColor(), setStyle()
472*/
473
474QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
475{
476 if (qbrush_check_type(style))
477 init(color, style);
478 else {
479 d.reset(nullBrushInstance());
480 d->ref.ref();
481 }
482}
483
484/*!
485 \fn QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
486
487 Constructs a brush with the given \a color and \a style.
488
489 \sa setColor(), setStyle()
490*/
491QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
492{
493 if (qbrush_check_type(style))
494 init(color, style);
495 else {
496 d.reset(nullBrushInstance());
497 d->ref.ref();
498 }
499}
500
501/*!
502 Constructs a brush with the given \a color and the custom pattern
503 stored in \a pixmap.
504
505 The style is set to Qt::TexturePattern. The color will only have
506 an effect for QBitmaps.
507
508 \sa setColor(), setPixmap()
509*/
510
511QBrush::QBrush(const QColor &color, const QPixmap &pixmap)
512{
513 init(color, Qt::TexturePattern);
514 setTexture(pixmap);
515}
516
517/*!
518
519 Constructs a brush with the given \a color and the custom pattern
520 stored in \a pixmap.
521
522 The style is set to Qt::TexturePattern. The color will only have
523 an effect for QBitmaps.
524
525 \sa setColor(), setPixmap()
526*/
527QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap)
528{
529 init(color, Qt::TexturePattern);
530 setTexture(pixmap);
531}
532
533/*!
534 Constructs a copy of \a other.
535*/
536
537QBrush::QBrush(const QBrush &other)
538 : d(other.d.data())
539{
540 d->ref.ref();
541}
542
543/*!
544 Constructs a brush based on the given \a gradient.
545
546 The brush style is set to the corresponding gradient style (either
547 Qt::LinearGradientPattern, Qt::RadialGradientPattern or
548 Qt::ConicalGradientPattern).
549*/
550QBrush::QBrush(const QGradient &gradient)
551{
552 Q_ASSERT_X(gradient.type() != QGradient::NoGradient, "QBrush::QBrush",
553 "QGradient should not be used directly, use the linear, radial\n"
554 "or conical gradients instead");
555
556 const Qt::BrushStyle enum_table[] = {
557 Qt::LinearGradientPattern,
558 Qt::RadialGradientPattern,
559 Qt::ConicalGradientPattern
560 };
561
562 init(QColor(), enum_table[gradient.type()]);
563 QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data());
564 grad->gradient = gradient;
565}
566
567/*!
568 Destroys the brush.
569*/
570
571QBrush::~QBrush()
572{
573}
574
575void QBrush::cleanUp(QBrushData *x)
576{
577 QBrushDataPointerDeleter::deleteData(x);
578}
579
580
581void QBrush::detach(Qt::BrushStyle newStyle)
582{
583 if (newStyle == d->style && d->ref == 1)
584 return;
585
586 QScopedPointer<QBrushData> x;
587 switch(newStyle) {
588 case Qt::TexturePattern: {
589 QTexturedBrushData *tbd = new QTexturedBrushData;
590 if (d->style == Qt::TexturePattern) {
591 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
592 if (data->m_has_pixmap_texture)
593 tbd->setPixmap(data->pixmap());
594 else
595 tbd->setImage(data->image());
596 }
597 x.reset(tbd);
598 break;
599 }
600 case Qt::LinearGradientPattern:
601 case Qt::RadialGradientPattern:
602 case Qt::ConicalGradientPattern:
603 x.reset(new QGradientBrushData);
604 static_cast<QGradientBrushData *>(x.data())->gradient =
605 static_cast<QGradientBrushData *>(d.data())->gradient;
606 break;
607 default:
608 x.reset(new QBrushData);
609 break;
610 }
611 x->ref = 1;
612 x->style = newStyle;
613 x->color = d->color;
614 x->transform = d->transform;
615 d.reset(x.take());
616}
617
618
619/*!
620 \fn QBrush &QBrush::operator=(const QBrush &brush)
621
622 Assigns the given \a brush to \e this brush and returns a
623 reference to \e this brush.
624*/
625
626QBrush &QBrush::operator=(const QBrush &b)
627{
628 if (d == b.d)
629 return *this;
630
631 b.d->ref.ref();
632 d.reset(b.d.data());
633 return *this;
634}
635
636/*!
637 Returns the brush as a QVariant
638*/
639QBrush::operator QVariant() const
640{
641 return QVariant(QVariant::Brush, this);
642}
643
644/*!
645 \fn Qt::BrushStyle QBrush::style() const
646
647 Returns the brush style.
648
649 \sa setStyle()
650*/
651
652/*!
653 Sets the brush style to \a style.
654
655 \sa style()
656*/
657
658void QBrush::setStyle(Qt::BrushStyle style)
659{
660 if (d->style == style)
661 return;
662
663 if (qbrush_check_type(style)) {
664 detach(style);
665 d->style = style;
666 }
667}
668
669
670/*!
671 \fn const QColor &QBrush::color() const
672
673 Returns the brush color.
674
675 \sa setColor()
676*/
677
678/*!
679 \fn void QBrush::setColor(const QColor &color)
680
681 Sets the brush color to the given \a color.
682
683 Note that calling setColor() will not make a difference if the
684 style is a gradient. The same is the case if the style is
685 Qt::TexturePattern style unless the current texture is a QBitmap.
686
687 \sa color()
688*/
689
690void QBrush::setColor(const QColor &c)
691{
692 detach(d->style);
693 d->color = c;
694}
695
696/*!
697 \fn void QBrush::setColor(Qt::GlobalColor color)
698 \overload
699
700 Sets the brush color to the given \a color.
701*/
702
703
704#ifdef QT3_SUPPORT
705
706/*!
707 \fn void QBrush::setPixmap(const QPixmap &pixmap)
708
709 \compat
710
711 Sets a custom pattern for this brush.
712
713 Use setTexture() instead.
714*/
715
716/*!
717 \fn QPixmap *QBrush::pixmap() const
718
719 Returns a pointer to the custom brush pattern.
720
721 Use texture() instead.
722*/
723QPixmap *QBrush::pixmap() const
724{
725 if (d->style != Qt::TexturePattern)
726 return 0;
727 QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data());
728 QPixmap &pixmap = data->pixmap();
729 return pixmap.isNull() ? 0 : &pixmap;
730}
731#endif
732
733/*!
734 \fn QPixmap QBrush::texture() const
735
736 Returns the custom brush pattern, or a null pixmap if no custom brush pattern
737 has been set.
738
739 \sa setTexture()
740*/
741QPixmap QBrush::texture() const
742{
743 return d->style == Qt::TexturePattern
744 ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap()
745 : QPixmap();
746}
747
748/*!
749 Sets the brush pixmap to \a pixmap. The style is set to
750 Qt::TexturePattern.
751
752 The current brush color will only have an effect for monochrome
753 pixmaps, i.e. for QPixmap::depth() == 1 (\l {QBitmap}{QBitmaps}).
754
755 \sa texture()
756*/
757
758void QBrush::setTexture(const QPixmap &pixmap)
759{
760 if (!pixmap.isNull()) {
761 detach(Qt::TexturePattern);
762 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
763 data->setPixmap(pixmap);
764 } else {
765 detach(Qt::NoBrush);
766 }
767}
768
769
770/*!
771 \since 4.2
772
773 Returns the custom brush pattern, or a null image if no custom
774 brush pattern has been set.
775
776 If the texture was set as a QPixmap it will be converted to a
777 QImage.
778
779 \sa setTextureImage()
780*/
781
782QImage QBrush::textureImage() const
783{
784 return d->style == Qt::TexturePattern
785 ? (static_cast<QTexturedBrushData *>(d.data()))->image()
786 : QImage();
787}
788
789
790/*!
791 \since 4.2
792
793 Sets the brush image to \a image. The style is set to
794 Qt::TexturePattern.
795
796 Note the current brush color will \e not have any affect on
797 monochrome images, as opposed to calling setTexture() with a
798 QBitmap. If you want to change the color of monochrome image
799 brushes, either convert the image to QBitmap with \c
800 QBitmap::fromImage() and set the resulting QBitmap as a texture,
801 or change the entries in the color table for the image.
802
803 \sa textureImage(), setTexture()
804*/
805
806void QBrush::setTextureImage(const QImage &image)
807{
808 if (!image.isNull()) {
809 detach(Qt::TexturePattern);
810 QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
811 data->setImage(image);
812 } else {
813 detach(Qt::NoBrush);
814 }
815}
816
817
818/*!
819 Returns the gradient describing this brush.
820*/
821const QGradient *QBrush::gradient() const
822{
823 if (d->style == Qt::LinearGradientPattern
824 || d->style == Qt::RadialGradientPattern
825 || d->style == Qt::ConicalGradientPattern) {
826 return &static_cast<const QGradientBrushData *>(d.data())->gradient;
827 }
828 return 0;
829}
830
831
832/*!
833 Returns true if the brush is fully opaque otherwise false. A brush
834 is considered opaque if:
835
836 \list
837 \i The alpha component of the color() is 255.
838 \i Its texture() does not have an alpha channel and is not a QBitmap.
839 \i The colors in the gradient() all have an alpha component that is 255.
840 \endlist
841*/
842
843bool QBrush::isOpaque() const
844{
845 bool opaqueColor = d->color.alpha() == 255;
846
847 // Test awfully simple case first
848 if (d->style == Qt::SolidPattern)
849 return opaqueColor;
850
851 if (d->style == Qt::LinearGradientPattern
852 || d->style == Qt::RadialGradientPattern
853 || d->style == Qt::ConicalGradientPattern) {
854 QGradientStops stops = gradient()->stops();
855 for (int i=0; i<stops.size(); ++i)
856 if (stops.at(i).second.alpha() != 255)
857 return false;
858 return true;
859 } else if (d->style == Qt::TexturePattern) {
860 return qHasPixmapTexture(*this)
861 ? !texture().hasAlphaChannel() && !texture().isQBitmap()
862 : !textureImage().hasAlphaChannel();
863 }
864
865 return false;
866}
867
868
869/*!
870 \since 4.2
871
872 Sets \a matrix as an explicit transformation matrix on the
873 current brush. The brush transformation matrix is merged with
874 QPainter transformation matrix to produce the final result.
875
876 \sa matrix()
877*/
878void QBrush::setMatrix(const QMatrix &matrix)
879{
880 setTransform(QTransform(matrix));
881}
882
883/*!
884 \since 4.3
885
886 Sets \a matrix as an explicit transformation matrix on the
887 current brush. The brush transformation matrix is merged with
888 QPainter transformation matrix to produce the final result.
889
890 \sa transform()
891*/
892void QBrush::setTransform(const QTransform &matrix)
893{
894 detach(d->style);
895 d->transform = matrix;
896}
897
898
899/*!
900 \fn void QBrush::matrix() const
901 \since 4.2
902
903 Returns the current transformation matrix for the brush.
904
905 \sa setMatrix()
906*/
907
908/*!
909 \fn bool QBrush::operator!=(const QBrush &brush) const
910
911 Returns true if the brush is different from the given \a brush;
912 otherwise returns false.
913
914 Two brushes are different if they have different styles, colors or
915 pixmaps.
916
917 \sa operator==()
918*/
919
920/*!
921 \fn bool QBrush::operator==(const QBrush &brush) const
922
923 Returns true if the brush is equal to the given \a brush;
924 otherwise returns false.
925
926 Two brushes are equal if they have equal styles, colors and
927 pixmaps.
928
929 \sa operator!=()
930*/
931
932bool QBrush::operator==(const QBrush &b) const
933{
934 if (b.d == d)
935 return true;
936 if (b.d->style == d->style && b.d->color == d->color) {
937 switch (d->style) {
938 case Qt::TexturePattern: {
939 QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
940 QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
941 return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
942 }
943 case Qt::LinearGradientPattern:
944 case Qt::RadialGradientPattern:
945 case Qt::ConicalGradientPattern:
946 {
947 QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
948 QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
949 return d1->gradient == d2->gradient;
950 }
951 default:
952 return true;
953 }
954 }
955 return false;
956}
957
958/*!
959 \fn QBrush::operator const QColor&() const
960
961 Returns the brush's color.
962
963 Use color() instead.
964*/
965
966#ifndef QT_NO_DEBUG_STREAM
967/*!
968 \internal
969*/
970QDebug operator<<(QDebug dbg, const QBrush &b)
971{
972#ifndef Q_BROKEN_DEBUG_STREAM
973 static const char *BRUSH_STYLES[] = {
974 "NoBrush",
975 "SolidPattern",
976 "Dense1Pattern",
977 "Dense2Pattern",
978 "Dense3Pattern",
979 "Dense4Pattern",
980 "Dense5Pattern",
981 "Dense6Pattern",
982 "Dense7Pattern",
983 "HorPattern",
984 "VerPattern",
985 "CrossPattern",
986 "BDiagPattern",
987 "FDiagPattern",
988 "DiagCrossPattern",
989 "LinearGradientPattern",
990 "RadialGradientPattern",
991 "ConicalGradientPattern",
992 "TexturePattern"
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.