blob: f35d4f330bdb449db166837323a9f020037048e4 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include "qbrush.h"
#include <QPainter>
#include <QBitmap>
#include <private/qpixmap_raster_p.h>
#include <qdebug.h>
class tst_QBrush : public QObject
{
Q_OBJECT
public:
tst_QBrush();
private slots:
void operator_eq_eq();
void operator_eq_eq_data();
void stream();
void stream_data();
void badStyles();
void testQLinearGradientSetters();
void testQRadialGradientSetters();
void testQConicalGradientSetters();
void testQGradientCopyConstructor();
void gradientStops();
void gradientPresets();
void textures();
void swap();
void nullBrush();
void isOpaque();
void debug();
void textureBrushStream();
void textureBrushComparison();
};
tst_QBrush::tst_QBrush()
{
}
void tst_QBrush::operator_eq_eq_data()
{
QTest::addColumn<QBrush>("brush1");
QTest::addColumn<QBrush>("brush2");
QTest::addColumn<bool>("isEqual");
QLinearGradient lg(10, 10, 100, 100);
lg.setColorAt(0, Qt::red);
lg.setColorAt(0.5, Qt::blue);
lg.setColorAt(1, Qt::green);
QTest::newRow("black vs black") << QBrush(Qt::black) << QBrush(Qt::black) << true;
QTest::newRow("black vs blue") << QBrush(Qt::black) << QBrush(Qt::blue) << false;
QTest::newRow("red vs no") << QBrush(Qt::red) << QBrush(Qt::NoBrush) << false;
QTest::newRow("no vs no") << QBrush(Qt::NoBrush) << QBrush(Qt::NoBrush) << true;
QTest::newRow("lg vs same lg") << QBrush(lg) << QBrush(lg) << true;
QTest::newRow("lg vs diff lg") << QBrush(lg) << QBrush(QLinearGradient(QPoint(0, 0), QPoint(1, 1)))
<< false;
QTest::newRow("rad vs con") << QBrush(QRadialGradient(0, 0, 0, 0, 0)) << QBrush(QConicalGradient(0, 0, 0)) << false;
QBrush b1(lg);
QBrush b2(lg);
b1.setTransform(QTransform().scale(2, 2));
QTest::newRow("lg with transform vs same lg") << b1 << b2 << false;
b2.setTransform(QTransform().scale(2, 2));
QTest::newRow("lg w/transform vs same lg w/same transform") << b1 << b2 << true;
}
void tst_QBrush::operator_eq_eq()
{
QFETCH(QBrush, brush1);
QFETCH(QBrush, brush2);
QFETCH(bool, isEqual);
QCOMPARE(brush1 == brush2, isEqual);
}
void tst_QBrush::stream_data()
{
QTest::addColumn<QBrush>("brush");
QLinearGradient lg(10, 10, 100, 100);
lg.setColorAt(0, Qt::red);
lg.setColorAt(0.5, Qt::blue);
lg.setColorAt(1, Qt::green);
QTest::newRow("black") << QBrush(Qt::black);
QTest::newRow("red") << QBrush(Qt::red);
QTest::newRow("no") << QBrush(Qt::NoBrush);
QTest::newRow("lg") << QBrush(lg);
QTest::newRow("rad") << QBrush(QRadialGradient(0, 0, 0, 0, 0));
QTest::newRow("con") << QBrush(QConicalGradient(0, 0, 0));
}
void tst_QBrush::stream()
{
QFETCH(QBrush, brush);
QByteArray data;
{
QDataStream stream(&data, QIODevice::WriteOnly);
stream << brush;
}
QBrush cmp;
{
QDataStream stream(&data, QIODevice::ReadOnly);
stream >> cmp;
}
QCOMPARE(brush.style(), cmp.style());
QCOMPARE(brush.color(), cmp.color());
QCOMPARE(brush, cmp);
}
void tst_QBrush::testQLinearGradientSetters()
{
QLinearGradient lg;
QCOMPARE(lg.start(), QPointF(0, 0));
QCOMPARE(lg.finalStop(), QPointF(1, 1));
lg.setStart(101, 102);
QCOMPARE(lg.start(), QPointF(101, 102));
lg.setStart(QPointF(201, 202));
QCOMPARE(lg.start(), QPointF(201, 202));
lg.setFinalStop(103, 104);
QCOMPARE(lg.finalStop(), QPointF(103, 104));
lg.setFinalStop(QPointF(203, 204));
QCOMPARE(lg.finalStop(), QPointF(203, 204));
}
void tst_QBrush::testQRadialGradientSetters()
{
QRadialGradient rg;
QCOMPARE(rg.radius(), qreal(1.0));
QCOMPARE(rg.center(), QPointF(0, 0));
QCOMPARE(rg.focalPoint(), QPointF(0, 0));
rg.setRadius(100);
QCOMPARE(rg.radius(), qreal(100.0));
rg.setCenter(101, 102);
QCOMPARE(rg.center(), QPointF(101, 102));
rg.setCenter(QPointF(201, 202));
QCOMPARE(rg.center(), QPointF(201, 202));
rg.setFocalPoint(103, 104);
QCOMPARE(rg.focalPoint(), QPointF(103, 104));
rg.setFocalPoint(QPointF(203, 204));
QCOMPARE(rg.focalPoint(), QPointF(203, 204));
}
void tst_QBrush::testQConicalGradientSetters()
{
QConicalGradient cg;
QCOMPARE(cg.angle(), qreal(0.0));
QCOMPARE(cg.center(), QPointF(0, 0));
cg.setAngle(100);
QCOMPARE(cg.angle(), qreal(100.0));
cg.setCenter(102, 103);
QCOMPARE(cg.center(), QPointF(102, 103));
cg.setCenter(QPointF(202, 203));
QCOMPARE(cg.center(), QPointF(202, 203));
}
void tst_QBrush::testQGradientCopyConstructor()
{
{
QLinearGradient lg1(101, 102, 103, 104);
QLinearGradient lg2 = lg1;
QCOMPARE(lg1.start(), lg2.start());
QCOMPARE(lg1.finalStop(), lg2.finalStop());
QGradient g = lg1;
QCOMPARE(((QLinearGradient *) &g)->start(), lg1.start());
QCOMPARE(((QLinearGradient *) &g)->finalStop(), lg1.finalStop());
}
{
QRadialGradient rg1(101, 102, 103, 104, 105);
QRadialGradient rg2 = rg1;
QCOMPARE(rg1.center(), rg2.center());
QCOMPARE(rg1.focalPoint(), rg2.focalPoint());
QCOMPARE(rg1.radius(), rg2.radius());
QGradient g = rg1;
QCOMPARE(((QRadialGradient *) &g)->center(), rg1.center());
QCOMPARE(((QRadialGradient *) &g)->focalPoint(), rg1.focalPoint());
QCOMPARE(((QRadialGradient *) &g)->radius(), rg1.radius());
}
{
QConicalGradient cg1(101, 102, 103);
QConicalGradient cg2 = cg1;
QCOMPARE(cg1.center(), cg2.center());
QCOMPARE(cg1.angle(), cg2.angle());
QGradient g = cg1;
QCOMPARE(((QConicalGradient *) &g)->center(), cg1.center());
QCOMPARE(((QConicalGradient *) &g)->angle(), cg1.angle());
}
}
void tst_QBrush::badStyles()
{
// QBrush(Qt::BrushStyle) constructor
QCOMPARE(QBrush(Qt::LinearGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::RadialGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::ConicalGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::TexturePattern).style(), Qt::NoBrush);
// QBrush(QColor, Qt::BrushStyle) constructor
QCOMPARE(QBrush(QColor(0, 0, 0), Qt::LinearGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(QColor(0, 0, 0), Qt::RadialGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(QColor(0, 0, 0), Qt::ConicalGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(QColor(0, 0, 0), Qt::TexturePattern).style(), Qt::NoBrush);
// QBrush(Qt::GlobalColor, Qt::BrushStyle) constructor
QCOMPARE(QBrush(Qt::black, Qt::LinearGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::black, Qt::RadialGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::black, Qt::ConicalGradientPattern).style(), Qt::NoBrush);
QCOMPARE(QBrush(Qt::black, Qt::TexturePattern).style(), Qt::NoBrush);
// Set style...
QBrush brush(Qt::red);
brush.setStyle(Qt::LinearGradientPattern);
QCOMPARE(brush.style(), Qt::SolidPattern);
brush.setStyle(Qt::RadialGradientPattern);
QCOMPARE(brush.style(), Qt::SolidPattern);
brush.setStyle(Qt::ConicalGradientPattern);
QCOMPARE(brush.style(), Qt::SolidPattern);
brush.setStyle(Qt::TexturePattern);
QCOMPARE(brush.style(), Qt::SolidPattern);
}
void tst_QBrush::gradientStops()
{
QLinearGradient gradient;
gradient.setColorAt(0, Qt::red);
gradient.setColorAt(1, Qt::blue);
QCOMPARE(gradient.stops().size(), 2);
QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::red)));
QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::blue)));
gradient.setColorAt(0, Qt::blue);
gradient.setColorAt(1, Qt::red);
QCOMPARE(gradient.stops().size(), 2);
QCOMPARE(gradient.stops().at(0), QGradientStop(0, QColor(Qt::blue)));
QCOMPARE(gradient.stops().at(1), QGradientStop(1, QColor(Qt::red)));
gradient.setColorAt(0.5, Qt::green);
QCOMPARE(gradient.stops().size(), 3);
QCOMPARE(gradient.stops().at(1), QGradientStop(0.5, QColor(Qt::green)));
// A hack in parseStopNode() in qsvghandler.cpp depends on inserting stops at NaN.
gradient.setStops(QGradientStops() << QGradientStop(qQNaN(), QColor()));
QCOMPARE(gradient.stops().size(), 1);
QVERIFY(qIsNaN(gradient.stops().at(0).first));
QCOMPARE(gradient.stops().at(0).second, QColor());
}
void tst_QBrush::gradientPresets()
{
QGradient gradient(QGradient::WarmFlame);
QCOMPARE(gradient.type(), QGradient::LinearGradient);
QCOMPARE(gradient.coordinateMode(), QGradient::ObjectMode);
QLinearGradient *lg = static_cast<QLinearGradient *>(&gradient);
QCOMPARE(lg->start(), QPointF(0, 1));
QCOMPARE(lg->finalStop(), QPointF(1, 0));
QCOMPARE(lg->stops().size(), 3);
QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1String("#ff9a9e"))));
QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1String("#fad0c4"))));
QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1String("#fad0c4"))));
QGradient invalidPreset(QGradient::Preset(-1));
QCOMPARE(invalidPreset.type(), QGradient::NoGradient);
QBrush brush(invalidPreset);
QCOMPARE(brush.style(), Qt::NoBrush);
}
void fill(QPaintDevice *pd) {
QPainter p(pd);
int w = pd->width();
int h = pd->height();
p.fillRect(0, 0, w, h, Qt::white);
p.fillRect(0, 0, w/3, h/3, Qt::black);
}
void tst_QBrush::textures()
{
QPixmap pixmap_source(10, 10);
QImage image_source(10, 10, QImage::Format_RGB32);
fill(&pixmap_source);
fill(&image_source);
// Create a pixmap brush and compare its texture and textureImage
// to the expected image
QBrush pixmap_brush;
pixmap_brush.setTexture(pixmap_source);
QImage image = pixmap_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
image = pixmap_brush.textureImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
pixmap_brush = QBrush(pixmap_source);
image = pixmap_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
image = pixmap_brush.textureImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
// Create a image brush and compare its texture and textureImage
// to the expected image
QBrush image_brush;
image_brush.setTextureImage(image_source);
image = image_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
QCOMPARE(image_brush.textureImage(), image_source);
image_brush = QBrush(image_source);
image = image_brush.texture().toImage().convertToFormat(QImage::Format_RGB32);
QCOMPARE(image, image_source);
QCOMPARE(image_brush.textureImage(), image_source);
}
void tst_QBrush::swap()
{
QBrush b1(Qt::black), b2(Qt::white);
b1.swap(b2);
QCOMPARE(b1.color(), QColor(Qt::white));
QCOMPARE(b2.color(), QColor(Qt::black));
}
void tst_QBrush::nullBrush()
{
QBrush brush(QColor(100,0,0), Qt::NoBrush);
QCOMPARE(brush.color(), QColor(100,0,0));
}
void tst_QBrush::isOpaque()
{
QBitmap bm(8, 8);
bm.fill(Qt::black);
QBrush brush(bm);
QVERIFY(!brush.isOpaque());
}
void tst_QBrush::debug()
{
QPixmap pixmap_source(10, 10);
fill(&pixmap_source);
QBrush pixmap_brush;
pixmap_brush.setTexture(pixmap_source);
QCOMPARE(pixmap_brush.style(), Qt::TexturePattern);
qDebug() << pixmap_brush; // don't crash
}
void tst_QBrush::textureBrushStream()
{
QPixmap pixmap_source(10, 10);
QImage image_source(10, 10, QImage::Format_RGB32);
fill(&pixmap_source);
fill(&image_source);
QBrush pixmap_brush;
pixmap_brush.setTexture(pixmap_source);
QBrush image_brush;
image_brush.setTextureImage(image_source);
QByteArray data1;
QByteArray data2;
{
QDataStream stream1(&data1, QIODevice::WriteOnly);
QDataStream stream2(&data2, QIODevice::WriteOnly);
stream1 << pixmap_brush;
stream2 << image_brush;
}
QBrush loadedBrush1;
QBrush loadedBrush2;
{
QDataStream stream1(&data1, QIODevice::ReadOnly);
QDataStream stream2(&data2, QIODevice::ReadOnly);
stream1 >> loadedBrush1;
stream2 >> loadedBrush2;
}
QCOMPARE(loadedBrush1.style(), Qt::TexturePattern);
QCOMPARE(loadedBrush2.style(), Qt::TexturePattern);
#ifdef Q_OS_ANDROID
QEXPECT_FAIL("", "QTBUG-69193", Continue);
#endif
QCOMPARE(loadedBrush1.texture(), pixmap_source);
QCOMPARE(loadedBrush2.textureImage(), image_source);
}
void tst_QBrush::textureBrushComparison()
{
QImage image1(10, 10, QImage::Format_RGB32);
QRasterPlatformPixmap* ppixmap = new QRasterPlatformPixmap(QPlatformPixmap::PixmapType);
ppixmap->fromImage(image1, Qt::NoFormatConversion);
QPixmap pixmap(ppixmap);
QImage image2(image1);
QBrush pixmapBrush, imageBrush1, imageBrush2;
pixmapBrush.setTexture(pixmap);
imageBrush1.setTextureImage(image1);
imageBrush2.setTextureImage(image2);
QCOMPARE(imageBrush1, imageBrush2);
QCOMPARE(pixmapBrush, imageBrush1);
}
QTEST_MAIN(tst_QBrush)
#include "tst_qbrush.moc"