1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#include "qbrush.h"
33#include <QPainter>
34#include <QBitmap>
35#include <private/qpixmap_raster_p.h>
36
37#include <qdebug.h>
38
39class tst_QBrush : public QObject
40{
41 Q_OBJECT
42
43public:
44 tst_QBrush();
45
46private slots:
47 void operator_eq_eq();
48 void operator_eq_eq_data();
49
50 void stream();
51 void stream_data();
52
53 void badStyles();
54
55 void testQLinearGradientSetters();
56 void testQRadialGradientSetters();
57 void testQConicalGradientSetters();
58 void testQGradientCopyConstructor();
59
60 void gradientStops();
61 void gradientPresets();
62
63 void textures();
64
65 void swap();
66 void nullBrush();
67 void isOpaque();
68 void debug();
69
70 void textureBrushStream();
71 void textureBrushComparison();
72};
73
74
75tst_QBrush::tst_QBrush()
76{
77}
78
79void tst_QBrush::operator_eq_eq_data()
80{
81 QTest::addColumn<QBrush>(name: "brush1");
82 QTest::addColumn<QBrush>(name: "brush2");
83 QTest::addColumn<bool>(name: "isEqual");
84
85 QLinearGradient lg(10, 10, 100, 100);
86 lg.setColorAt(pos: 0, color: Qt::red);
87 lg.setColorAt(pos: 0.5, color: Qt::blue);
88 lg.setColorAt(pos: 1, color: Qt::green);
89
90 QTest::newRow(dataTag: "black vs black") << QBrush(Qt::black) << QBrush(Qt::black) << true;
91 QTest::newRow(dataTag: "black vs blue") << QBrush(Qt::black) << QBrush(Qt::blue) << false;
92
93 QTest::newRow(dataTag: "red vs no") << QBrush(Qt::red) << QBrush(Qt::NoBrush) << false;
94 QTest::newRow(dataTag: "no vs no") << QBrush(Qt::NoBrush) << QBrush(Qt::NoBrush) << true;
95
96 QTest::newRow(dataTag: "lg vs same lg") << QBrush(lg) << QBrush(lg) << true;
97 QTest::newRow(dataTag: "lg vs diff lg") << QBrush(lg) << QBrush(QLinearGradient(QPoint(0, 0), QPoint(1, 1)))
98 << false;
99
100 QTest::newRow(dataTag: "rad vs con") << QBrush(QRadialGradient(0, 0, 0, 0, 0)) << QBrush(QConicalGradient(0, 0, 0)) << false;
101
102 QBrush b1(lg);
103 QBrush b2(lg);
104 b1.setTransform(QTransform().scale(sx: 2, sy: 2));
105 QTest::newRow(dataTag: "lg with transform vs same lg") << b1 << b2 << false;
106
107 b2.setTransform(QTransform().scale(sx: 2, sy: 2));
108 QTest::newRow(dataTag: "lg w/transform vs same lg w/same transform") << b1 << b2 << true;
109
110}
111
112void tst_QBrush::operator_eq_eq()
113{
114 QFETCH(QBrush, brush1);
115 QFETCH(QBrush, brush2);
116 QFETCH(bool, isEqual);
117 QCOMPARE(brush1 == brush2, isEqual);
118}
119
120void tst_QBrush::stream_data()
121{
122 QTest::addColumn<QBrush>(name: "brush");
123
124 QLinearGradient lg(10, 10, 100, 100);
125 lg.setColorAt(pos: 0, color: Qt::red);
126 lg.setColorAt(pos: 0.5, color: Qt::blue);
127 lg.setColorAt(pos: 1, color: Qt::green);
128
129 QTest::newRow(dataTag: "black") << QBrush(Qt::black);
130 QTest::newRow(dataTag: "red") << QBrush(Qt::red);
131 QTest::newRow(dataTag: "no") << QBrush(Qt::NoBrush);
132 QTest::newRow(dataTag: "lg") << QBrush(lg);
133 QTest::newRow(dataTag: "rad") << QBrush(QRadialGradient(0, 0, 0, 0, 0));
134 QTest::newRow(dataTag: "con") << QBrush(QConicalGradient(0, 0, 0));
135}
136
137void tst_QBrush::stream()
138{
139 QFETCH(QBrush, brush);
140
141 QByteArray data;
142
143 {
144 QDataStream stream(&data, QIODevice::WriteOnly);
145 stream << brush;
146 }
147
148 QBrush cmp;
149 {
150 QDataStream stream(&data, QIODevice::ReadOnly);
151 stream >> cmp;
152 }
153
154 QCOMPARE(brush.style(), cmp.style());
155 QCOMPARE(brush.color(), cmp.color());
156 QCOMPARE(brush, cmp);
157}
158
159void tst_QBrush::testQLinearGradientSetters()
160{
161 QLinearGradient lg;
162
163 QCOMPARE(lg.start(), QPointF(0, 0));
164 QCOMPARE(lg.finalStop(), QPointF(1, 1));
165
166 lg.setStart(x: 101, y: 102);
167 QCOMPARE(lg.start(), QPointF(101, 102));
168
169 lg.setStart(QPointF(201, 202));
170 QCOMPARE(lg.start(), QPointF(201, 202));
171
172 lg.setFinalStop(x: 103, y: 104);
173 QCOMPARE(lg.finalStop(), QPointF(103, 104));
174
175 lg.setFinalStop(QPointF(203, 204));
176 QCOMPARE(lg.finalStop(), QPointF(203, 204));
177}
178
179void tst_QBrush::testQRadialGradientSetters()
180{
181 QRadialGradient rg;
182
183 QCOMPARE(rg.radius(), qreal(1.0));
184 QCOMPARE(rg.center(), QPointF(0, 0));
185 QCOMPARE(rg.focalPoint(), QPointF(0, 0));
186
187 rg.setRadius(100);
188 QCOMPARE(rg.radius(), qreal(100.0));
189
190 rg.setCenter(x: 101, y: 102);
191 QCOMPARE(rg.center(), QPointF(101, 102));
192
193 rg.setCenter(QPointF(201, 202));
194 QCOMPARE(rg.center(), QPointF(201, 202));
195
196 rg.setFocalPoint(x: 103, y: 104);
197 QCOMPARE(rg.focalPoint(), QPointF(103, 104));
198
199 rg.setFocalPoint(QPointF(203, 204));
200 QCOMPARE(rg.focalPoint(), QPointF(203, 204));
201}
202
203void tst_QBrush::testQConicalGradientSetters()
204{
205 QConicalGradient cg;
206
207 QCOMPARE(cg.angle(), qreal(0.0));
208 QCOMPARE(cg.center(), QPointF(0, 0));
209
210 cg.setAngle(100);
211 QCOMPARE(cg.angle(), qreal(100.0));
212
213 cg.setCenter(x: 102, y: 103);
214 QCOMPARE(cg.center(), QPointF(102, 103));
215
216 cg.setCenter(QPointF(202, 203));
217 QCOMPARE(cg.center(), QPointF(202, 203));
218}
219
220void tst_QBrush::testQGradientCopyConstructor()
221{
222 {
223 QLinearGradient lg1(101, 102, 103, 104);
224
225 QLinearGradient lg2 = lg1;
226 QCOMPARE(lg1.start(), lg2.start());
227 QCOMPARE(lg1.finalStop(), lg2.finalStop());
228
229 QGradient g = lg1;
230 QCOMPARE(((QLinearGradient *) &g)->start(), lg1.start());
231 QCOMPARE(((QLinearGradient *) &g)->finalStop(), lg1.finalStop());
232 }
233
234 {
235 QRadialGradient rg1(101, 102, 103, 104, 105);
236
237 QRadialGradient rg2 = rg1;
238 QCOMPARE(rg1.center(), rg2.center());
239 QCOMPARE(rg1.focalPoint(), rg2.focalPoint());
240 QCOMPARE(rg1.radius(), rg2.radius());
241
242 QGradient g = rg1;
243 QCOMPARE(((QRadialGradient *) &g)->center(), rg1.center());
244 QCOMPARE(((QRadialGradient *) &g)->focalPoint(), rg1.focalPoint());
245 QCOMPARE(((QRadialGradient *) &g)->radius(), rg1.radius());
246 }
247
248 {
249 QConicalGradient cg1(101, 102, 103);
250
251 QConicalGradient cg2 = cg1;
252 QCOMPARE(cg1.center(), cg2.center());
253 QCOMPARE(cg1.angle(), cg2.angle());
254
255 QGradient g = cg1;
256 QCOMPARE(((QConicalGradient *) &g)->center(), cg1.center());
257 QCOMPARE(((QConicalGradient *) &g)->angle(), cg1.angle());
258 }
259
260}
261
262void tst_QBrush::badStyles()
263{
264 // QBrush(Qt::BrushStyle) constructor
265 QCOMPARE(QBrush(Qt::LinearGradientPattern).style(), Qt::NoBrush);
266 QCOMPARE(QBrush(Qt::RadialGradientPattern).style(), Qt::NoBrush);
267 QCOMPARE(QBrush(Qt::ConicalGradientPattern).style(), Qt::NoBrush);
268 QCOMPARE(QBrush(Qt::TexturePattern).style(), Qt::NoBrush);
269
270 // QBrush(QColor, Qt::BrushStyle) constructor
271 QCOMPARE(QBrush(QColor(0, 0, 0), Qt::LinearGradientPattern).style(), Qt::NoBrush);
272 QCOMPARE(QBrush(QColor(0, 0, 0), Qt::RadialGradientPattern).style(), Qt::NoBrush);
273 QCOMPARE(QBrush(QColor(0, 0, 0), Qt::ConicalGradientPattern).style(), Qt::NoBrush);
274 QCOMPARE(QBrush(QColor(0, 0, 0), Qt::TexturePattern).style(), Qt::NoBrush);
275
276 // QBrush(Qt::GlobalColor, Qt::BrushStyle) constructor
277 QCOMPARE(QBrush(Qt::black, Qt::LinearGradientPattern).style(), Qt::NoBrush);
278 QCOMPARE(QBrush(Qt::black, Qt::RadialGradientPattern).style(), Qt::NoBrush);
279 QCOMPARE(QBrush(Qt::black, Qt::ConicalGradientPattern).style(), Qt::NoBrush);
280 QCOMPARE(QBrush(Qt::black, Qt::TexturePattern).style(), Qt::NoBrush);
281
282 // Set style...
283 QBrush brush(Qt::red);
284
285 brush.setStyle(Qt::LinearGradientPattern);
286 QCOMPARE(brush.style(), Qt::SolidPattern);
287
288 brush.setStyle(Qt::RadialGradientPattern);
289 QCOMPARE(brush.style(), Qt::SolidPattern);
290
291 brush.setStyle(Qt::ConicalGradientPattern);
292 QCOMPARE(brush.style(), Qt::SolidPattern);
293
294 brush.setStyle(Qt::TexturePattern);
295 QCOMPARE(brush.style(), Qt::SolidPattern);
296
297}
298
299void tst_QBrush::gradientStops()
300{
301 QLinearGradient gradient;
302 gradient.setColorAt(pos: 0, color: Qt::red);
303 gradient.setColorAt(pos: 1, color: Qt::blue);
304
305 QCOMPARE(gradient.stops().size(), 2);
306
307 QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::red)));
308 QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::blue)));
309
310 gradient.setColorAt(pos: 0, color: Qt::blue);
311 gradient.setColorAt(pos: 1, color: Qt::red);
312
313 QCOMPARE(gradient.stops().size(), 2);
314
315 QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::blue)));
316 QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::red)));
317
318 gradient.setColorAt(pos: 0.5, color: Qt::green);
319
320 QCOMPARE(gradient.stops().size(), 3);
321 QCOMPARE(gradient.stops().at(1), QGradientStop(0.5, QColor(Qt::green)));
322
323 // A hack in parseStopNode() in qsvghandler.cpp depends on inserting stops at NaN.
324 gradient.setStops(QGradientStops() << QGradientStop(qQNaN(), QColor()));
325 QCOMPARE(gradient.stops().size(), 1);
326 QVERIFY(qIsNaN(gradient.stops().at(0).first));
327 QCOMPARE(gradient.stops().at(0).second, QColor());
328}
329
330void tst_QBrush::gradientPresets()
331{
332 QGradient gradient(QGradient::WarmFlame);
333 QCOMPARE(gradient.type(), QGradient::LinearGradient);
334 QCOMPARE(gradient.coordinateMode(), QGradient::ObjectMode);
335
336 QLinearGradient *lg = static_cast<QLinearGradient *>(&gradient);
337 QCOMPARE(lg->start(), QPointF(0, 1));
338 QCOMPARE(lg->finalStop(), QPointF(1, 0));
339
340 QCOMPARE(lg->stops().size(), 3);
341 QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e"))));
342 QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4"))));
343 QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4"))));
344
345
346 QGradient invalidPreset(QGradient::Preset(-1));
347 QCOMPARE(invalidPreset.type(), QGradient::NoGradient);
348 QBrush brush(invalidPreset);
349 QCOMPARE(brush.style(), Qt::NoBrush);
350}
351
352void fill(QPaintDevice *pd) {
353 QPainter p(pd);
354
355 int w = pd->width();
356 int h = pd->height();
357
358 p.fillRect(x: 0, y: 0, w, h, c: Qt::white);
359 p.fillRect(x: 0, y: 0, w: w/3, h: h/3, c: Qt::black);
360}
361
362void tst_QBrush::textures()
363{
364 QPixmap pixmap_source(10, 10);
365 QImage image_source(10, 10, QImage::Format_RGB32);
366
367 fill(pd: &pixmap_source);
368 fill(pd: &image_source);
369
370 // Create a pixmap brush and compare its texture and textureImage
371 // to the expected image
372 QBrush pixmap_brush;
373 pixmap_brush.setTexture(pixmap_source);
374 QImage image = pixmap_brush.texture().toImage().convertToFormat(f: QImage::Format_RGB32);
375 QCOMPARE(image, image_source);
376 image = pixmap_brush.textureImage().convertToFormat(f: QImage::Format_RGB32);
377 QCOMPARE(image, image_source);
378
379 pixmap_brush = QBrush(pixmap_source);
380 image = pixmap_brush.texture().toImage().convertToFormat(f: QImage::Format_RGB32);
381 QCOMPARE(image, image_source);
382 image = pixmap_brush.textureImage().convertToFormat(f: QImage::Format_RGB32);
383 QCOMPARE(image, image_source);
384
385 // Create a image brush and compare its texture and textureImage
386 // to the expected image
387 QBrush image_brush;
388 image_brush.setTextureImage(image_source);
389 image = image_brush.texture().toImage().convertToFormat(f: QImage::Format_RGB32);
390 QCOMPARE(image, image_source);
391 QCOMPARE(image_brush.textureImage(), image_source);
392
393 image_brush = QBrush(image_source);
394 image = image_brush.texture().toImage().convertToFormat(f: QImage::Format_RGB32);
395 QCOMPARE(image, image_source);
396 QCOMPARE(image_brush.textureImage(), image_source);
397}
398
399void tst_QBrush::swap()
400{
401 QBrush b1(Qt::black), b2(Qt::white);
402 b1.swap(other&: b2);
403 QCOMPARE(b1.color(), QColor(Qt::white));
404 QCOMPARE(b2.color(), QColor(Qt::black));
405}
406
407void tst_QBrush::nullBrush()
408{
409 QBrush brush(QColor(100,0,0), Qt::NoBrush);
410 QCOMPARE(brush.color(), QColor(100,0,0));
411}
412
413void tst_QBrush::isOpaque()
414{
415 QBitmap bm(8, 8);
416 bm.fill(fillColor: Qt::black);
417
418 QBrush brush(bm);
419 QVERIFY(!brush.isOpaque());
420}
421
422void tst_QBrush::debug()
423{
424 QPixmap pixmap_source(10, 10);
425 fill(pd: &pixmap_source);
426 QBrush pixmap_brush;
427 pixmap_brush.setTexture(pixmap_source);
428 QCOMPARE(pixmap_brush.style(), Qt::TexturePattern);
429 qDebug() << pixmap_brush; // don't crash
430}
431
432void tst_QBrush::textureBrushStream()
433{
434 QPixmap pixmap_source(10, 10);
435 QImage image_source(10, 10, QImage::Format_RGB32);
436
437 fill(pd: &pixmap_source);
438 fill(pd: &image_source);
439
440 QBrush pixmap_brush;
441 pixmap_brush.setTexture(pixmap_source);
442 QBrush image_brush;
443 image_brush.setTextureImage(image_source);
444
445 QByteArray data1;
446 QByteArray data2;
447 {
448 QDataStream stream1(&data1, QIODevice::WriteOnly);
449 QDataStream stream2(&data2, QIODevice::WriteOnly);
450 stream1 << pixmap_brush;
451 stream2 << image_brush;
452 }
453
454 QBrush loadedBrush1;
455 QBrush loadedBrush2;
456 {
457 QDataStream stream1(&data1, QIODevice::ReadOnly);
458 QDataStream stream2(&data2, QIODevice::ReadOnly);
459 stream1 >> loadedBrush1;
460 stream2 >> loadedBrush2;
461 }
462
463 QCOMPARE(loadedBrush1.style(), Qt::TexturePattern);
464 QCOMPARE(loadedBrush2.style(), Qt::TexturePattern);
465#ifdef Q_OS_ANDROID
466 QEXPECT_FAIL("", "QTBUG-69193", Continue);
467#endif
468 QCOMPARE(loadedBrush1.texture(), pixmap_source);
469 QCOMPARE(loadedBrush2.textureImage(), image_source);
470}
471
472void tst_QBrush::textureBrushComparison()
473{
474 QImage image1(10, 10, QImage::Format_RGB32);
475 QRasterPlatformPixmap* ppixmap = new QRasterPlatformPixmap(QPlatformPixmap::PixmapType);
476 ppixmap->fromImage(image: image1, flags: Qt::NoFormatConversion);
477 QPixmap pixmap(ppixmap);
478 QImage image2(image1);
479
480 QBrush pixmapBrush, imageBrush1, imageBrush2;
481 pixmapBrush.setTexture(pixmap);
482 imageBrush1.setTextureImage(image1);
483 imageBrush2.setTextureImage(image2);
484
485 QCOMPARE(imageBrush1, imageBrush2);
486 QCOMPARE(pixmapBrush, imageBrush1);
487}
488
489QTEST_MAIN(tst_QBrush)
490#include "tst_qbrush.moc"
491

source code of qtbase/tests/auto/gui/painting/qbrush/tst_qbrush.cpp