|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 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 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qbrush.h" |
|
43 #include "qpixmap.h" |
|
44 #include "qbitmap.h" |
|
45 #include "qpixmapcache.h" |
|
46 #include "qdatastream.h" |
|
47 #include "qvariant.h" |
|
48 #include "qline.h" |
|
49 #include "qdebug.h" |
|
50 #include <QtCore/qcoreapplication.h> |
|
51 |
|
52 QT_BEGIN_NAMESPACE |
|
53 |
|
54 const 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 |
|
97 QPixmap 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 |
|
111 class QBrushPatternImageCache |
|
112 { |
|
113 public: |
|
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 |
|
147 private: |
|
148 QImage m_images[Qt::DiagCrossPattern - Qt::Dense1Pattern + 1][2]; |
|
149 bool m_initialized; |
|
150 }; |
|
151 |
|
152 static void qt_cleanup_brush_pattern_image_cache(); |
|
153 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushPatternImageCache, qt_brushPatternImageCache, |
|
154 { |
|
155 qAddPostRoutine(qt_cleanup_brush_pattern_image_cache); |
|
156 }) |
|
157 |
|
158 static void qt_cleanup_brush_pattern_image_cache() |
|
159 { |
|
160 qt_brushPatternImageCache()->cleanup(); |
|
161 } |
|
162 |
|
163 Q_GUI_EXPORT |
|
164 QImage qt_imageForBrush(int brushStyle, bool invert) |
|
165 { |
|
166 return qt_brushPatternImageCache()->getImage(brushStyle, invert); |
|
167 } |
|
168 |
|
169 struct 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 |
|
220 bool 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 |
|
228 struct QGradientBrushData : public QBrushData |
|
229 { |
|
230 QGradient gradient; |
|
231 }; |
|
232 |
|
233 struct 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 |
|
341 template <> |
|
342 class QGlobalStaticDeleter<QBrushData> |
|
343 { |
|
344 public: |
|
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 |
|
360 Q_GLOBAL_STATIC_WITH_INITIALIZER(QBrushData, nullBrushInstance, |
|
361 { |
|
362 x->ref = 1; |
|
363 x->style = Qt::BrushStyle(0); |
|
364 x->color = Qt::black; |
|
365 }) |
|
366 |
|
367 static 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 |
|
388 void 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 |
|
418 QBrush::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 |
|
432 QBrush::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 |
|
446 QBrush::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 |
|
458 QBrush::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 |
|
474 QBrush::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 */ |
|
491 QBrush::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 |
|
511 QBrush::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 */ |
|
527 QBrush::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 |
|
537 QBrush::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 */ |
|
550 QBrush::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 |
|
571 QBrush::~QBrush() |
|
572 { |
|
573 } |
|
574 |
|
575 void QBrush::cleanUp(QBrushData *x) |
|
576 { |
|
577 QBrushDataPointerDeleter::deleteData(x); |
|
578 } |
|
579 |
|
580 |
|
581 void 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 |
|
626 QBrush &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 */ |
|
639 QBrush::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 |
|
658 void 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 |
|
690 void 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 */ |
|
723 QPixmap *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 */ |
|
741 QPixmap 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 |
|
758 void 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 |
|
782 QImage 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 |
|
806 void 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 */ |
|
821 const 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 |
|
843 bool 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 */ |
|
878 void 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 */ |
|
892 void 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 |
|
932 bool 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 */ |
|
970 QDebug operator<<(QDebug dbg, const QBrush &b) |
|
971 { |
|
972 #ifndef Q_BROKEN_DEBUG_STREAM |
|
973 dbg.nospace() << "QBrush(" << b.color() << ',' << b.style() << ')'; |
|
974 return dbg.space(); |
|
975 #else |
|
976 qWarning("This compiler doesn't support streaming QBrush to QDebug"); |
|
977 return dbg; |
|
978 Q_UNUSED(b); |
|
979 #endif |
|
980 } |
|
981 #endif |
|
982 |
|
983 /***************************************************************************** |
|
984 QBrush stream functions |
|
985 *****************************************************************************/ |
|
986 #ifndef QT_NO_DATASTREAM |
|
987 /*! |
|
988 \fn QDataStream &operator<<(QDataStream &stream, const QBrush &brush) |
|
989 \relates QBrush |
|
990 |
|
991 Writes the given \a brush to the given \a stream and returns a |
|
992 reference to the \a stream. |
|
993 |
|
994 \sa {Format of the QDataStream Operators} |
|
995 */ |
|
996 |
|
997 QDataStream &operator<<(QDataStream &s, const QBrush &b) |
|
998 { |
|
999 quint8 style = (quint8) b.style(); |
|
1000 bool gradient_style = false; |
|
1001 |
|
1002 if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern |
|
1003 || style == Qt::ConicalGradientPattern) |
|
1004 gradient_style = true; |
|
1005 |
|
1006 if (s.version() < QDataStream::Qt_4_0 && gradient_style) |
|
1007 style = Qt::NoBrush; |
|
1008 |
|
1009 s << style << b.color(); |
|
1010 if (b.style() == Qt::TexturePattern) { |
|
1011 s << b.texture(); |
|
1012 } else if (s.version() >= QDataStream::Qt_4_0 && gradient_style) { |
|
1013 const QGradient *gradient = b.gradient(); |
|
1014 int type_as_int = int(gradient->type()); |
|
1015 s << type_as_int; |
|
1016 if (s.version() >= QDataStream::Qt_4_3) { |
|
1017 s << int(gradient->spread()); |
|
1018 s << int(gradient->coordinateMode()); |
|
1019 } |
|
1020 |
|
1021 if (s.version() >= QDataStream::Qt_4_5) |
|
1022 s << int(gradient->interpolationMode()); |
|
1023 |
|
1024 if (sizeof(qreal) == sizeof(double)) { |
|
1025 s << gradient->stops(); |
|
1026 } else { |
|
1027 // ensure that we write doubles here instead of streaming the stops |
|
1028 // directly; otherwise, platforms that redefine qreal might generate |
|
1029 // data that cannot be read on other platforms. |
|
1030 QVector<QGradientStop> stops = gradient->stops(); |
|
1031 s << quint32(stops.size()); |
|
1032 for (int i = 0; i < stops.size(); ++i) { |
|
1033 const QGradientStop &stop = stops.at(i); |
|
1034 s << QPair<double, QColor>(double(stop.first), stop.second); |
|
1035 } |
|
1036 } |
|
1037 |
|
1038 if (gradient->type() == QGradient::LinearGradient) { |
|
1039 s << static_cast<const QLinearGradient *>(gradient)->start(); |
|
1040 s << static_cast<const QLinearGradient *>(gradient)->finalStop(); |
|
1041 } else if (gradient->type() == QGradient::RadialGradient) { |
|
1042 s << static_cast<const QRadialGradient *>(gradient)->center(); |
|
1043 s << static_cast<const QRadialGradient *>(gradient)->focalPoint(); |
|
1044 s << (double) static_cast<const QRadialGradient *>(gradient)->radius(); |
|
1045 } else { // type == Conical |
|
1046 s << static_cast<const QConicalGradient *>(gradient)->center(); |
|
1047 s << (double) static_cast<const QConicalGradient *>(gradient)->angle(); |
|
1048 } |
|
1049 } |
|
1050 if (s.version() >= QDataStream::Qt_4_3) |
|
1051 s << b.transform(); |
|
1052 return s; |
|
1053 } |
|
1054 |
|
1055 /*! |
|
1056 \fn QDataStream &operator>>(QDataStream &stream, QBrush &brush) |
|
1057 \relates QBrush |
|
1058 |
|
1059 Reads the given \a brush from the given \a stream and returns a |
|
1060 reference to the \a stream. |
|
1061 |
|
1062 \sa {Format of the QDataStream Operators} |
|
1063 */ |
|
1064 |
|
1065 QDataStream &operator>>(QDataStream &s, QBrush &b) |
|
1066 { |
|
1067 quint8 style; |
|
1068 QColor color; |
|
1069 s >> style; |
|
1070 s >> color; |
|
1071 if (style == Qt::TexturePattern) { |
|
1072 QPixmap pm; |
|
1073 s >> pm; |
|
1074 b = QBrush(color, pm); |
|
1075 } else if (style == Qt::LinearGradientPattern |
|
1076 || style == Qt::RadialGradientPattern |
|
1077 || style == Qt::ConicalGradientPattern) { |
|
1078 |
|
1079 int type_as_int; |
|
1080 QGradient::Type type; |
|
1081 QGradientStops stops; |
|
1082 QGradient::CoordinateMode cmode = QGradient::LogicalMode; |
|
1083 QGradient::Spread spread = QGradient::PadSpread; |
|
1084 QGradient::InterpolationMode imode = QGradient::ColorInterpolation; |
|
1085 |
|
1086 s >> type_as_int; |
|
1087 type = QGradient::Type(type_as_int); |
|
1088 if (s.version() >= QDataStream::Qt_4_3) { |
|
1089 s >> type_as_int; |
|
1090 spread = QGradient::Spread(type_as_int); |
|
1091 s >> type_as_int; |
|
1092 cmode = QGradient::CoordinateMode(type_as_int); |
|
1093 } |
|
1094 |
|
1095 if (s.version() >= QDataStream::Qt_4_5) { |
|
1096 s >> type_as_int; |
|
1097 imode = QGradient::InterpolationMode(type_as_int); |
|
1098 } |
|
1099 |
|
1100 if (sizeof(qreal) == sizeof(double)) { |
|
1101 s >> stops; |
|
1102 } else { |
|
1103 quint32 numStops; |
|
1104 double n; |
|
1105 QColor c; |
|
1106 |
|
1107 s >> numStops; |
|
1108 for (quint32 i = 0; i < numStops; ++i) { |
|
1109 s >> n >> c; |
|
1110 stops << QPair<qreal, QColor>(n, c); |
|
1111 } |
|
1112 } |
|
1113 |
|
1114 if (type == QGradient::LinearGradient) { |
|
1115 QPointF p1, p2; |
|
1116 s >> p1; |
|
1117 s >> p2; |
|
1118 QLinearGradient lg(p1, p2); |
|
1119 lg.setStops(stops); |
|
1120 lg.setSpread(spread); |
|
1121 lg.setCoordinateMode(cmode); |
|
1122 lg.setInterpolationMode(imode); |
|
1123 b = QBrush(lg); |
|
1124 } else if (type == QGradient::RadialGradient) { |
|
1125 QPointF center, focal; |
|
1126 double radius; |
|
1127 s >> center; |
|
1128 s >> focal; |
|
1129 s >> radius; |
|
1130 QRadialGradient rg(center, radius, focal); |
|
1131 rg.setStops(stops); |
|
1132 rg.setSpread(spread); |
|
1133 rg.setCoordinateMode(cmode); |
|
1134 rg.setInterpolationMode(imode); |
|
1135 b = QBrush(rg); |
|
1136 } else { // type == QGradient::ConicalGradient |
|
1137 QPointF center; |
|
1138 double angle; |
|
1139 s >> center; |
|
1140 s >> angle; |
|
1141 QConicalGradient cg(center, angle); |
|
1142 cg.setStops(stops); |
|
1143 cg.setSpread(spread); |
|
1144 cg.setCoordinateMode(cmode); |
|
1145 cg.setInterpolationMode(imode); |
|
1146 b = QBrush(cg); |
|
1147 } |
|
1148 } else { |
|
1149 b = QBrush(color, (Qt::BrushStyle)style); |
|
1150 } |
|
1151 if (s.version() >= QDataStream::Qt_4_3) { |
|
1152 QTransform transform; |
|
1153 s >> transform; |
|
1154 b.setTransform(transform); |
|
1155 } |
|
1156 return s; |
|
1157 } |
|
1158 #endif // QT_NO_DATASTREAM |
|
1159 |
|
1160 /******************************************************************************* |
|
1161 * QGradient implementations |
|
1162 */ |
|
1163 |
|
1164 |
|
1165 /*! |
|
1166 \class QGradient |
|
1167 \ingroup painting |
|
1168 \ingroup shared |
|
1169 |
|
1170 \brief The QGradient class is used in combination with QBrush to |
|
1171 specify gradient fills. |
|
1172 |
|
1173 Qt currently supports three types of gradient fills: |
|
1174 |
|
1175 \list |
|
1176 \o \e Linear gradients interpolate colors between start and end points. |
|
1177 \o \e Radial gradients interpolate colors between a focal point and end |
|
1178 points on a circle surrounding it. |
|
1179 \o \e Conical gradients interpolate colors around a center point. |
|
1180 \endlist |
|
1181 |
|
1182 A gradient's type can be retrieved using the type() function. |
|
1183 Each of the types is represented by a subclass of QGradient: |
|
1184 |
|
1185 \table |
|
1186 \row |
|
1187 \o \inlineimage qgradient-linear.png |
|
1188 \o \inlineimage qgradient-radial.png |
|
1189 \o \inlineimage qgradient-conical.png |
|
1190 \header |
|
1191 \o QLinearGradient |
|
1192 \o QRadialGradient |
|
1193 \o QConicalGradient |
|
1194 \endtable |
|
1195 |
|
1196 The colors in a gradient is defined using stop points of the |
|
1197 QGradientStop type, i.e. a position and a color. Use the |
|
1198 setColorAt() function to define a single stop |
|
1199 point. Alternatively, use the setStops() function to define |
|
1200 several stop points in one go. Note that the latter function \e |
|
1201 replaces the current set of stop points. |
|
1202 |
|
1203 It is the gradient's complete set of stop points (accessible |
|
1204 through the stops() function) that describes how the gradient area |
|
1205 should be filled. If no stop points have been specified, a |
|
1206 gradient of black at 0 to white at 1 is used. |
|
1207 |
|
1208 A diagonal linear gradient from black at (100, 100) to white at |
|
1209 (200, 200) could be specified like this: |
|
1210 |
|
1211 \snippet doc/src/snippets/brush/brush.cpp 0 |
|
1212 |
|
1213 A gradient can have an arbitrary number of stop points. The |
|
1214 following would create a radial gradient starting with |
|
1215 red in the center, blue and then green on the edges: |
|
1216 |
|
1217 \snippet doc/src/snippets/brush/brush.cpp 1 |
|
1218 |
|
1219 It is possible to repeat or reflect the gradient outside its area |
|
1220 by specifiying the \l {QGradient::Spread}{spread method} using the |
|
1221 setSpread() function. The default is to pad the outside area with |
|
1222 the color at the closest stop point. The currently set \l |
|
1223 {QGradient::Spread}{spread method} can be retrieved using the |
|
1224 spread() function. The QGradient::Spread enum defines three |
|
1225 different methods: |
|
1226 |
|
1227 \table |
|
1228 \row |
|
1229 \o \inlineimage qradialgradient-pad.png |
|
1230 \o \inlineimage qradialgradient-repeat.png |
|
1231 \o \inlineimage qradialgradient-reflect.png |
|
1232 \row |
|
1233 \o \l {QGradient::PadSpread}{PadSpread} |
|
1234 \o \l {QGradient::RepeatSpread}{RepeatSpread} |
|
1235 \o \l {QGradient::ReflectSpread}{ReflectSpread} |
|
1236 \endtable |
|
1237 |
|
1238 Note that the setSpread() function only has effect for linear and |
|
1239 radial gradients. The reason is that the conical gradient is |
|
1240 closed by definition, i.e. the \e conical gradient fills the |
|
1241 entire circle from 0 - 360 degrees, while the boundary of a radial |
|
1242 or a linear gradient can be specified through its radius or final |
|
1243 stop points, respectively. |
|
1244 |
|
1245 The gradient coordinates can be specified in logical coordinates, |
|
1246 relative to device coordinates, or relative to object bounding box coordinates. |
|
1247 The \l {QGradient::CoordinateMode}{coordinate mode} can be set using the |
|
1248 setCoordinateMode() function. The default is LogicalMode, where the |
|
1249 gradient coordinates are specified in the same way as the object |
|
1250 coordinates. To retrieve the currently set \l {QGradient::CoordinateMode} |
|
1251 {coordinate mode} use coordinateMode(). |
|
1252 |
|
1253 |
|
1254 \sa {demos/gradients}{The Gradients Demo}, QBrush |
|
1255 */ |
|
1256 |
|
1257 /*! |
|
1258 \internal |
|
1259 */ |
|
1260 QGradient::QGradient() |
|
1261 : m_type(NoGradient), dummy(0) |
|
1262 { |
|
1263 } |
|
1264 |
|
1265 |
|
1266 /*! |
|
1267 \enum QGradient::Type |
|
1268 |
|
1269 Specifies the type of gradient. |
|
1270 |
|
1271 \value LinearGradient Interpolates colors between start and end points |
|
1272 (QLinearGradient). |
|
1273 |
|
1274 \value RadialGradient Interpolate colors between a focal point and end |
|
1275 points on a circle surrounding it (QRadialGradient). |
|
1276 |
|
1277 \value ConicalGradient Interpolate colors around a center point (QConicalGradient). |
|
1278 \value NoGradient No gradient is used. |
|
1279 |
|
1280 \sa type() |
|
1281 */ |
|
1282 |
|
1283 /*! |
|
1284 \enum QGradient::Spread |
|
1285 |
|
1286 Specifies how the area outside the gradient area should be |
|
1287 filled. |
|
1288 |
|
1289 \value PadSpread The area is filled with the closest stop |
|
1290 color. This is the default. |
|
1291 |
|
1292 \value RepeatSpread The gradient is repeated outside the gradient |
|
1293 area. |
|
1294 |
|
1295 \value ReflectSpread The gradient is reflected outside the |
|
1296 gradient area. |
|
1297 |
|
1298 \sa spread(), setSpread() |
|
1299 */ |
|
1300 |
|
1301 /*! |
|
1302 \fn void QGradient::setSpread(Spread method) |
|
1303 |
|
1304 Specifies the spread \a method that should be used for this |
|
1305 gradient. |
|
1306 |
|
1307 Note that this function only has effect for linear and radial |
|
1308 gradients. |
|
1309 |
|
1310 \sa spread() |
|
1311 */ |
|
1312 |
|
1313 /*! |
|
1314 \fn QGradient::Spread QGradient::spread() const |
|
1315 |
|
1316 Returns the spread method use by this gradient. The default is |
|
1317 PadSpread. |
|
1318 |
|
1319 \sa setSpread() |
|
1320 */ |
|
1321 |
|
1322 /*! |
|
1323 \fn QGradient::Type QGradient::type() const |
|
1324 |
|
1325 Returns the type of gradient. |
|
1326 */ |
|
1327 |
|
1328 /*! |
|
1329 \fn void QGradient::setColorAt(qreal position, const QColor &color) |
|
1330 |
|
1331 Creates a stop point at the given \a position with the given \a |
|
1332 color. The given \a position must be in the range 0 to 1. |
|
1333 |
|
1334 \sa setStops(), stops() |
|
1335 */ |
|
1336 |
|
1337 void QGradient::setColorAt(qreal pos, const QColor &color) |
|
1338 { |
|
1339 if (pos > 1 || pos < 0) { |
|
1340 qWarning("QGradient::setColorAt: Color position must be specified in the range 0 to 1"); |
|
1341 return; |
|
1342 } |
|
1343 |
|
1344 int index = 0; |
|
1345 while (index < m_stops.size() && m_stops.at(index).first < pos) ++index; |
|
1346 |
|
1347 if (index < m_stops.size() && m_stops.at(index).first == pos) |
|
1348 m_stops[index].second = color; |
|
1349 else |
|
1350 m_stops.insert(index, QGradientStop(pos, color)); |
|
1351 } |
|
1352 |
|
1353 /*! |
|
1354 \fn void QGradient::setStops(const QGradientStops &stopPoints) |
|
1355 |
|
1356 Replaces the current set of stop points with the given \a |
|
1357 stopPoints. The positions of the points must be in the range 0 to |
|
1358 1, and must be sorted with the lowest point first. |
|
1359 |
|
1360 \sa setColorAt(), stops() |
|
1361 */ |
|
1362 void QGradient::setStops(const QGradientStops &stops) |
|
1363 { |
|
1364 m_stops.clear(); |
|
1365 for (int i=0; i<stops.size(); ++i) |
|
1366 setColorAt(stops.at(i).first, stops.at(i).second); |
|
1367 } |
|
1368 |
|
1369 |
|
1370 /*! |
|
1371 Returns the stop points for this gradient. |
|
1372 |
|
1373 If no stop points have been specified, a gradient of black at 0 to white |
|
1374 at 1 is used. |
|
1375 |
|
1376 \sa setStops(), setColorAt() |
|
1377 */ |
|
1378 QGradientStops QGradient::stops() const |
|
1379 { |
|
1380 if (m_stops.isEmpty()) { |
|
1381 QGradientStops tmp; |
|
1382 tmp << QGradientStop(0, Qt::black) << QGradientStop(1, Qt::white); |
|
1383 return tmp; |
|
1384 } |
|
1385 return m_stops; |
|
1386 } |
|
1387 |
|
1388 #define Q_DUMMY_ACCESSOR union {void *p; uint i;}; p = dummy; |
|
1389 |
|
1390 /*! |
|
1391 \enum QGradient::CoordinateMode |
|
1392 \since 4.4 |
|
1393 |
|
1394 This enum specifies how gradient coordinates map to the paint |
|
1395 device on which the gradient is used. |
|
1396 |
|
1397 \value LogicalMode This is the default mode. The gradient coordinates |
|
1398 are specified logical space just like the object coordinates. |
|
1399 \value StretchToDeviceMode In this mode the gradient coordinates |
|
1400 are relative to the bounding rectangle of the paint device, |
|
1401 with (0,0) in the top left corner, and (1,1) in the bottom right |
|
1402 corner of the paint device. |
|
1403 \value ObjectBoundingMode In this mode the gradient coordinates are |
|
1404 relative to the bounding rectangle of the object being drawn, with |
|
1405 (0,0) in the top left corner, and (1,1) in the bottom right corner |
|
1406 of the object's bounding rectangle. |
|
1407 */ |
|
1408 |
|
1409 /*! |
|
1410 \since 4.4 |
|
1411 |
|
1412 Returns the coordinate mode of this gradient. The default mode is |
|
1413 LogicalMode. |
|
1414 */ |
|
1415 QGradient::CoordinateMode QGradient::coordinateMode() const |
|
1416 { |
|
1417 Q_DUMMY_ACCESSOR |
|
1418 return CoordinateMode(i & 0x03); |
|
1419 } |
|
1420 |
|
1421 /*! |
|
1422 \since 4.4 |
|
1423 |
|
1424 Sets the coordinate mode of this gradient to \a mode. The default |
|
1425 mode is LogicalMode. |
|
1426 */ |
|
1427 void QGradient::setCoordinateMode(CoordinateMode mode) |
|
1428 { |
|
1429 Q_DUMMY_ACCESSOR |
|
1430 i &= ~0x03; |
|
1431 i |= uint(mode); |
|
1432 dummy = p; |
|
1433 } |
|
1434 |
|
1435 /*! |
|
1436 \enum QGradient::InterpolationMode |
|
1437 \since 4.5 |
|
1438 \internal |
|
1439 |
|
1440 \value ComponentInterpolation The color components and the alpha component are |
|
1441 independently linearly interpolated. |
|
1442 \value ColorInterpolation The colors are linearly interpolated in |
|
1443 premultiplied color space. |
|
1444 */ |
|
1445 |
|
1446 /*! |
|
1447 \since 4.5 |
|
1448 \internal |
|
1449 |
|
1450 Returns the interpolation mode of this gradient. The default mode is |
|
1451 ColorInterpolation. |
|
1452 */ |
|
1453 QGradient::InterpolationMode QGradient::interpolationMode() const |
|
1454 { |
|
1455 Q_DUMMY_ACCESSOR |
|
1456 return InterpolationMode((i >> 2) & 0x01); |
|
1457 } |
|
1458 |
|
1459 /*! |
|
1460 \since 4.5 |
|
1461 \internal |
|
1462 |
|
1463 Sets the interpolation mode of this gradient to \a mode. The default |
|
1464 mode is ColorInterpolation. |
|
1465 */ |
|
1466 void QGradient::setInterpolationMode(InterpolationMode mode) |
|
1467 { |
|
1468 Q_DUMMY_ACCESSOR |
|
1469 i &= ~(1 << 2); |
|
1470 i |= (uint(mode) << 2); |
|
1471 dummy = p; |
|
1472 } |
|
1473 |
|
1474 #undef Q_DUMMY_ACCESSOR |
|
1475 |
|
1476 /*! |
|
1477 \fn bool QGradient::operator!=(const QGradient &gradient) const |
|
1478 \since 4.2 |
|
1479 |
|
1480 Returns true if the gradient is the same as the other \a gradient |
|
1481 specified; otherwise returns false. |
|
1482 |
|
1483 \sa operator==() |
|
1484 */ |
|
1485 |
|
1486 /*! |
|
1487 Returns true if the gradient is the same as the other \a gradient |
|
1488 specified; otherwise returns false. |
|
1489 |
|
1490 \sa operator!=() |
|
1491 */ |
|
1492 bool QGradient::operator==(const QGradient &gradient) const |
|
1493 { |
|
1494 if (gradient.m_type != m_type |
|
1495 || gradient.m_spread != m_spread |
|
1496 || gradient.dummy != dummy) return false; |
|
1497 |
|
1498 if (m_type == LinearGradient) { |
|
1499 if (m_data.linear.x1 != gradient.m_data.linear.x1 |
|
1500 || m_data.linear.y1 != gradient.m_data.linear.y1 |
|
1501 || m_data.linear.x2 != gradient.m_data.linear.x2 |
|
1502 || m_data.linear.y2 != gradient.m_data.linear.y2) |
|
1503 return false; |
|
1504 } else if (m_type == RadialGradient) { |
|
1505 if (m_data.radial.cx != gradient.m_data.radial.cx |
|
1506 || m_data.radial.cy != gradient.m_data.radial.cy |
|
1507 || m_data.radial.fx != gradient.m_data.radial.fx |
|
1508 || m_data.radial.fy != gradient.m_data.radial.fy |
|
1509 || m_data.radial.radius != gradient.m_data.radial.radius) |
|
1510 return false; |
|
1511 } else { // m_type == ConicalGradient |
|
1512 if (m_data.conical.cx != gradient.m_data.conical.cx |
|
1513 || m_data.conical.cy != gradient.m_data.conical.cy |
|
1514 || m_data.conical.angle != gradient.m_data.conical.angle) |
|
1515 return false; |
|
1516 } |
|
1517 |
|
1518 return stops() == gradient.stops(); |
|
1519 } |
|
1520 |
|
1521 /*! |
|
1522 \internal |
|
1523 */ |
|
1524 bool QGradient::operator==(const QGradient &gradient) |
|
1525 { |
|
1526 return const_cast<const QGradient *>(this)->operator==(gradient); |
|
1527 } |
|
1528 |
|
1529 /*! |
|
1530 \class QLinearGradient |
|
1531 \ingroup painting |
|
1532 |
|
1533 \brief The QLinearGradient class is used in combination with QBrush to |
|
1534 specify a linear gradient brush. |
|
1535 |
|
1536 Linear gradients interpolate colors between start and end |
|
1537 points. Outside these points the gradient is either padded, |
|
1538 reflected or repeated depending on the currently set \l |
|
1539 {QGradient::Spread}{spread} method: |
|
1540 |
|
1541 \table |
|
1542 \row |
|
1543 \o \inlineimage qlineargradient-pad.png |
|
1544 \o \inlineimage qlineargradient-reflect.png |
|
1545 \o \inlineimage qlineargradient-repeat.png |
|
1546 \row |
|
1547 \o \l {QGradient::PadSpread}{PadSpread} (default) |
|
1548 \o \l {QGradient::ReflectSpread}{ReflectSpread} |
|
1549 \o \l {QGradient::RepeatSpread}{RepeatSpread} |
|
1550 \endtable |
|
1551 |
|
1552 The colors in a gradient is defined using stop points of the |
|
1553 QGradientStop type, i.e. a position and a color. Use the |
|
1554 QGradient::setColorAt() or the QGradient::setStops() function to |
|
1555 define the stop points. It is the gradient's complete set of stop |
|
1556 points that describes how the gradient area should be filled. If |
|
1557 no stop points have been specified, a gradient of black at 0 to |
|
1558 white at 1 is used. |
|
1559 |
|
1560 In addition to the functions inherited from QGradient, the |
|
1561 QLinearGradient class provides the finalStop() function which |
|
1562 returns the final stop point of the gradient, and the start() |
|
1563 function returning the start point of the gradient. |
|
1564 |
|
1565 \sa QRadialGradient, QConicalGradient, {demos/gradients}{The |
|
1566 Gradients Demo} |
|
1567 */ |
|
1568 |
|
1569 |
|
1570 /*! |
|
1571 Constructs a default linear gradient with interpolation area |
|
1572 between (0, 0) and (1, 1). |
|
1573 |
|
1574 \sa QGradient::setColorAt(), setStart(), setFinalStop() |
|
1575 */ |
|
1576 |
|
1577 QLinearGradient::QLinearGradient() |
|
1578 { |
|
1579 m_type = LinearGradient; |
|
1580 m_spread = PadSpread; |
|
1581 m_data.linear.x1 = 0; |
|
1582 m_data.linear.y1 = 0; |
|
1583 m_data.linear.x2 = 1; |
|
1584 m_data.linear.y2 = 1; |
|
1585 } |
|
1586 |
|
1587 |
|
1588 /*! |
|
1589 Constructs a linear gradient with interpolation area between the |
|
1590 given \a start point and \a finalStop. |
|
1591 |
|
1592 \note The expected parameter values are in pixels. |
|
1593 |
|
1594 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1595 */ |
|
1596 QLinearGradient::QLinearGradient(const QPointF &start, const QPointF &finalStop) |
|
1597 { |
|
1598 m_type = LinearGradient; |
|
1599 m_spread = PadSpread; |
|
1600 m_data.linear.x1 = start.x(); |
|
1601 m_data.linear.y1 = start.y(); |
|
1602 m_data.linear.x2 = finalStop.x(); |
|
1603 m_data.linear.y2 = finalStop.y(); |
|
1604 } |
|
1605 |
|
1606 /*! |
|
1607 \fn QLinearGradient::QLinearGradient(qreal x1, qreal y1, qreal x2, qreal y2) |
|
1608 |
|
1609 Constructs a linear gradient with interpolation area between (\a |
|
1610 x1, \a y1) and (\a x2, \a y2). |
|
1611 |
|
1612 \note The expected parameter values are in pixels. |
|
1613 |
|
1614 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1615 */ |
|
1616 QLinearGradient::QLinearGradient(qreal xStart, qreal yStart, qreal xFinalStop, qreal yFinalStop) |
|
1617 { |
|
1618 m_type = LinearGradient; |
|
1619 m_spread = PadSpread; |
|
1620 m_data.linear.x1 = xStart; |
|
1621 m_data.linear.y1 = yStart; |
|
1622 m_data.linear.x2 = xFinalStop; |
|
1623 m_data.linear.y2 = yFinalStop; |
|
1624 } |
|
1625 |
|
1626 |
|
1627 /*! |
|
1628 Returns the start point of this linear gradient in logical coordinates. |
|
1629 |
|
1630 \sa QGradient::stops() |
|
1631 */ |
|
1632 |
|
1633 QPointF QLinearGradient::start() const |
|
1634 { |
|
1635 Q_ASSERT(m_type == LinearGradient); |
|
1636 return QPointF(m_data.linear.x1, m_data.linear.y1); |
|
1637 } |
|
1638 |
|
1639 /*! |
|
1640 \fn void QLinearGradient::setStart(qreal x, qreal y) |
|
1641 \overload |
|
1642 \since 4.2 |
|
1643 |
|
1644 Sets the start point of this linear gradient in logical |
|
1645 coordinates to \a x, \a y. |
|
1646 |
|
1647 \sa start() |
|
1648 */ |
|
1649 |
|
1650 /*! |
|
1651 \since 4.2 |
|
1652 |
|
1653 Sets the start point of this linear gradient in logical |
|
1654 coordinates to \a start. |
|
1655 |
|
1656 \sa start() |
|
1657 */ |
|
1658 |
|
1659 void QLinearGradient::setStart(const QPointF &start) |
|
1660 { |
|
1661 Q_ASSERT(m_type == LinearGradient); |
|
1662 m_data.linear.x1 = start.x(); |
|
1663 m_data.linear.y1 = start.y(); |
|
1664 } |
|
1665 |
|
1666 |
|
1667 /*! |
|
1668 \fn void QLinearGradient::setFinalStop(qreal x, qreal y) |
|
1669 \overload |
|
1670 \since 4.2 |
|
1671 |
|
1672 Sets the final stop point of this linear gradient in logical |
|
1673 coordinates to \a x, \a y. |
|
1674 |
|
1675 \sa start() |
|
1676 */ |
|
1677 |
|
1678 /*! |
|
1679 Returns the final stop point of this linear gradient in logical coordinates. |
|
1680 |
|
1681 \sa QGradient::stops() |
|
1682 */ |
|
1683 |
|
1684 QPointF QLinearGradient::finalStop() const |
|
1685 { |
|
1686 Q_ASSERT(m_type == LinearGradient); |
|
1687 return QPointF(m_data.linear.x2, m_data.linear.y2); |
|
1688 } |
|
1689 |
|
1690 |
|
1691 /*! |
|
1692 \since 4.2 |
|
1693 |
|
1694 Sets the final stop point of this linear gradient in logical |
|
1695 coordinates to \a stop. |
|
1696 |
|
1697 \sa finalStop() |
|
1698 */ |
|
1699 |
|
1700 void QLinearGradient::setFinalStop(const QPointF &stop) |
|
1701 { |
|
1702 Q_ASSERT(m_type == LinearGradient); |
|
1703 m_data.linear.x2 = stop.x(); |
|
1704 m_data.linear.y2 = stop.y(); |
|
1705 } |
|
1706 |
|
1707 |
|
1708 /*! |
|
1709 \class QRadialGradient |
|
1710 \ingroup painting |
|
1711 |
|
1712 \brief The QRadialGradient class is used in combination with QBrush to |
|
1713 specify a radial gradient brush. |
|
1714 |
|
1715 Radial gradients interpolate colors between a focal point and end |
|
1716 points on a circle surrounding it. Outside the end points the |
|
1717 gradient is either padded, reflected or repeated depending on the |
|
1718 currently set \l {QGradient::Spread}{spread} method: |
|
1719 |
|
1720 \table |
|
1721 \row |
|
1722 \o \inlineimage qradialgradient-pad.png |
|
1723 \o \inlineimage qradialgradient-reflect.png |
|
1724 \o \inlineimage qradialgradient-repeat.png |
|
1725 \row |
|
1726 \o \l {QGradient::PadSpread}{PadSpread} (default) |
|
1727 \o \l {QGradient::ReflectSpread}{ReflectSpread} |
|
1728 \o \l {QGradient::RepeatSpread}{RepeatSpread} |
|
1729 \endtable |
|
1730 |
|
1731 The colors in a gradient is defined using stop points of the |
|
1732 QGradientStop type, i.e. a position and a color. Use the |
|
1733 QGradient::setColorAt() or the QGradient::setStops() function to |
|
1734 define the stop points. It is the gradient's complete set of stop |
|
1735 points that describes how the gradient area should be filled. If |
|
1736 no stop points have been specified, a gradient of black at 0 to |
|
1737 white at 1 is used. |
|
1738 |
|
1739 In addition to the functions inherited from QGradient, the |
|
1740 QRadialGradient class provides the center(), focalPoint() and |
|
1741 radius() functions returning the gradient's center, focal point |
|
1742 and radius respectively. |
|
1743 |
|
1744 \sa QLinearGradient, QConicalGradient, {demos/gradients}{The |
|
1745 Gradients Demo} |
|
1746 */ |
|
1747 |
|
1748 static QPointF qt_radial_gradient_adapt_focal_point(const QPointF ¢er, |
|
1749 qreal radius, |
|
1750 const QPointF &focalPoint) |
|
1751 { |
|
1752 // We have a one pixel buffer zone to avoid numerical instability on the |
|
1753 // circle border |
|
1754 //### this is hacky because technically we should adjust based on current matrix |
|
1755 const qreal compensated_radius = radius - radius * 0.001; |
|
1756 QLineF line(center, focalPoint); |
|
1757 if (line.length() > (compensated_radius)) |
|
1758 line.setLength(compensated_radius); |
|
1759 return line.p2(); |
|
1760 } |
|
1761 |
|
1762 /*! |
|
1763 Constructs a radial gradient with the given \a center, \a |
|
1764 radius and \a focalPoint. |
|
1765 |
|
1766 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1767 */ |
|
1768 |
|
1769 QRadialGradient::QRadialGradient(const QPointF ¢er, qreal radius, const QPointF &focalPoint) |
|
1770 { |
|
1771 m_type = RadialGradient; |
|
1772 m_spread = PadSpread; |
|
1773 m_data.radial.cx = center.x(); |
|
1774 m_data.radial.cy = center.y(); |
|
1775 m_data.radial.radius = radius; |
|
1776 |
|
1777 QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(center, radius, focalPoint); |
|
1778 m_data.radial.fx = adapted_focal.x(); |
|
1779 m_data.radial.fy = adapted_focal.y(); |
|
1780 } |
|
1781 |
|
1782 /*! |
|
1783 Constructs a radial gradient with the given \a center, \a |
|
1784 radius and the focal point in the circle center. |
|
1785 |
|
1786 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1787 */ |
|
1788 QRadialGradient::QRadialGradient(const QPointF ¢er, qreal radius) |
|
1789 { |
|
1790 m_type = RadialGradient; |
|
1791 m_spread = PadSpread; |
|
1792 m_data.radial.cx = center.x(); |
|
1793 m_data.radial.cy = center.y(); |
|
1794 m_data.radial.radius = radius; |
|
1795 m_data.radial.fx = center.x(); |
|
1796 m_data.radial.fy = center.y(); |
|
1797 } |
|
1798 |
|
1799 |
|
1800 /*! |
|
1801 Constructs a radial gradient with the given center (\a cx, \a cy), |
|
1802 \a radius and focal point (\a fx, \a fy). |
|
1803 |
|
1804 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1805 */ |
|
1806 |
|
1807 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius, qreal fx, qreal fy) |
|
1808 { |
|
1809 m_type = RadialGradient; |
|
1810 m_spread = PadSpread; |
|
1811 m_data.radial.cx = cx; |
|
1812 m_data.radial.cy = cy; |
|
1813 m_data.radial.radius = radius; |
|
1814 |
|
1815 QPointF adapted_focal = qt_radial_gradient_adapt_focal_point(QPointF(cx, cy), |
|
1816 radius, |
|
1817 QPointF(fx, fy)); |
|
1818 |
|
1819 m_data.radial.fx = adapted_focal.x(); |
|
1820 m_data.radial.fy = adapted_focal.y(); |
|
1821 } |
|
1822 |
|
1823 /*! |
|
1824 Constructs a radial gradient with the center at (\a cx, \a cy) and the |
|
1825 specified \a radius. The focal point lies at the center of the circle. |
|
1826 |
|
1827 \sa QGradient::setColorAt(), QGradient::setStops() |
|
1828 */ |
|
1829 QRadialGradient::QRadialGradient(qreal cx, qreal cy, qreal radius) |
|
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 m_data.radial.fx = cx; |
|
1837 m_data.radial.fy = cy; |
|
1838 } |
|
1839 |
|
1840 |
|
1841 /*! |
|
1842 Constructs a radial gradient with the center and focal point at |
|
1843 (0, 0) with a radius of 1. |
|
1844 */ |
|
1845 QRadialGradient::QRadialGradient() |
|
1846 { |
|
1847 m_type = RadialGradient; |
|
1848 m_spread = PadSpread; |
|
1849 m_data.radial.cx = 0; |
|
1850 m_data.radial.cy = 0; |
|
1851 m_data.radial.radius = 1; |
|
1852 m_data.radial.fx = 0; |
|
1853 m_data.radial.fy = 0; |
|
1854 } |
|
1855 |
|
1856 |
|
1857 /*! |
|
1858 Returns the center of this radial gradient in logical coordinates. |
|
1859 |
|
1860 \sa QGradient::stops() |
|
1861 */ |
|
1862 |
|
1863 QPointF QRadialGradient::center() const |
|
1864 { |
|
1865 Q_ASSERT(m_type == RadialGradient); |
|
1866 return QPointF(m_data.radial.cx, m_data.radial.cy); |
|
1867 } |
|
1868 |
|
1869 /*! |
|
1870 \fn void QRadialGradient::setCenter(qreal x, qreal y) |
|
1871 \overload |
|
1872 \since 4.2 |
|
1873 |
|
1874 Sets the center of this radial gradient in logical coordinates |
|
1875 to (\a x, \a y). |
|
1876 |
|
1877 \sa center() |
|
1878 */ |
|
1879 |
|
1880 /*! |
|
1881 \since 4.2 |
|
1882 |
|
1883 Sets the center of this radial gradient in logical coordinates |
|
1884 to \a center. |
|
1885 |
|
1886 \sa center() |
|
1887 */ |
|
1888 |
|
1889 void QRadialGradient::setCenter(const QPointF ¢er) |
|
1890 { |
|
1891 Q_ASSERT(m_type == RadialGradient); |
|
1892 m_data.radial.cx = center.x(); |
|
1893 m_data.radial.cy = center.y(); |
|
1894 } |
|
1895 |
|
1896 |
|
1897 /*! |
|
1898 Returns the radius of this radial gradient in logical coordinates. |
|
1899 |
|
1900 \sa QGradient::stops() |
|
1901 */ |
|
1902 |
|
1903 qreal QRadialGradient::radius() const |
|
1904 { |
|
1905 Q_ASSERT(m_type == RadialGradient); |
|
1906 return m_data.radial.radius; |
|
1907 } |
|
1908 |
|
1909 |
|
1910 /*! |
|
1911 \since 4.2 |
|
1912 |
|
1913 Sets the radius of this radial gradient in logical coordinates |
|
1914 to \a radius |
|
1915 */ |
|
1916 void QRadialGradient::setRadius(qreal radius) |
|
1917 { |
|
1918 Q_ASSERT(m_type == RadialGradient); |
|
1919 m_data.radial.radius = radius; |
|
1920 } |
|
1921 |
|
1922 |
|
1923 /*! |
|
1924 Returns the focal point of this radial gradient in logical |
|
1925 coordinates. |
|
1926 |
|
1927 \sa QGradient::stops() |
|
1928 */ |
|
1929 |
|
1930 QPointF QRadialGradient::focalPoint() const |
|
1931 { |
|
1932 Q_ASSERT(m_type == RadialGradient); |
|
1933 return QPointF(m_data.radial.fx, m_data.radial.fy); |
|
1934 } |
|
1935 |
|
1936 /*! |
|
1937 \fn void QRadialGradient::setFocalPoint(qreal x, qreal y) |
|
1938 \overload |
|
1939 \since 4.2 |
|
1940 |
|
1941 Sets the focal point of this radial gradient in logical |
|
1942 coordinates to (\a x, \a y). |
|
1943 |
|
1944 \sa focalPoint() |
|
1945 */ |
|
1946 |
|
1947 /*! |
|
1948 \since 4.2 |
|
1949 |
|
1950 Sets the focal point of this radial gradient in logical |
|
1951 coordinates to \a focalPoint. |
|
1952 |
|
1953 \sa focalPoint() |
|
1954 */ |
|
1955 |
|
1956 void QRadialGradient::setFocalPoint(const QPointF &focalPoint) |
|
1957 { |
|
1958 Q_ASSERT(m_type == RadialGradient); |
|
1959 m_data.radial.fx = focalPoint.x(); |
|
1960 m_data.radial.fy = focalPoint.y(); |
|
1961 } |
|
1962 |
|
1963 |
|
1964 |
|
1965 /*! |
|
1966 \class QConicalGradient |
|
1967 \ingroup painting |
|
1968 |
|
1969 \brief The QConicalGradient class is used in combination with QBrush to |
|
1970 specify a conical gradient brush. |
|
1971 |
|
1972 Conical gradients interpolate interpolate colors counter-clockwise |
|
1973 around a center point. |
|
1974 |
|
1975 \image qconicalgradient.png |
|
1976 |
|
1977 The colors in a gradient is defined using stop points of the |
|
1978 QGradientStop type, i.e. a position and a color. Use the |
|
1979 QGradient::setColorAt() or the QGradient::setStops() function to |
|
1980 define the stop points. It is the gradient's complete set of stop |
|
1981 points that describes how the gradient area should be filled. If |
|
1982 no stop points have been specified, a gradient of black at 0 to |
|
1983 white at 1 is used. |
|
1984 |
|
1985 In addition to the functions inherited from QGradient, the |
|
1986 QConicalGradient class provides the angle() and center() functions |
|
1987 returning the start angle and center of the gradient. |
|
1988 |
|
1989 Note that the setSpread() function has no effect for conical |
|
1990 gradients. The reason is that the conical gradient is closed by |
|
1991 definition, i.e. the conical gradient fills the entire circle from |
|
1992 0 - 360 degrees, while the boundary of a radial or a linear |
|
1993 gradient can be specified through its radius or final stop points, |
|
1994 respectively. |
|
1995 |
|
1996 \sa QLinearGradient, QRadialGradient, {demos/gradients}{The |
|
1997 Gradients Demo} |
|
1998 */ |
|
1999 |
|
2000 |
|
2001 /*! |
|
2002 Constructs a conical gradient with the given \a center, starting |
|
2003 the interpolation at the given \a angle. The \a angle must be |
|
2004 specified in degrees between 0 and 360. |
|
2005 |
|
2006 \sa QGradient::setColorAt(), QGradient::setStops() |
|
2007 */ |
|
2008 |
|
2009 QConicalGradient::QConicalGradient(const QPointF ¢er, qreal angle) |
|
2010 { |
|
2011 m_type = ConicalGradient; |
|
2012 m_spread = PadSpread; |
|
2013 m_data.conical.cx = center.x(); |
|
2014 m_data.conical.cy = center.y(); |
|
2015 m_data.conical.angle = angle; |
|
2016 } |
|
2017 |
|
2018 |
|
2019 /*! |
|
2020 Constructs a conical gradient with the given center (\a cx, \a |
|
2021 cy), starting the interpolation at the given \a angle. The angle |
|
2022 must be specified in degrees between 0 and 360. |
|
2023 |
|
2024 \sa QGradient::setColorAt(), QGradient::setStops() |
|
2025 */ |
|
2026 |
|
2027 QConicalGradient::QConicalGradient(qreal cx, qreal cy, qreal angle) |
|
2028 { |
|
2029 m_type = ConicalGradient; |
|
2030 m_spread = PadSpread; |
|
2031 m_data.conical.cx = cx; |
|
2032 m_data.conical.cy = cy; |
|
2033 m_data.conical.angle = angle; |
|
2034 } |
|
2035 |
|
2036 |
|
2037 /*! |
|
2038 Constructs a conical with center at (0, 0) starting the |
|
2039 interpolation at angle 0. |
|
2040 |
|
2041 \sa QGradient::setColorAt(), setCenter(), setAngle() |
|
2042 */ |
|
2043 |
|
2044 QConicalGradient::QConicalGradient() |
|
2045 { |
|
2046 m_type = ConicalGradient; |
|
2047 m_spread = PadSpread; |
|
2048 m_data.conical.cx = 0; |
|
2049 m_data.conical.cy = 0; |
|
2050 m_data.conical.angle = 0; |
|
2051 } |
|
2052 |
|
2053 |
|
2054 /*! |
|
2055 Returns the center of the conical gradient in logical |
|
2056 coordinates. |
|
2057 |
|
2058 \sa stops() |
|
2059 */ |
|
2060 |
|
2061 QPointF QConicalGradient::center() const |
|
2062 { |
|
2063 Q_ASSERT(m_type == ConicalGradient); |
|
2064 return QPointF(m_data.conical.cx, m_data.conical.cy); |
|
2065 } |
|
2066 |
|
2067 |
|
2068 /*! |
|
2069 \fn void QConicalGradient::setCenter(qreal x, qreal y) |
|
2070 |
|
2071 \overload |
|
2072 |
|
2073 Sets the center of this conical gradient in logical coordinates to |
|
2074 (\a x, \a y). |
|
2075 |
|
2076 \sa center() |
|
2077 */ |
|
2078 |
|
2079 /*! |
|
2080 Sets the center of this conical gradient in logical coordinates to |
|
2081 \a center. |
|
2082 |
|
2083 \sa center() |
|
2084 */ |
|
2085 |
|
2086 void QConicalGradient::setCenter(const QPointF ¢er) |
|
2087 { |
|
2088 Q_ASSERT(m_type == ConicalGradient); |
|
2089 m_data.conical.cx = center.x(); |
|
2090 m_data.conical.cy = center.y(); |
|
2091 } |
|
2092 |
|
2093 /*! |
|
2094 Returns the start angle of the conical gradient in logical |
|
2095 coordinates. |
|
2096 |
|
2097 \sa stops() |
|
2098 */ |
|
2099 |
|
2100 qreal QConicalGradient::angle() const |
|
2101 { |
|
2102 Q_ASSERT(m_type == ConicalGradient); |
|
2103 return m_data.conical.angle; |
|
2104 } |
|
2105 |
|
2106 |
|
2107 /*! |
|
2108 \since 4.2 |
|
2109 |
|
2110 Sets \a angle to be the start angle for this conical gradient in |
|
2111 logical coordinates. |
|
2112 |
|
2113 \sa angle() |
|
2114 */ |
|
2115 |
|
2116 void QConicalGradient::setAngle(qreal angle) |
|
2117 { |
|
2118 Q_ASSERT(m_type == ConicalGradient); |
|
2119 m_data.conical.angle = angle; |
|
2120 } |
|
2121 |
|
2122 /*! |
|
2123 \typedef QGradientStop |
|
2124 \relates QGradient |
|
2125 |
|
2126 Typedef for QPair<\l qreal, QColor>. |
|
2127 */ |
|
2128 |
|
2129 /*! |
|
2130 \typedef QGradientStops |
|
2131 \relates QGradient |
|
2132 |
|
2133 Typedef for QVector<QGradientStop>. |
|
2134 */ |
|
2135 |
|
2136 /*! |
|
2137 \typedef QBrush::DataPtr |
|
2138 \internal |
|
2139 */ |
|
2140 |
|
2141 /*! |
|
2142 \fn DataPtr &QBrush::data_ptr() |
|
2143 \internal |
|
2144 */ |
|
2145 |
|
2146 |
|
2147 /*! |
|
2148 \fn bool QBrush::isDetached() const |
|
2149 \internal |
|
2150 */ |
|
2151 |
|
2152 /*! |
|
2153 \fn QTransform QBrush::transform() const |
|
2154 \since 4.3 |
|
2155 |
|
2156 Returns the current transformation matrix for the brush. |
|
2157 |
|
2158 \sa setTransform() |
|
2159 */ |
|
2160 |
|
2161 QT_END_NAMESPACE |