diff options
author | Jo Asplin <jo.asplin@nokia.com> | 2011-08-31 17:11:06 +0200 |
---|---|---|
committer | Jo Asplin <jo.asplin@nokia.com> | 2011-09-01 10:59:49 +0200 |
commit | a90f50942e5304e6bf1c8a3e32f1f65c7a38f60b (patch) | |
tree | 6ed9a3d0a0a3dd09a78593d89c000f29d3494b89 /tests/auto/gui/painting | |
parent | a863eb1c7bbd5d40a741151f811bd7c62cf51e2d (diff) |
Moved gui autotests into new directory structure
Task-number: QTBUG-21133
Change-Id: I83b8f652935cf92151265ca2530a3cf81c31fdef
Reviewed-on: http://codereview.qt.nokia.com/3996
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jo Asplin <jo.asplin@nokia.com>
Diffstat (limited to 'tests/auto/gui/painting')
230 files changed, 15109 insertions, 0 deletions
diff --git a/tests/auto/gui/painting/painting.pro b/tests/auto/gui/painting/painting.pro new file mode 100644 index 0000000000..62230eeac7 --- /dev/null +++ b/tests/auto/gui/painting/painting.pro @@ -0,0 +1,21 @@ +TEMPLATE=subdirs +SUBDIRS=\ + qpainterpath \ + qpainterpathstroker \ + qcolor \ + qbrush \ + qregion \ + qpainter \ + qpathclipper \ + qprinterinfo \ + qpen \ + qpaintengine \ + qtransform \ + qwmatrix \ + qprinter \ + qpolygon \ + +!contains(QT_CONFIG, private_tests): SUBDIRS -= \ + qpathclipper \ + + diff --git a/tests/auto/gui/painting/qbrush/.gitignore b/tests/auto/gui/painting/qbrush/.gitignore new file mode 100644 index 0000000000..e9321a18bd --- /dev/null +++ b/tests/auto/gui/painting/qbrush/.gitignore @@ -0,0 +1 @@ +tst_qbrush diff --git a/tests/auto/gui/painting/qbrush/qbrush.pro b/tests/auto/gui/painting/qbrush/qbrush.pro new file mode 100644 index 0000000000..1c3efd46be --- /dev/null +++ b/tests/auto/gui/painting/qbrush/qbrush.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qbrush.cpp diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp new file mode 100644 index 0000000000..9ee679e0f7 --- /dev/null +++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp @@ -0,0 +1,423 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include "qbrush.h" +#include <QPainter> +#include <QBitmap> + +#include <qdebug.h> + +//TESTED_CLASS= +//TESTED_FILES= + +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 textures(); + + void swap(); + void nullBrush(); + void isOpaque(); + void debug(); +}; + +Q_DECLARE_METATYPE(QBrush) + +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 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 +} + +QTEST_MAIN(tst_QBrush) +#include "tst_qbrush.moc" diff --git a/tests/auto/gui/painting/qcolor/.gitignore b/tests/auto/gui/painting/qcolor/.gitignore new file mode 100644 index 0000000000..92f91eb54e --- /dev/null +++ b/tests/auto/gui/painting/qcolor/.gitignore @@ -0,0 +1 @@ +tst_qcolor diff --git a/tests/auto/gui/painting/qcolor/qcolor.pro b/tests/auto/gui/painting/qcolor/qcolor.pro new file mode 100644 index 0000000000..b9d437ef7c --- /dev/null +++ b/tests/auto/gui/painting/qcolor/qcolor.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_qcolor.cpp + + + diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp new file mode 100644 index 0000000000..2b6896ae5d --- /dev/null +++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp @@ -0,0 +1,1538 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <limits.h> + +#include <qcolor.h> +#include <qdebug.h> + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QColor : public QObject +{ + Q_OBJECT + +public: + tst_QColor(); + +private slots: + void getSetCheck(); + void isValid_data(); + void isValid(); + + void name_data(); + void name(); + void setNamedColor(); + + void constructNamedColorWithSpace(); + + void colorNames(); + + void spec(); + + void globalColors_data(); + void globalColors(); + + void alpha(); + void setAlpha(); + + void red(); + void green(); + void blue(); + + void setRed(); + void setGreen(); + void setBlue(); + + void getRgb(); + void setRgb(); + + void rgba(); + void setRgba(); + + void rgb(); + + void hue(); + void saturation(); + void value(); + + void getHsv(); + void setHsv(); + + void cyan(); + void magenta(); + void yellow(); + void black(); + + void getCmyk(); + void setCmyk(); + + void hueHsl(); + void saturationHsl(); + void lightness(); + + void getHsl(); + void setHsl(); + + void toRgb_data(); + void toRgb(); + void toRgbNonDestructive(); + + void toHsv_data(); + void toHsv(); + void toHsvNonDestructive(); + + void toCmyk_data(); + void toCmyk(); + void toCmykNonDestructive(); + + void toHsl_data(); + void toHsl();; + void toHslNonDestructive(); + + void convertTo(); + + void fromRgb(); + void fromHsv(); + void fromCmyk(); + void fromHsl(); + + void light(); + void dark(); + + void assignmentOoperator(); + void equalityOperator(); + + void specConstructor_data(); + void specConstructor(); + + void achromaticHslHue(); + +#ifdef Q_WS_X11 + void allowX11ColorNames(); + void setallowX11ColorNames(); +#endif +}; + +// Testing get/set functions +void tst_QColor::getSetCheck() +{ + QColor obj1; + // int QColor::alpha() + // void QColor::setAlpha(int) + obj1.setAlpha(0); + QCOMPARE(obj1.alpha(), 0); + obj1.setAlpha(-1); + QCOMPARE(obj1.alpha(), 0); // range<0, 255> + obj1.setAlpha(INT_MIN); + QCOMPARE(obj1.alpha(), 0); // range<0, 255> + obj1.setAlpha(255); + QCOMPARE(obj1.alpha(), 255); // range<0, 255> + obj1.setAlpha(INT_MAX); + QCOMPARE(obj1.alpha(), 255); // range<0, 255> + + // qreal QColor::alphaF() + // void QColor::setAlphaF(qreal) + obj1.setAlphaF(0.0); + QCOMPARE(obj1.alphaF(), qreal(0.0)); // range<0.0, 1.0> + obj1.setAlphaF(-0.2); + QCOMPARE(obj1.alphaF(), qreal(0.0)); // range<0.0, 1.0> + obj1.setAlphaF(1.0); + QCOMPARE(obj1.alphaF(), qreal(1.0)); // range<0.0, 1.0> + obj1.setAlphaF(1.1); + QCOMPARE(obj1.alphaF(), qreal(1.0)); // range<0.0, 1.0> + + // int QColor::red() + // void QColor::setRed(int) + obj1.setRed(0); + QCOMPARE(obj1.red(), 0); + obj1.setRed(-1); + QCOMPARE(obj1.red(), 0); // range<0, 255> + obj1.setRed(INT_MIN); + QCOMPARE(obj1.red(), 0); // range<0, 255> + obj1.setRed(255); + QCOMPARE(obj1.red(), 255); // range<0, 255> + obj1.setRed(INT_MAX); + QCOMPARE(obj1.red(), 255); // range<0, 255> + + // int QColor::green() + // void QColor::setGreen(int) + obj1.setGreen(0); + QCOMPARE(obj1.green(), 0); + obj1.setGreen(-1); + QCOMPARE(obj1.green(), 0); // range<0, 255> + obj1.setGreen(INT_MIN); + QCOMPARE(obj1.green(), 0); // range<0, 255> + obj1.setGreen(255); + QCOMPARE(obj1.green(), 255); // range<0, 255> + obj1.setGreen(INT_MAX); + QCOMPARE(obj1.green(), 255); // range<0, 255> + + // int QColor::blue() + // void QColor::setBlue(int) + obj1.setBlue(0); + QCOMPARE(obj1.blue(), 0); + obj1.setBlue(-1); + QCOMPARE(obj1.blue(), 0); // range<0, 255> + obj1.setBlue(INT_MIN); + QCOMPARE(obj1.blue(), 0); // range<0, 255> + obj1.setBlue(255); + QCOMPARE(obj1.blue(), 255); // range<0, 255> + obj1.setBlue(INT_MAX); + QCOMPARE(obj1.blue(), 255); // range<0, 255> + + // qreal QColor::redF() + // void QColor::setRedF(qreal) + obj1.setRedF(0.0); + QCOMPARE(obj1.redF(), qreal(0.0)); + obj1.setRedF(-0.2); + QCOMPARE(obj1.redF(), qreal(0.0)); // range<0.0, 1.0 + obj1.setRedF(1.1); + QCOMPARE(obj1.redF(), qreal(1.0)); // range<0.0, 1.0 + + // qreal QColor::greenF() + // void QColor::setGreenF(qreal) + obj1.setGreenF(0.0); + QCOMPARE(obj1.greenF(), qreal(0.0)); + obj1.setGreenF(-0.2); + QCOMPARE(obj1.greenF(), qreal(0.0)); // range<0.0, 1.0 + obj1.setGreenF(1.1); + QCOMPARE(obj1.greenF(), qreal(1.0)); // range<0.0, 1.0 + + // qreal QColor::blueF() + // void QColor::setBlueF(qreal) + obj1.setBlueF(0.0); + QCOMPARE(obj1.blueF(), qreal(0.0)); + obj1.setBlueF(-0.2); + QCOMPARE(obj1.blueF(), qreal(0.0)); // range<0.0, 1.0 + obj1.setBlueF(1.1); + QCOMPARE(obj1.blueF(), qreal(1.0)); // range<0.0, 1.0 + + // QRgb QColor::rgba() + // void QColor::setRgba(QRgb) + QRgb var9(qRgba(10, 20, 30, 40)); + obj1.setRgba(var9); + QCOMPARE(obj1.rgba(), var9); + obj1.setRgba(QRgb(0)); + QCOMPARE(obj1.rgba(), QRgb(0)); + + // QRgb QColor::rgb() + // void QColor::setRgb(QRgb) + QRgb var10(qRgb(10, 20, 30)); + obj1.setRgb(var10); + QCOMPARE(obj1.rgb(), var10); + obj1.setRgb(QRgb(0)); + QCOMPARE(obj1.rgb(), qRgb(0, 0, 0)); +} + +Q_DECLARE_METATYPE(QColor) + + +tst_QColor::tst_QColor() + +{ } + +void tst_QColor::isValid_data() +{ + QTest::addColumn<QColor>("color"); + QTest::addColumn<bool>("isValid"); + + QTest::newRow("defaultConstructor") << QColor() << false; + QTest::newRow("rgbConstructor-valid") << QColor(2,5,7) << true; + QTest::newRow("rgbConstructor-invalid") << QColor(2,5,999) << false; + QTest::newRow("nameQStringConstructor-valid") << QColor(QString("#ffffff")) << true; + QTest::newRow("nameQStringConstructor-invalid") << QColor(QString("#ffffgg")) << false; + QTest::newRow("nameQStringConstructor-empty") << QColor(QString("")) << false; + QTest::newRow("nameQStringConstructor-named") << QColor(QString("red")) << true; + QTest::newRow("nameCharConstructor-valid") << QColor("#ffffff") << true; + QTest::newRow("nameCharConstructor-invalid") << QColor("#ffffgg") << false; + QTest::newRow("nameCharConstructor-invalid-2") << QColor("#fffffg") << false; +} + +void tst_QColor::isValid() +{ + QFETCH(QColor, color); + QFETCH(bool, isValid); + QVERIFY(color.isValid() == isValid); +} + +void tst_QColor::name_data() +{ + QTest::addColumn<QColor>("color"); + QTest::addColumn<QString>("name"); + + QTest::newRow("invalid") << QColor() << "#000000"; + QTest::newRow("global color black") << QColor(Qt::black) << "#000000"; + QTest::newRow("global color white") << QColor(Qt::white) << "#ffffff"; + QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << "#808080"; + QTest::newRow("global color gray") << QColor(Qt::gray) << "#a0a0a4"; + QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << "#c0c0c0"; + QTest::newRow("global color red") << QColor(Qt::red) << "#ff0000"; + QTest::newRow("global color green") << QColor(Qt::green) << "#00ff00"; + QTest::newRow("global color blue") << QColor(Qt::blue) << "#0000ff"; + QTest::newRow("global color cyan") << QColor(Qt::cyan) << "#00ffff"; + QTest::newRow("global color magenta") << QColor(Qt::magenta) << "#ff00ff"; + QTest::newRow("global color yellow") << QColor(Qt::yellow) << "#ffff00"; + QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << "#800000"; + QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << "#008000"; + QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << "#000080"; + QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << "#008080"; + QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << "#800080"; + QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << "#808000"; +} + +void tst_QColor::name() +{ + QFETCH(QColor, color); + QFETCH(QString, name); + QCOMPARE(color.name(), name); +} + +void tst_QColor::globalColors_data() +{ + QTest::addColumn<QColor>("color"); + QTest::addColumn<uint>("argb"); + + QTest::newRow("invalid") << QColor() << 0xff000000; + QTest::newRow("global color black") << QColor(Qt::black) << 0xff000000; + QTest::newRow("global color white") << QColor(Qt::white) << 0xffffffff; + QTest::newRow("global color darkGray") << QColor(Qt::darkGray) << 0xff808080; + QTest::newRow("global color gray") << QColor(Qt::gray) << 0xffa0a0a4; + QTest::newRow("global color lightGray") << QColor(Qt::lightGray) << 0xffc0c0c0; + QTest::newRow("global color red") << QColor(Qt::red) << 0xffff0000; + QTest::newRow("global color green") << QColor(Qt::green) << 0xff00ff00; + QTest::newRow("global color blue") << QColor(Qt::blue) << 0xff0000ff; + QTest::newRow("global color cyan") << QColor(Qt::cyan) << 0xff00ffff; + QTest::newRow("global color magenta") << QColor(Qt::magenta) << 0xffff00ff; + QTest::newRow("global color yellow") << QColor(Qt::yellow) << 0xffffff00; + QTest::newRow("global color darkRed") << QColor(Qt::darkRed) << 0xff800000; + QTest::newRow("global color darkGreen") << QColor(Qt::darkGreen) << 0xff008000; + QTest::newRow("global color darkBlue") << QColor(Qt::darkBlue) << 0xff000080; + QTest::newRow("global color darkCyan") << QColor(Qt::darkCyan) << 0xff008080; + QTest::newRow("global color darkMagenta") << QColor(Qt::darkMagenta) << 0xff800080; + QTest::newRow("global color darkYellow") << QColor(Qt::darkYellow) << 0xff808000; + QTest::newRow("global color transparent") << QColor(Qt::transparent) << 0x00000000u; +} + + +void tst_QColor::globalColors() +{ + QFETCH(QColor, color); + QFETCH(uint, argb); + QCOMPARE(color.rgba(), argb); +} + +/* + CSS color names = SVG 1.0 color names + transparent (rgba(0,0,0,0)) +*/ + +#ifdef rgb +# undef rgb +#endif +#define rgb(r,g,b) (0xff000000 | r << 16 | g << 8 | b) + +static const struct RGBData { + const char *name; + uint value; +} rgbTbl[] = { + { "aliceblue", rgb(240, 248, 255) }, + { "antiquewhite", rgb(250, 235, 215) }, + { "aqua", rgb( 0, 255, 255) }, + { "aquamarine", rgb(127, 255, 212) }, + { "azure", rgb(240, 255, 255) }, + { "beige", rgb(245, 245, 220) }, + { "bisque", rgb(255, 228, 196) }, + { "black", rgb( 0, 0, 0) }, + { "blanchedalmond", rgb(255, 235, 205) }, + { "blue", rgb( 0, 0, 255) }, + { "blueviolet", rgb(138, 43, 226) }, + { "brown", rgb(165, 42, 42) }, + { "burlywood", rgb(222, 184, 135) }, + { "cadetblue", rgb( 95, 158, 160) }, + { "chartreuse", rgb(127, 255, 0) }, + { "chocolate", rgb(210, 105, 30) }, + { "coral", rgb(255, 127, 80) }, + { "cornflowerblue", rgb(100, 149, 237) }, + { "cornsilk", rgb(255, 248, 220) }, + { "crimson", rgb(220, 20, 60) }, + { "cyan", rgb( 0, 255, 255) }, + { "darkblue", rgb( 0, 0, 139) }, + { "darkcyan", rgb( 0, 139, 139) }, + { "darkgoldenrod", rgb(184, 134, 11) }, + { "darkgray", rgb(169, 169, 169) }, + { "darkgreen", rgb( 0, 100, 0) }, + { "darkgrey", rgb(169, 169, 169) }, + { "darkkhaki", rgb(189, 183, 107) }, + { "darkmagenta", rgb(139, 0, 139) }, + { "darkolivegreen", rgb( 85, 107, 47) }, + { "darkorange", rgb(255, 140, 0) }, + { "darkorchid", rgb(153, 50, 204) }, + { "darkred", rgb(139, 0, 0) }, + { "darksalmon", rgb(233, 150, 122) }, + { "darkseagreen", rgb(143, 188, 143) }, + { "darkslateblue", rgb( 72, 61, 139) }, + { "darkslategray", rgb( 47, 79, 79) }, + { "darkslategrey", rgb( 47, 79, 79) }, + { "darkturquoise", rgb( 0, 206, 209) }, + { "darkviolet", rgb(148, 0, 211) }, + { "deeppink", rgb(255, 20, 147) }, + { "deepskyblue", rgb( 0, 191, 255) }, + { "dimgray", rgb(105, 105, 105) }, + { "dimgrey", rgb(105, 105, 105) }, + { "dodgerblue", rgb( 30, 144, 255) }, + { "firebrick", rgb(178, 34, 34) }, + { "floralwhite", rgb(255, 250, 240) }, + { "forestgreen", rgb( 34, 139, 34) }, + { "fuchsia", rgb(255, 0, 255) }, + { "gainsboro", rgb(220, 220, 220) }, + { "ghostwhite", rgb(248, 248, 255) }, + { "gold", rgb(255, 215, 0) }, + { "goldenrod", rgb(218, 165, 32) }, + { "gray", rgb(128, 128, 128) }, + { "green", rgb( 0, 128, 0) }, + { "greenyellow", rgb(173, 255, 47) }, + { "grey", rgb(128, 128, 128) }, + { "honeydew", rgb(240, 255, 240) }, + { "hotpink", rgb(255, 105, 180) }, + { "indianred", rgb(205, 92, 92) }, + { "indigo", rgb( 75, 0, 130) }, + { "ivory", rgb(255, 255, 240) }, + { "khaki", rgb(240, 230, 140) }, + { "lavender", rgb(230, 230, 250) }, + { "lavenderblush", rgb(255, 240, 245) }, + { "lawngreen", rgb(124, 252, 0) }, + { "lemonchiffon", rgb(255, 250, 205) }, + { "lightblue", rgb(173, 216, 230) }, + { "lightcoral", rgb(240, 128, 128) }, + { "lightcyan", rgb(224, 255, 255) }, + { "lightgoldenrodyellow", rgb(250, 250, 210) }, + { "lightgray", rgb(211, 211, 211) }, + { "lightgreen", rgb(144, 238, 144) }, + { "lightgrey", rgb(211, 211, 211) }, + { "lightpink", rgb(255, 182, 193) }, + { "lightsalmon", rgb(255, 160, 122) }, + { "lightseagreen", rgb( 32, 178, 170) }, + { "lightskyblue", rgb(135, 206, 250) }, + { "lightslategray", rgb(119, 136, 153) }, + { "lightslategrey", rgb(119, 136, 153) }, + { "lightsteelblue", rgb(176, 196, 222) }, + { "lightyellow", rgb(255, 255, 224) }, + { "lime", rgb( 0, 255, 0) }, + { "limegreen", rgb( 50, 205, 50) }, + { "linen", rgb(250, 240, 230) }, + { "magenta", rgb(255, 0, 255) }, + { "maroon", rgb(128, 0, 0) }, + { "mediumaquamarine", rgb(102, 205, 170) }, + { "mediumblue", rgb( 0, 0, 205) }, + { "mediumorchid", rgb(186, 85, 211) }, + { "mediumpurple", rgb(147, 112, 219) }, + { "mediumseagreen", rgb( 60, 179, 113) }, + { "mediumslateblue", rgb(123, 104, 238) }, + { "mediumspringgreen", rgb( 0, 250, 154) }, + { "mediumturquoise", rgb( 72, 209, 204) }, + { "mediumvioletred", rgb(199, 21, 133) }, + { "midnightblue", rgb( 25, 25, 112) }, + { "mintcream", rgb(245, 255, 250) }, + { "mistyrose", rgb(255, 228, 225) }, + { "moccasin", rgb(255, 228, 181) }, + { "navajowhite", rgb(255, 222, 173) }, + { "navy", rgb( 0, 0, 128) }, + { "oldlace", rgb(253, 245, 230) }, + { "olive", rgb(128, 128, 0) }, + { "olivedrab", rgb(107, 142, 35) }, + { "orange", rgb(255, 165, 0) }, + { "orangered", rgb(255, 69, 0) }, + { "orchid", rgb(218, 112, 214) }, + { "palegoldenrod", rgb(238, 232, 170) }, + { "palegreen", rgb(152, 251, 152) }, + { "paleturquoise", rgb(175, 238, 238) }, + { "palevioletred", rgb(219, 112, 147) }, + { "papayawhip", rgb(255, 239, 213) }, + { "peachpuff", rgb(255, 218, 185) }, + { "peru", rgb(205, 133, 63) }, + { "pink", rgb(255, 192, 203) }, + { "plum", rgb(221, 160, 221) }, + { "powderblue", rgb(176, 224, 230) }, + { "purple", rgb(128, 0, 128) }, + { "red", rgb(255, 0, 0) }, + { "rosybrown", rgb(188, 143, 143) }, + { "royalblue", rgb( 65, 105, 225) }, + { "saddlebrown", rgb(139, 69, 19) }, + { "salmon", rgb(250, 128, 114) }, + { "sandybrown", rgb(244, 164, 96) }, + { "seagreen", rgb( 46, 139, 87) }, + { "seashell", rgb(255, 245, 238) }, + { "sienna", rgb(160, 82, 45) }, + { "silver", rgb(192, 192, 192) }, + { "skyblue", rgb(135, 206, 235) }, + { "slateblue", rgb(106, 90, 205) }, + { "slategray", rgb(112, 128, 144) }, + { "slategrey", rgb(112, 128, 144) }, + { "snow", rgb(255, 250, 250) }, + { "springgreen", rgb( 0, 255, 127) }, + { "steelblue", rgb( 70, 130, 180) }, + { "tan", rgb(210, 180, 140) }, + { "teal", rgb( 0, 128, 128) }, + { "thistle", rgb(216, 191, 216) }, + { "tomato", rgb(255, 99, 71) }, + { "transparent", 0 }, + { "turquoise", rgb( 64, 224, 208) }, + { "violet", rgb(238, 130, 238) }, + { "wheat", rgb(245, 222, 179) }, + { "white", rgb(255, 255, 255) }, + { "whitesmoke", rgb(245, 245, 245) }, + { "yellow", rgb(255, 255, 0) }, + { "yellowgreen", rgb(154, 205, 50) } +}; +static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData); + +#undef rgb + +void tst_QColor::setNamedColor() +{ + for (int i = 0; i < rgbTblSize; ++i) { + QColor color; + color.setNamedColor(QLatin1String(rgbTbl[i].name)); + QColor expected; + expected.setRgba(rgbTbl[i].value); + QCOMPARE(color, expected); + } +} + +void tst_QColor::constructNamedColorWithSpace() +{ + QColor whiteSmoke("white smoke"); + QCOMPARE(whiteSmoke, QColor(245, 245, 245)); +} + +void tst_QColor::colorNames() +{ + DEPENDS_ON("setNamedColor()"); + + QStringList all = QColor::colorNames(); + QCOMPARE(all.size(), rgbTblSize); + for (int i = 0; i < all.size(); ++i) + QCOMPARE(all.at(i), QString::fromLatin1(rgbTbl[i].name)); +} + +void tst_QColor::spec() +{ + QColor invalid; + QCOMPARE(invalid.spec(), QColor::Invalid); + + QColor rgb = QColor::fromRgb(0, 0, 0); + QCOMPARE(rgb.spec(), QColor::Rgb); + + QColor hsv = QColor::fromHsv(0, 0, 0); + QCOMPARE(hsv.spec(), QColor::Hsv); + + QColor cmyk = QColor::fromCmyk(0, 0, 0, 0); + QCOMPARE(cmyk.spec(), QColor::Cmyk); + + QColor hsl = QColor::fromHsl(0, 0, 0, 0); + QCOMPARE(hsl.spec(), QColor::Hsl); + +} + +void tst_QColor::alpha() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::red() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::green() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::blue() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::getRgb() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::setAlpha() +{ DEPENDS_ON(setRgb()); } + +bool veryFuzzyCompare(double a, double b) +{ + return qAbs(a - b) < 0.01; +} + +void tst_QColor::setRed() +{ + DEPENDS_ON(setRgb()); + + QColor c = QColor(Qt::blue).toHsv(); + c.setRed(127); + QCOMPARE(c.red(), 127); + QCOMPARE(c.green(), 0); + QCOMPARE(c.blue(), 255); + + c = QColor(Qt::blue).toHsv(); + c.setRedF(0.5); + QVERIFY(veryFuzzyCompare(c.redF(), 0.5)); + QCOMPARE(c.greenF(), qreal(0.0)); + QCOMPARE(c.blueF(), qreal(1.0)); +} + +void tst_QColor::setGreen() +{ + DEPENDS_ON(setRgb()); + + QColor c = QColor(Qt::blue).toHsv(); + c.setGreen(127); + QCOMPARE(c.red(), 0); + QCOMPARE(c.green(), 127); + QCOMPARE(c.blue(), 255); + + c = QColor(Qt::blue).toHsv(); + c.setGreenF(0.5); + QCOMPARE(c.redF(), qreal(0.0)); + QVERIFY(veryFuzzyCompare(c.greenF(), 0.5)); + QCOMPARE(c.blueF(), qreal(1.0)); +} + +void tst_QColor::setBlue() +{ + DEPENDS_ON(setRgb()); + + QColor c = QColor(Qt::red).toHsv(); + c.setBlue(127); + QCOMPARE(c.red(), 255); + QCOMPARE(c.green(), 0); + QCOMPARE(c.blue(), 127); + + c = QColor(Qt::red).toHsv(); + c.setBlueF(0.5); + QCOMPARE(c.redF(), qreal(1.0)); + QCOMPARE(c.greenF(), qreal(0.0)); + QVERIFY(veryFuzzyCompare(c.blueF(), 0.5)); +} + + +void tst_QColor::setRgb() +{ + QColor color; + + for (int A = 0; A <= USHRT_MAX; ++A) { + { + // 0-255 + int a = A >> 8; + QRgb rgb = qRgba(0, 0, 0, a); + + color.setRgb(0, 0, 0, a); + QCOMPARE(color.alpha(), a); + QCOMPARE(color.rgb(), qRgb(0, 0, 0)); + + color.setRgb(rgb); + QCOMPARE(color.alpha(), 255); + QCOMPARE(color.rgb(), qRgb(0, 0, 0)); + + int r, g, b, a2; + color.setRgb(0, 0, 0, a); + color.getRgb(&r, &g, &b, &a2); + QCOMPARE(a2, a); + + QColor c(0, 0, 0); + c.setAlpha(a); + QCOMPARE(c.alpha(), a); + } + + { + // 0.0-1.0 + qreal a = A / qreal(USHRT_MAX); + color.setRgbF(0.0, 0.0, 0.0, a); + QCOMPARE(color.alphaF(), a); + + qreal r, g, b, a2; + color.getRgbF(&r, &g, &b, &a2); + QCOMPARE(a2, a); + + QColor c(0, 0, 0); + c.setAlphaF(a); + + QCOMPARE(c.alphaF(), a); + } + } + + for (int R = 0; R <= USHRT_MAX; ++R) { + { + // 0-255 + int r = R >> 8; + QRgb rgb = qRgb(r, 0, 0); + + color.setRgb(r, 0, 0); + QCOMPARE(color.red(), r); + QCOMPARE(color.rgb(), rgb); + + color.setRgb(rgb); + QCOMPARE(color.red(), r); + QCOMPARE(color.rgb(), rgb); + + int r2, g, b, a; + color.getRgb(&r2, &g, &b, &a); + QCOMPARE(r2, r); + } + + { + // 0.0-1.0 + qreal r = R / qreal(USHRT_MAX); + color.setRgbF(r, 0.0, 0.0); + QCOMPARE(color.redF(), r); + + qreal r2, g, b, a; + color.getRgbF(&r2, &g, &b, &a); + QCOMPARE(r2, r); + } + } + + for (int G = 0; G <= USHRT_MAX; ++G) { + { + // 0-255 + int g = G >> 8; + QRgb rgb = qRgb(0, g, 0); + + color.setRgb(0, g, 0); + QCOMPARE(color.green(), g); + QCOMPARE(color.rgb(), rgb); + + color.setRgb(rgb); + QCOMPARE(color.green(), g); + QCOMPARE(color.rgb(), rgb); + + int r, g2, b, a; + color.getRgb(&r, &g2, &b, &a); + QCOMPARE(g2, g); + } + + { + // 0.0-1.0 + qreal g = G / qreal(USHRT_MAX); + color.setRgbF(0.0, g, 0.0); + QCOMPARE(color.greenF(), g); + + qreal r, g2, b, a; + color.getRgbF(&r, &g2, &b, &a); + QCOMPARE(g2, g); + } + } + + for (int B = 0; B <= USHRT_MAX; ++B) { + { + // 0-255 + int b = B >> 8; + QRgb rgb = qRgb(0, 0, b); + + color.setRgb(0, 0, b); + QCOMPARE(color.blue(), b); + QCOMPARE(color.rgb(), rgb); + + color.setRgb(rgb); + QCOMPARE(color.blue(), b); + QCOMPARE(color.rgb(), rgb); + + int r, g, b2, a; + color.getRgb(&r, &g, &b2, &a); + QCOMPARE(b2, b); + } + + { + // 0.0-1.0 + qreal b = B / qreal(USHRT_MAX); + color.setRgbF(0.0, 0.0, b); + QCOMPARE(color.blueF(), b); + + qreal r, g, b2, a; + color.getRgbF(&r, &g, &b2, &a); + QCOMPARE(b2, b); + } + } +} + +void tst_QColor::rgba() +{ DEPENDS_ON("setRgba()"); } + +void tst_QColor::setRgba() +{ + for (int a = 0; a < 255; ++a) { + const QRgb rgba1 = qRgba(a, a, a, a); + QColor color; + color.setRgba(rgba1); + QCOMPARE(color.alpha(), a); + const QRgb rgba2 = color.rgba(); + QCOMPARE(rgba2, rgba1); + QCOMPARE(qAlpha(rgba2), a); + } +} + +void tst_QColor::rgb() +{ DEPENDS_ON(setRgb()); } + +void tst_QColor::hue() +{ DEPENDS_ON(setHsv()); } + +void tst_QColor::saturation() +{ DEPENDS_ON(setHsv()); } + +void tst_QColor::value() +{ DEPENDS_ON(setHsv()); } + +void tst_QColor::getHsv() +{ DEPENDS_ON(setHsv()); } + +void tst_QColor::setHsv() +{ + QColor color; + + for (int A = 0; A <= USHRT_MAX; ++A) { + { + // 0-255 + int a = A >> 8; + color.setHsv(0, 0, 0, a); + QCOMPARE(color.alpha(), a); + + int h, s, v, a2; + color.getHsv(&h, &s, &v, &a2); + QCOMPARE(a2, a); + } + + { + // 0.0-1.0 + qreal a = A / qreal(USHRT_MAX); + color.setHsvF(0.0, 0.0, 0.0, a); QCOMPARE(color.alphaF(), a); + + qreal h, s, v, a2; + color.getHsvF(&h, &s, &v, &a2); + QCOMPARE(a2, a); + } + } + + for (int H = 0; H < 36000; ++H) { + { + // 0-255 + int h = H / 100; + + color.setHsv(h, 0, 0, 0); + QCOMPARE(color.hue(), h); + + int h2, s, v, a; + color.getHsv(&h2, &s, &v, &a); + QCOMPARE(h2, h); + } + + { + // 0.0-1.0 + qreal h = H / 36000.0; + color.setHsvF(h, 0.0, 0.0, 0.0); + QCOMPARE(color.hueF(), h); + + qreal h2, s, v, a; + color.getHsvF(&h2, &s, &v, &a); + QCOMPARE(h2, h); + } + } + + for (int S = 0; S <= USHRT_MAX; ++S) { + { + // 0-255 + int s = S >> 8; + color.setHsv(0, s, 0, 0); + QCOMPARE(color.saturation(), s); + + int h, s2, v, a; + color.getHsv(&h, &s2, &v, &a); + QCOMPARE(s2, s); + } + + { + // 0.0-1.0 + qreal s = S / qreal(USHRT_MAX); + color.setHsvF(0.0, s, 0.0, 0.0); + QCOMPARE(color.saturationF(), s); + + qreal h, s2, v, a; + color.getHsvF(&h, &s2, &v, &a); + QCOMPARE(s2, s); + } + } + + for (int V = 0; V <= USHRT_MAX; ++V) { + { + // 0-255 + int v = V >> 8; + color.setHsv(0, 0, v, 0); + QCOMPARE(color.value(), v); + + int h, s, v2, a; + color.getHsv(&h, &s, &v2, &a); + QCOMPARE(v2, v); + } + + { + // 0.0-1.0 + qreal v = V / qreal(USHRT_MAX); + color.setHsvF(0.0, 0.0, v, 0.0); + QCOMPARE(color.valueF(), v); + + qreal h, s, v2, a; + color.getHsvF(&h, &s, &v2, &a); + QCOMPARE(v2, v); + } + } +} + +void tst_QColor::cyan() +{ DEPENDS_ON(setCmyk()); } + +void tst_QColor::magenta() +{ DEPENDS_ON(setCmyk()); } + +void tst_QColor::yellow() +{ DEPENDS_ON(setCmyk()); } + +void tst_QColor::black() +{ DEPENDS_ON(setCmyk()); } + +void tst_QColor::getCmyk() +{ DEPENDS_ON(setCmyk()); } + +void tst_QColor::setCmyk() +{ + QColor color; + + for (int A = 0; A <= USHRT_MAX; ++A) { + { + // 0-255 + int a = A >> 8; + color.setCmyk(0, 0, 0, 0, a); + QCOMPARE(color.alpha(), a); + + int c, m, y, k, a2; + color.getCmyk(&c, &m, &y, &k, &a2); + QCOMPARE(a2, a); + } + + { + // 0.0-1.0 + qreal a = A / qreal(USHRT_MAX); + color.setCmykF(0.0, 0.0, 0.0, 0.0, a); + QCOMPARE(color.alphaF(), a); + + qreal c, m, y, k, a2; + color.getCmykF(&c, &m, &y, &k, &a2); + QCOMPARE(a2, a); + } + } + + for (int C = 0; C <= USHRT_MAX; ++C) { + { + // 0-255 + int c = C >> 8; + color.setCmyk(c, 0, 0, 0, 0); + QCOMPARE(color.cyan(), c); + + int c2, m, y, k, a; + color.getCmyk(&c2, &m, &y, &k, &a); + QCOMPARE(c2, c); + } + + { + // 0.0-1.0 + qreal c = C / qreal(USHRT_MAX); + color.setCmykF(c, 0.0, 0.0, 0.0, 0.0); + QCOMPARE(color.cyanF(), c); + + qreal c2, m, y, k, a; + color.getCmykF(&c2, &m, &y, &k, &a); + QCOMPARE(c2, c); + } + } + + for (int M = 0; M <= USHRT_MAX; ++M) { + { + // 0-255 + int m = M >> 8; + color.setCmyk(0, m, 0, 0, 0); + QCOMPARE(color.magenta(), m); + + int c, m2, y, k, a; + color.getCmyk(&c, &m2, &y, &k, &a); + QCOMPARE(m2, m); + } + + { + // 0.0-1.0 + qreal m = M / qreal(USHRT_MAX); + color.setCmykF(0.0, m, 0.0, 0.0, 0.0); + QCOMPARE(color.magentaF(), m); + + qreal c, m2, y, k, a; + color.getCmykF(&c, &m2, &y, &k, &a); + QCOMPARE(m2, m); + } + } + + for (int Y = 0; Y <= USHRT_MAX; ++Y) { + { + // 0-255 + int y = Y >> 8; + color.setCmyk(0, 0, y, 0, 0); + QCOMPARE(color.yellow(), y); + + int c, m, y2, k, a; + color.getCmyk(&c, &m, &y2, &k, &a); + QCOMPARE(y2, y); + } + + { + // 0.0-1.0 + qreal y = Y / qreal(USHRT_MAX); + color.setCmykF(0.0, 0.0, y, 0.0, 0.0); + QCOMPARE(color.yellowF(), y); + + qreal c, m, y2, k, a; + color.getCmykF(&c, &m, &y2, &k, &a); + QCOMPARE(y2, y); + } + } + + for (int K = 0; K <= USHRT_MAX; ++K) { + { + // 0-255 + int k = K >> 8; + color.setCmyk(0, 0, 0, k, 0); + QCOMPARE(color.black(), k); + + int c, m, y, k2, a; + color.getCmyk(&c, &m, &y, &k2, &a); + QCOMPARE(k2, k); + } + + { + // 0.0-1.0 + qreal k = K / qreal(USHRT_MAX); + color.setCmykF(0.0, 0.0, 0.0, k, 0.0); + QCOMPARE(color.blackF(), k); + + qreal c, m, y, k2, a; + color.getCmykF(&c, &m, &y, &k2, &a); + QCOMPARE(k2, k); + } + } +} + +void tst_QColor::hueHsl() +{ DEPENDS_ON(setHsl()); } + +void tst_QColor::saturationHsl() +{ DEPENDS_ON(setHsl()); } + +void tst_QColor::lightness() +{ DEPENDS_ON(setHsl()); } + +void tst_QColor::getHsl() +{ DEPENDS_ON(setHsl()); } + +void tst_QColor::setHsl() +{ + QColor color; + + for (int A = 0; A <= USHRT_MAX; ++A) { + { + // 0-255 + int a = A >> 8; + color.setHsl(0, 0, 0, a); + QCOMPARE(color.alpha(), a); + + int h, s, l, a2; + color.getHsv(&h, &s, &l, &a2); + QCOMPARE(a2, a); + } + + { + // 0.0-1.0 + qreal a = A / qreal(USHRT_MAX); + color.setHslF(0.0, 0.0, 0.0, a); QCOMPARE(color.alphaF(), a); + + qreal h, s, l, a2; + color.getHslF(&h, &s, &l, &a2); + QCOMPARE(a2, a); + } + } + + for (int H = 0; H < 36000; ++H) { + { + // 0-255 + int h = H / 100; + + color.setHsl(h, 0, 0, 0); + QCOMPARE(color.hslHue(), h); + + int h2, s, l, a; + color.getHsl(&h2, &s, &l, &a); + QCOMPARE(h2, h); + } + + { + // 0.0-1.0 + qreal h = H / 36000.0; + color.setHslF(h, 0.0, 0.0, 0.0); + QCOMPARE(color.hslHueF(), h); + + qreal h2, s, l, a; + color.getHslF(&h2, &s, &l, &a); + QCOMPARE(h2, h); + } + } + + for (int S = 0; S <= USHRT_MAX; ++S) { + { + // 0-255 + int s = S >> 8; + color.setHsl(0, s, 0, 0); + QCOMPARE(color.hslSaturation(), s); + + int h, s2, l, a; + color.getHsl(&h, &s2, &l, &a); + QCOMPARE(s2, s); + } + + { + // 0.0-1.0 + qreal s = S / qreal(USHRT_MAX); + color.setHslF(0.0, s, 0.0, 0.0); + QCOMPARE(color.hslSaturationF(), s); + + qreal h, s2, l, a; + color.getHslF(&h, &s2, &l, &a); + QCOMPARE(s2, s); + } + } + + for (int L = 0; L <= USHRT_MAX; ++L) { + { + // 0-255 + int l = L >> 8; + color.setHsl(0, 0, l, 0); + QCOMPARE(color.lightness(), l); + + int h, s, l2, a; + color.getHsl(&h, &s, &l2, &a); + QCOMPARE(l2, l); + } + + { + // 0.0-1.0 + qreal l = L / qreal(USHRT_MAX); + color.setHslF(0.0, 0.0, l, 0.0); + QCOMPARE(color.lightnessF(), l); + + qreal h, s, l2, a; + color.getHslF(&h, &s, &l2, &a); + QCOMPARE(l2, l); + } + } +} + +void tst_QColor::toRgb_data() +{ + QTest::addColumn<QColor>("expectedColor"); + QTest::addColumn<QColor>("hsvColor"); + QTest::addColumn<QColor>("cmykColor"); + QTest::addColumn<QColor>("hslColor"); + + QTest::newRow("black") + << QColor::fromRgbF(0.0, 0.0, 0.0) + << QColor::fromHsvF(-1.0, 0.0, 0.0) + << QColor::fromCmykF(0.0, 0.0, 0.0, 1.0) + << QColor::fromHslF(-1.0, 0.0, 0.0); + + QTest::newRow("white") + << QColor::fromRgbF(1.0, 1.0, 1.0) + << QColor::fromHsvF(-1.0, 0.0, 1.0) + << QColor::fromCmykF(0.0, 0.0, 0.0, 0.0) + << QColor::fromHslF(-1.0, 0.0, 1.0); + + QTest::newRow("red") + << QColor::fromRgbF(1.0, 0.0, 0.0) + << QColor::fromHsvF(0.0, 1.0, 1.0) + << QColor::fromCmykF(0.0, 1.0, 1.0, 0.0) + << QColor::fromHslF(0.0, 1.0, 0.5, 1.0); + + QTest::newRow("green") + << QColor::fromRgbF(0.0, 1.0, 0.0) + << QColor::fromHsvF(0.33333, 1.0, 1.0) + << QColor::fromCmykF(1.0, 0.0, 1.0, 0.0) + << QColor::fromHslF(0.33333, 1.0, 0.5); + + QTest::newRow("blue") + << QColor::fromRgbF(0.0, 0.0, 1.0) + << QColor::fromHsvF(0.66667, 1.0, 1.0) + << QColor::fromCmykF(1.0, 1.0, 0.0, 0.0) + << QColor::fromHslF(0.66667, 1.0, 0.5); + + QTest::newRow("cyan") + << QColor::fromRgbF(0.0, 1.0, 1.0) + << QColor::fromHsvF(0.5, 1.0, 1.0) + << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0) + << QColor::fromHslF(0.5, 1.0, 0.5); + + QTest::newRow("magenta") + << QColor::fromRgbF(1.0, 0.0, 1.0) + << QColor::fromHsvF(0.83333, 1.0, 1.0) + << QColor::fromCmykF(0.0, 1.0, 0.0, 0.0) + << QColor::fromHslF(0.83333, 1.0, 0.5); + + QTest::newRow("yellow") + << QColor::fromRgbF(1.0, 1.0, 0.0) + << QColor::fromHsvF(0.16667, 1.0, 1.0) + << QColor::fromCmykF(0.0, 0.0, 1.0, 0.0) + << QColor::fromHslF(0.16667, 1.0, 0.5); + + QTest::newRow("gray") + << QColor::fromRgbF(0.6431375, 0.6431375, 0.6431375) + << QColor::fromHsvF(-1.0, 0.0, 0.6431375) + << QColor::fromCmykF(0.0, 0.0, 0.0, 0.356863) + << QColor::fromHslF(-1.0, 0.0, 0.6431375); + + // ### add colors using the 0-255 functions +} + +void tst_QColor::toRgb() +{ + // invalid should remain invalid + QVERIFY(!QColor().toRgb().isValid()); + + QFETCH(QColor, expectedColor); + QFETCH(QColor, hsvColor); + QFETCH(QColor, cmykColor); + QFETCH(QColor, hslColor); + QCOMPARE(hsvColor.toRgb(), expectedColor); + QCOMPARE(cmykColor.toRgb(), expectedColor); + QCOMPARE(hslColor.toRgb(), expectedColor); + +} + +void tst_QColor::toHsv_data() +{ + QTest::addColumn<QColor>("expectedColor"); + QTest::addColumn<QColor>("rgbColor"); + QTest::addColumn<QColor>("cmykColor"); + QTest::addColumn<QColor>("hslColor"); + + QTest::newRow("data0") + << QColor::fromHsv(300, 255, 255) + << QColor(255, 0, 255) + << QColor::fromCmyk(0, 255, 0, 0) + << QColor::fromHslF(300./360., 1., 0.5, 1.0); + + QTest::newRow("data1") + << QColor::fromHsvF(1., 1., 1., 1.) + << QColor(255, 0, 0, 255) + << QColor::fromCmykF(0., 1., 1., 0.) + << QColor::fromHsvF(1., 1., 1., 1.); +} + +void tst_QColor::toRgbNonDestructive() +{ + QColor aColor = QColor::fromRgbF(0.11, 0.22, 0.33, 0.44); + QCOMPARE(aColor, aColor.toRgb()); +} + +void tst_QColor::toHsv() +{ + // invalid should remain invalid + QVERIFY(!QColor().toHsv().isValid()); + + QFETCH(QColor, expectedColor); + QFETCH(QColor, rgbColor); + QFETCH(QColor, cmykColor); + QFETCH(QColor, hslColor); + QCOMPARE(rgbColor.toHsv(), expectedColor); + QCOMPARE(cmykColor.toHsv(), expectedColor); + QCOMPARE(hslColor.toHsv(), expectedColor); +} + +void tst_QColor::toHsvNonDestructive() +{ + QColor aColor = QColor::fromHsvF(0.11, 0.22, 0.33, 0.44); + QCOMPARE(aColor, aColor.toHsv()); +} + +void tst_QColor::toCmyk_data() +{ + QTest::addColumn<QColor>("expectedColor"); + QTest::addColumn<QColor>("rgbColor"); + QTest::addColumn<QColor>("hsvColor"); + QTest::addColumn<QColor>("hslColor"); + + QTest::newRow("data0") + << QColor::fromCmykF(1.0, 0.0, 0.0, 0.0) + << QColor(0, 255, 255) + << QColor::fromHsv(180, 255, 255) + << QColor::fromHslF(180./360., 1., 0.5, 1.0); + + QTest::newRow("data1") + << QColor::fromCmyk(255, 255, 255, 255) + << QColor::fromRgb(0, 0, 0) + << QColor::fromRgb(0, 0, 0).toHsv() + << QColor::fromRgb(0, 0, 0).toHsl(); +} + +void tst_QColor::toCmyk() +{ + // invalid should remain invalid + QVERIFY(!QColor().toCmyk().isValid()); + + QFETCH(QColor, expectedColor); + QFETCH(QColor, rgbColor); + QFETCH(QColor, hsvColor); + QFETCH(QColor, hslColor); + QCOMPARE(rgbColor.toHsv().toCmyk(), expectedColor); + QCOMPARE(hsvColor.toCmyk(), expectedColor); + QCOMPARE(hslColor.toCmyk(), expectedColor); +} + +void tst_QColor::toCmykNonDestructive() +{ + QColor aColor = QColor::fromCmykF(0.11, 0.22, 0.33, 0.44); + QCOMPARE(aColor, aColor.toCmyk()); +} + +void tst_QColor::toHsl_data() +{ + QTest::addColumn<QColor>("expectedColor"); + QTest::addColumn<QColor>("hsvColor"); + QTest::addColumn<QColor>("rgbColor"); + QTest::addColumn<QColor>("cmykColor"); + + + QTest::newRow("data0") + << QColor::fromHslF(300./360., 1., 0.5, 1.0) + << QColor::fromHsv(300, 255, 255) + << QColor(255, 0, 255) + << QColor::fromCmyk(0, 255, 0, 0); + + QTest::newRow("data1") + << QColor::fromHslF(1., 1., 0.5, 1.0) + << QColor::fromHsvF(1., 1., 1., 1.) + << QColor(255, 0, 0, 255) + << QColor::fromCmykF(0., 1., 1., 0.); +} + +void tst_QColor::toHsl() +{ + // invalid should remain invalid + QVERIFY(!QColor().toHsl().isValid()); + + QFETCH(QColor, expectedColor); + QFETCH(QColor, rgbColor); + QFETCH(QColor, cmykColor); + QFETCH(QColor, hsvColor); + + QCOMPARE(rgbColor.toHsl(), expectedColor); + QCOMPARE(cmykColor.toHsl(), expectedColor); + QCOMPARE(hsvColor.toHsl(), expectedColor); + +} + + +void tst_QColor::toHslNonDestructive() +{ + QColor aColor = QColor::fromHslF(0.11, 0.22, 0.33, 0.44); + QCOMPARE(aColor, aColor.toHsl()); +} + + +void tst_QColor::convertTo() +{ + QColor color(Qt::black); + + QColor rgb = color.convertTo(QColor::Rgb); + QVERIFY(rgb.spec() == QColor::Rgb); + + QColor hsv = color.convertTo(QColor::Hsv); + QVERIFY(hsv.spec() == QColor::Hsv); + + QColor cmyk = color.convertTo(QColor::Cmyk); + QVERIFY(cmyk.spec() == QColor::Cmyk); + + QColor hsl = color.convertTo(QColor::Hsl); + QVERIFY(hsl.spec() == QColor::Hsl); + + QColor invalid = color.convertTo(QColor::Invalid); + QVERIFY(invalid.spec() == QColor::Invalid); + + DEPENDS_ON(toRgb()); + DEPENDS_ON(toHsv()); + DEPENDS_ON(toCmyk()); + DEPENDS_ON(toHsl()); +} + +void tst_QColor::fromRgb() +{ DEPENDS_ON(convertTo()); } + +void tst_QColor::fromHsv() +{ DEPENDS_ON(convertTo()); } + +void tst_QColor::fromCmyk() +{ DEPENDS_ON(convertTo()); } + +void tst_QColor::fromHsl() +{ DEPENDS_ON(convertTo()); } + +void tst_QColor::light() +{ + QColor gray(Qt::gray); + QColor lighter = gray.light(); + QVERIFY(lighter.value() > gray.value()); +} + +void tst_QColor::dark() +{ + QColor gray(Qt::gray); + QColor darker = gray.dark(); + QVERIFY(darker.value() < gray.value()); +} + +void tst_QColor::assignmentOoperator() +{ DEPENDS_ON(convertTo()); } + +void tst_QColor::equalityOperator() +{ DEPENDS_ON(convertTo()); } + +Q_DECLARE_METATYPE(QColor::Spec); + +void tst_QColor::specConstructor_data() +{ + QTest::addColumn<QColor::Spec>("spec"); + + QTest::newRow("Invalid") << QColor::Invalid; + QTest::newRow("Rgb") << QColor::Rgb; + QTest::newRow("Hsv") << QColor::Hsv; + QTest::newRow("Cmyk") << QColor::Cmyk; +} + +void tst_QColor::specConstructor() +{ + QFETCH(QColor::Spec, spec); + QColor color = spec; + QCOMPARE(color.spec(), spec); +} + +void tst_QColor::achromaticHslHue() +{ + QColor color = Qt::black; + + QColor hsl = color.toHsl(); + QCOMPARE(hsl.hslHue(), -1); +} + +#ifdef Q_WS_X11 +void tst_QColor::allowX11ColorNames() +{ + DEPENDS_ON(setallowX11ColorNames()); +} + +void tst_QColor::setallowX11ColorNames() +{ +#if defined(Q_OS_IRIX) + QSKIP("This fails due to the gamma settings in the SGI X server", SkipAll); +#else + RGBData x11RgbTbl[] = { + // a few standard X11 color names + { "DodgerBlue1", qRgb(30, 144, 255) }, + { "DodgerBlue2", qRgb(28, 134, 238) }, + { "DodgerBlue3", qRgb(24, 116, 205) }, + { "DodgerBlue4", qRgb(16, 78, 139) }, + { "SteelBlue1", qRgb(99, 184, 255) }, + { "SteelBlue2", qRgb(92, 172, 238) }, + { "SteelBlue3", qRgb(79, 148, 205) }, + { "SteelBlue4", qRgb(54, 100, 139) }, + { "DeepSkyBlue1", qRgb(0, 191, 255) }, + { "DeepSkyBlue2", qRgb(0, 178, 238) }, + { "DeepSkyBlue3", qRgb(0, 154, 205) }, + { "DeepSkyBlue4", qRgb(0, 104, 139) }, + { "SkyBlue1", qRgb(135, 206, 255) }, + { "SkyBlue2", qRgb(126, 192, 238) }, + { "SkyBlue3", qRgb(108, 166, 205) }, + { "SkyBlue4", qRgb(74, 112, 139) } + }; + static const int x11RgbTblSize = sizeof(x11RgbTbl) / sizeof(RGBData); + + // X11 color names should not work by default + QVERIFY(!QColor::allowX11ColorNames()); + for (int i = 0; i < x11RgbTblSize; ++i) { + QString colorName = QLatin1String(x11RgbTbl[i].name); + QColor color; + color.setNamedColor(colorName); + QVERIFY(!color.isValid()); + } + + // enable X11 color names + QColor::setAllowX11ColorNames(true); + QVERIFY(QColor::allowX11ColorNames()); + for (int i = 0; i < x11RgbTblSize; ++i) { + QString colorName = QLatin1String(x11RgbTbl[i].name); + QColor color; + color.setNamedColor(colorName); + QColor expected(x11RgbTbl[i].value); + QCOMPARE(color, expected); + } + + // should be able to turn off X11 color names + QColor::setAllowX11ColorNames(false); + QVERIFY(!QColor::allowX11ColorNames()); + for (int i = 0; i < x11RgbTblSize; ++i) { + QString colorName = QLatin1String(x11RgbTbl[i].name); + QColor color; + color.setNamedColor(colorName); + QVERIFY(!color.isValid()); + } +#endif // Q_OS_IRIX +} +#endif // Q_WS_X11 + +QTEST_MAIN(tst_QColor) +#include "tst_qcolor.moc" diff --git a/tests/auto/gui/painting/qpaintengine/.gitignore b/tests/auto/gui/painting/qpaintengine/.gitignore new file mode 100644 index 0000000000..e55942ea9f --- /dev/null +++ b/tests/auto/gui/painting/qpaintengine/.gitignore @@ -0,0 +1 @@ +tst_qpaintengine diff --git a/tests/auto/gui/painting/qpaintengine/qpaintengine.pro b/tests/auto/gui/painting/qpaintengine/qpaintengine.pro new file mode 100644 index 0000000000..e37c1668ac --- /dev/null +++ b/tests/auto/gui/painting/qpaintengine/qpaintengine.pro @@ -0,0 +1,9 @@ +############################################################ +# Project file for autotest for file qpaintengine.h +############################################################ + +load(qttest_p4) + +SOURCES += tst_qpaintengine.cpp + + diff --git a/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp b/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp new file mode 100644 index 0000000000..ba9cc62a3d --- /dev/null +++ b/tests/auto/gui/painting/qpaintengine/tst_qpaintengine.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qcoreapplication.h> +#include <qdebug.h> +#include <qpaintengine.h> +#include <qpixmap.h> + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPaintEngine : public QObject +{ +Q_OBJECT + +public: + tst_QPaintEngine(); + virtual ~tst_QPaintEngine(); + +private slots: + void getSetCheck(); +}; + +tst_QPaintEngine::tst_QPaintEngine() +{ +} + +tst_QPaintEngine::~tst_QPaintEngine() +{ +} + +class MyPaintEngine : public QPaintEngine +{ +public: + MyPaintEngine() : QPaintEngine() {} + bool begin(QPaintDevice *) { return true; } + bool end() { return true; } + void updateState(const QPaintEngineState &) {} + void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {} + Type type() const { return Raster; } +}; + +// Testing get/set functions +void tst_QPaintEngine::getSetCheck() +{ + MyPaintEngine obj1; + // QPaintDevice * QPaintEngine::paintDevice() + // void QPaintEngine::setPaintDevice(QPaintDevice *) + QPixmap *var1 = new QPixmap; + obj1.setPaintDevice(var1); + QCOMPARE((QPaintDevice *)var1, obj1.paintDevice()); + obj1.setPaintDevice((QPaintDevice *)0); + QCOMPARE((QPaintDevice *)0, obj1.paintDevice()); + delete var1; +} + +QTEST_MAIN(tst_QPaintEngine) +#include "tst_qpaintengine.moc" diff --git a/tests/auto/gui/painting/qpainter/.gitignore b/tests/auto/gui/painting/qpainter/.gitignore new file mode 100644 index 0000000000..33e0dbe945 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/.gitignore @@ -0,0 +1,2 @@ +tst_qpainter +foo.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png Binary files differnew file mode 100644 index 0000000000..f2ab9a776d --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt0x0.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png Binary files differnew file mode 100644 index 0000000000..b1c755b5b0 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt100x100.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png Binary files differnew file mode 100644 index 0000000000..0e30498da5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/10x10SizeAt200x200.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png Binary files differnew file mode 100644 index 0000000000..f00796a3ad --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt0x0.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png Binary files differnew file mode 100644 index 0000000000..a9a1a8a536 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt100x100.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png Binary files differnew file mode 100644 index 0000000000..0e30498da5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/13x100SizeAt200x200.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png Binary files differnew file mode 100644 index 0000000000..67db116b90 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt0x0.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png Binary files differnew file mode 100644 index 0000000000..7d32afa4a8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt100x100.png diff --git a/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png Binary files differnew file mode 100644 index 0000000000..0e30498da5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawEllipse/200x200SizeAt200x200.png diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm new file mode 100644 index 0000000000..e645a0b86b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/dst.xbm @@ -0,0 +1,6 @@ +#define dst_width 8 +#define dst_height 8 +static char dst_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x30,0x00,0x30,0x00, + 0x11,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x10,0x00,0x00, + 0x00,0x11 }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm new file mode 100644 index 0000000000..303c799264 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndNotROP.xbm @@ -0,0 +1,6 @@ +#define res_AndNotROP_width 8 +#define res_AndNotROP_height 8 +static char res_AndNotROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm new file mode 100644 index 0000000000..31333de879 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_AndROP.xbm @@ -0,0 +1,6 @@ +#define res_AndROP_width 8 +#define res_AndROP_height 8 +static char res_AndROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm new file mode 100644 index 0000000000..9cc25ea147 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_ClearROP.xbm @@ -0,0 +1,6 @@ +#define res_ClearROP_width 8 +#define res_ClearROP_height 8 +static char res_ClearROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm new file mode 100644 index 0000000000..869844dcee --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_CopyROP.xbm @@ -0,0 +1,6 @@ +#define res_CopyROP_width 8 +#define res_CopyROP_height 8 +static char res_CopyROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0x35,0x00,0x5a,0x00, + 0x41,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc0,0x5b,0x2f, + 0x2b,0x50 }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm new file mode 100644 index 0000000000..d058484fa8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NandROP.xbm @@ -0,0 +1,6 @@ +#define res_NandROP_width 8 +#define res_NandROP_height 8 +static char res_NandROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm new file mode 100644 index 0000000000..3a2bc23468 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NopROP.xbm @@ -0,0 +1,6 @@ +#define res_NopROP_width 8 +#define res_NopROP_height 8 +static char res_NopROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm new file mode 100644 index 0000000000..c74be41bbd --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NorROP.xbm @@ -0,0 +1,6 @@ +#define res_NorROP_width 8 +#define res_NorROP_height 8 +static char res_NorROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm new file mode 100644 index 0000000000..0cf8c3a82c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotAndROP.xbm @@ -0,0 +1,6 @@ +#define res_NotAndROP_width 8 +#define res_NotAndROP_height 8 +static char res_NotAndROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm new file mode 100644 index 0000000000..65474e16c5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotCopyROP.xbm @@ -0,0 +1,6 @@ +#define res_NotCopyROP_width 8 +#define res_NotCopyROP_height 8 +static char res_NotCopyROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm new file mode 100644 index 0000000000..144d8995b6 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotOrROP.xbm @@ -0,0 +1,6 @@ +#define res_NotOrROP_width 8 +#define res_NotOrROP_height 8 +static char res_NotOrROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm new file mode 100644 index 0000000000..ccb3d36fb4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotROP.xbm @@ -0,0 +1,6 @@ +#define res_NotROP_width 8 +#define res_NotROP_height 8 +static char res_NotROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm new file mode 100644 index 0000000000..4be8f51a80 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_NotXorROP.xbm @@ -0,0 +1,6 @@ +#define res_NotXorROP_width 8 +#define res_NotXorROP_height 8 +static char res_NotXorROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm new file mode 100644 index 0000000000..d53fbe00e1 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrNotROP.xbm @@ -0,0 +1,6 @@ +#define res_OrNotROP_width 8 +#define res_OrNotROP_height 8 +static char res_OrNotROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm new file mode 100644 index 0000000000..06b51fcc68 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_OrROP.xbm @@ -0,0 +1,6 @@ +#define res_OrROP_width 8 +#define res_OrROP_height 8 +static char res_OrROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm new file mode 100644 index 0000000000..ab42472bb0 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_SetROP.xbm @@ -0,0 +1,6 @@ +#define res_SetROP_width 8 +#define res_SetROP_height 8 +static char res_SetROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm new file mode 100644 index 0000000000..5ac892dd0b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawLine_rop_bitmap/res/res_XorROP.xbm @@ -0,0 +1,6 @@ +#define res_XorROP_width 8 +#define res_XorROP_height 8 +static char res_XorROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png Binary files differnew file mode 100644 index 0000000000..8a3d28f3ed --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/dst3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png Binary files differnew file mode 100644 index 0000000000..fe017ac1ab --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png Binary files differnew file mode 100644 index 0000000000..82d938c023 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png Binary files differnew file mode 100644 index 0000000000..2b67b928e4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png Binary files differnew file mode 100644 index 0000000000..c95b5a10ba --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png Binary files differnew file mode 100644 index 0000000000..bbe2a24530 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png Binary files differnew file mode 100644 index 0000000000..0158278b84 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png Binary files differnew file mode 100644 index 0000000000..aa1f403075 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndNotROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png Binary files differnew file mode 100644 index 0000000000..ebf8244eee --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png Binary files differnew file mode 100644 index 0000000000..88568bc330 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png Binary files differnew file mode 100644 index 0000000000..0ed6de2865 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png Binary files differnew file mode 100644 index 0000000000..c2ff341e6b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png Binary files differnew file mode 100644 index 0000000000..e08c9acbe2 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png Binary files differnew file mode 100644 index 0000000000..e9d7a57333 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png Binary files differnew file mode 100644 index 0000000000..01438a195c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_AndROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_ClearROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png Binary files differnew file mode 100644 index 0000000000..587623d3e8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png Binary files differnew file mode 100644 index 0000000000..10e7ae59d5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png Binary files differnew file mode 100644 index 0000000000..5c14136eb4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png Binary files differnew file mode 100644 index 0000000000..207f52564b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png Binary files differnew file mode 100644 index 0000000000..6981cee080 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png Binary files differnew file mode 100644 index 0000000000..8b8de9892a --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png Binary files differnew file mode 100644 index 0000000000..9825c0539f --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_CopyROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png Binary files differnew file mode 100644 index 0000000000..8d26638c03 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png Binary files differnew file mode 100644 index 0000000000..f5b33589ba --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png Binary files differnew file mode 100644 index 0000000000..adc4ee3701 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png Binary files differnew file mode 100644 index 0000000000..dccc94c43b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png Binary files differnew file mode 100644 index 0000000000..4d207e7968 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png Binary files differnew file mode 100644 index 0000000000..aa93d4d4a4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png Binary files differnew file mode 100644 index 0000000000..ad320f950b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NandROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NopROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png Binary files differnew file mode 100644 index 0000000000..3e33bb1078 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png Binary files differnew file mode 100644 index 0000000000..ce2b6f4e15 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png Binary files differnew file mode 100644 index 0000000000..9eddc9840b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png Binary files differnew file mode 100644 index 0000000000..4ea9669dd3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png Binary files differnew file mode 100644 index 0000000000..c64e0a5630 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png Binary files differnew file mode 100644 index 0000000000..1fe3def383 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png Binary files differnew file mode 100644 index 0000000000..9c294b04d9 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NorROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png Binary files differnew file mode 100644 index 0000000000..01c694cdcc --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png Binary files differnew file mode 100644 index 0000000000..4b11aa9c41 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png Binary files differnew file mode 100644 index 0000000000..accbe42112 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png Binary files differnew file mode 100644 index 0000000000..3c58d4fac7 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png Binary files differnew file mode 100644 index 0000000000..3b0a41c396 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png Binary files differnew file mode 100644 index 0000000000..045ef33012 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png Binary files differnew file mode 100644 index 0000000000..3a83725938 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotAndROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png Binary files differnew file mode 100644 index 0000000000..7c51fc16fa --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png Binary files differnew file mode 100644 index 0000000000..8f519e8c52 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png Binary files differnew file mode 100644 index 0000000000..a0f9f60653 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png Binary files differnew file mode 100644 index 0000000000..95931a4317 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png Binary files differnew file mode 100644 index 0000000000..f825d523b0 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png Binary files differnew file mode 100644 index 0000000000..245a27ea2f --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png Binary files differnew file mode 100644 index 0000000000..b32020675b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png Binary files differnew file mode 100644 index 0000000000..cff8926587 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotCopyROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png Binary files differnew file mode 100644 index 0000000000..3622f3a2b1 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png Binary files differnew file mode 100644 index 0000000000..e31793e4a3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png Binary files differnew file mode 100644 index 0000000000..8e8237548b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png Binary files differnew file mode 100644 index 0000000000..f4b98914b4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png Binary files differnew file mode 100644 index 0000000000..b14fdba341 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png Binary files differnew file mode 100644 index 0000000000..129d7f3dc6 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png Binary files differnew file mode 100644 index 0000000000..d894c5cb68 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotOrROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png Binary files differnew file mode 100644 index 0000000000..b1e61504cd --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png Binary files differnew file mode 100644 index 0000000000..8cf29cde81 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png Binary files differnew file mode 100644 index 0000000000..99fedf8c04 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png Binary files differnew file mode 100644 index 0000000000..bc220f546e --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png Binary files differnew file mode 100644 index 0000000000..f48e8b9f4d --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png Binary files differnew file mode 100644 index 0000000000..c5e3c0fc63 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png Binary files differnew file mode 100644 index 0000000000..13bb69f91b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png Binary files differnew file mode 100644 index 0000000000..4a7ca7f9b3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_NotXorROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png Binary files differnew file mode 100644 index 0000000000..85b964301d --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png Binary files differnew file mode 100644 index 0000000000..d92bf16044 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png Binary files differnew file mode 100644 index 0000000000..bb81c5abe8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png Binary files differnew file mode 100644 index 0000000000..9378f166cd --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png Binary files differnew file mode 100644 index 0000000000..2ea026eb6c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png Binary files differnew file mode 100644 index 0000000000..8366d37eda --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png Binary files differnew file mode 100644 index 0000000000..39c36d1b52 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrNotROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png Binary files differnew file mode 100644 index 0000000000..beb2bc35b8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png Binary files differnew file mode 100644 index 0000000000..6ed17a72ed --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png Binary files differnew file mode 100644 index 0000000000..9e0b63c220 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png Binary files differnew file mode 100644 index 0000000000..6471b4aaa4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png Binary files differnew file mode 100644 index 0000000000..c158ea0d01 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png Binary files differnew file mode 100644 index 0000000000..eb3deacc86 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png Binary files differnew file mode 100644 index 0000000000..51948b0ac9 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_OrROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png Binary files differnew file mode 100644 index 0000000000..00968ffd06 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_SetROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png Binary files differnew file mode 100644 index 0000000000..c2b009cac3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP0.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png Binary files differnew file mode 100644 index 0000000000..42b0b3c308 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP1.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png Binary files differnew file mode 100644 index 0000000000..bc43614ab3 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP2.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png Binary files differnew file mode 100644 index 0000000000..7486d4b3f4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP3.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png Binary files differnew file mode 100644 index 0000000000..8098634be4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP4.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png Binary files differnew file mode 100644 index 0000000000..8c5b9feb7c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP5.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png Binary files differnew file mode 100644 index 0000000000..c7e51a1410 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP6.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png Binary files differnew file mode 100644 index 0000000000..8605b64d93 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/res/res_XorROP7.png diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm new file mode 100644 index 0000000000..f088d28c8c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src1.xbm @@ -0,0 +1,12 @@ +#define src1_width 32 +#define src1_height 32 +static char src1_bits[] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm new file mode 100644 index 0000000000..bd73f9433c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2-mask.xbm @@ -0,0 +1,16 @@ +#define src2_width 32 +#define src2_height 48 +static char src2_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm new file mode 100644 index 0000000000..40126a9d17 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src2.xbm @@ -0,0 +1,16 @@ +#define src2_width 32 +#define src2_height 48 +static char src2_bits[] = { + 0xa7,0x01,0xc0,0x03,0x40,0x9b,0x80,0x08,0x18,0x00,0x00,0x00,0x48,0x00,0x00, + 0x00,0xbb,0xbb,0xbb,0xbb,0xee,0xee,0xee,0xee,0x00,0x00,0x00,0x00,0xfe,0xff, + 0xff,0xff,0x0d,0x00,0x0d,0x00,0x20,0x00,0x20,0x00,0x80,0xed,0xb7,0x08,0xe8, + 0x61,0x54,0x08,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x68,0xa2,0x02, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm new file mode 100644 index 0000000000..2f2d5472a4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop/src3.xbm @@ -0,0 +1,12 @@ +#define src3_width 32 +#define src3_height 32 +static char src3_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm new file mode 100644 index 0000000000..45543c8ebf --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/dst.xbm @@ -0,0 +1,6 @@ +#define dst_width 8 +#define dst_height 8 +static char dst_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xb1,0x00,0x00,0x00,0x70,0xe6,0x6e,0x2b,0x70,0xe6,0x6e,0x2b,0x24,0x00,0x00, + 0x00,0x81 }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm new file mode 100644 index 0000000000..303c799264 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndNotROP.xbm @@ -0,0 +1,6 @@ +#define res_AndNotROP_width 8 +#define res_AndNotROP_height 8 +static char res_AndNotROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm new file mode 100644 index 0000000000..31333de879 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_AndROP.xbm @@ -0,0 +1,6 @@ +#define res_AndROP_width 8 +#define res_AndROP_height 8 +static char res_AndROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm new file mode 100644 index 0000000000..9cc25ea147 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_ClearROP.xbm @@ -0,0 +1,6 @@ +#define res_ClearROP_width 8 +#define res_ClearROP_height 8 +static char res_ClearROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm new file mode 100644 index 0000000000..869844dcee --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_CopyROP.xbm @@ -0,0 +1,6 @@ +#define res_CopyROP_width 8 +#define res_CopyROP_height 8 +static char res_CopyROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0x35,0x00,0x5a,0x00, + 0x41,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xc0,0x5b,0x2f, + 0x2b,0x50 }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm new file mode 100644 index 0000000000..d058484fa8 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NandROP.xbm @@ -0,0 +1,6 @@ +#define res_NandROP_width 8 +#define res_NandROP_height 8 +static char res_NandROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm new file mode 100644 index 0000000000..3a2bc23468 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NopROP.xbm @@ -0,0 +1,6 @@ +#define res_NopROP_width 8 +#define res_NopROP_height 8 +static char res_NopROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm new file mode 100644 index 0000000000..c74be41bbd --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NorROP.xbm @@ -0,0 +1,6 @@ +#define res_NorROP_width 8 +#define res_NorROP_height 8 +static char res_NorROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm new file mode 100644 index 0000000000..0cf8c3a82c --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotAndROP.xbm @@ -0,0 +1,6 @@ +#define res_NotAndROP_width 8 +#define res_NotAndROP_height 8 +static char res_NotAndROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm new file mode 100644 index 0000000000..65474e16c5 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotCopyROP.xbm @@ -0,0 +1,6 @@ +#define res_NotCopyROP_width 8 +#define res_NotCopyROP_height 8 +static char res_NotCopyROP_bits[] = { + 0xf0,0xf0,0xc0,0xc0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm new file mode 100644 index 0000000000..144d8995b6 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotOrROP.xbm @@ -0,0 +1,6 @@ +#define res_NotOrROP_width 8 +#define res_NotOrROP_height 8 +static char res_NotOrROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm new file mode 100644 index 0000000000..ccb3d36fb4 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotROP.xbm @@ -0,0 +1,6 @@ +#define res_NotROP_width 8 +#define res_NotROP_height 8 +static char res_NotROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm new file mode 100644 index 0000000000..4be8f51a80 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_NotXorROP.xbm @@ -0,0 +1,6 @@ +#define res_NotXorROP_width 8 +#define res_NotXorROP_height 8 +static char res_NotXorROP_bits[] = { + 0xf0,0xf0,0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm new file mode 100644 index 0000000000..d53fbe00e1 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrNotROP.xbm @@ -0,0 +1,6 @@ +#define res_OrNotROP_width 8 +#define res_OrNotROP_height 8 +static char res_OrNotROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xcc,0xcc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm new file mode 100644 index 0000000000..06b51fcc68 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_OrROP.xbm @@ -0,0 +1,6 @@ +#define res_OrROP_width 8 +#define res_OrROP_height 8 +static char res_OrROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0xff,0xff,0xff,0x7f, + 0xff,0xff,0xff,0x7f,0x50,0x00,0x00,0x00,0x09,0x02,0x00,0x00,0xff,0xff,0xff, + 0x7f,0xff }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm new file mode 100644 index 0000000000..ab42472bb0 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_SetROP.xbm @@ -0,0 +1,6 @@ +#define res_SetROP_width 8 +#define res_SetROP_height 8 +static char res_SetROP_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xfc,0xfc,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm new file mode 100644 index 0000000000..5ac892dd0b --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/res/res_XorROP.xbm @@ -0,0 +1,6 @@ +#define res_XorROP_width 8 +#define res_XorROP_height 8 +static char res_XorROP_bits[] = { + 0xf0,0xf0,0xcc,0xcc,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x62,0x00,0x6d,0x00, + 0x00,0xb5,0x7a,0x2b,0x50,0x00,0x00,0x00,0x41,0x00,0x00,0x00,0x42,0x55,0x53, + 0x59,0x3a }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm new file mode 100644 index 0000000000..ac9031f1f1 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1-mask.xbm @@ -0,0 +1,6 @@ +#define src1_width 8 +#define src1_height 8 +static char src1_bits[] = { + 0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00, + 0x59,0x00,0x00,0x00,0x18,0xe6,0x6e,0x2b,0x18,0xe6,0x6e,0x2b,0x00,0x00,0x00, + 0x00,0x49 }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm new file mode 100644 index 0000000000..d883569db2 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src1.xbm @@ -0,0 +1,6 @@ +#define src1_width 8 +#define src1_height 8 +static char src1_bits[] = { + 0xf0,0xf0,0xfc,0xfc,0xc0,0xc0,0xf0,0xf0,0x00,0x00,0x00,0xe0,0xe5,0x6e,0x2b, + 0x29,0x00,0x00,0x00,0xe8,0xe5,0x6e,0x2b,0xe8,0xe5,0x6e,0x2b,0x3c,0x00,0x00, + 0x05,0x3c }; diff --git a/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm new file mode 100644 index 0000000000..fb203df28a --- /dev/null +++ b/tests/auto/gui/painting/qpainter/drawPixmap_rop_bitmap/src2.xbm @@ -0,0 +1,5 @@ +#define src2_width 4 +#define src2_height 4 +static char src2_bits[] = { + 0x0f,0x5f,0x40,0x00,0x00,0x00,0x00,0x2d,0x00,0x39,0x00,0x5f,0x00,0x5d,0x00, + 0x30 }; diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro new file mode 100644 index 0000000000..00307d3e58 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/qpainter.pro @@ -0,0 +1,20 @@ +load(qttest_p4) + +QT += widgets widgets-private printsupport + +SOURCES += tst_qpainter.cpp +wince*|symbian: { + addFiles.files = drawEllipse drawLine_rop_bitmap drawPixmap_rop drawPixmap_rop_bitmap task217400.png + addFiles.path = . + DEPLOYMENT += addFiles +} + +wince* { + DEFINES += SRCDIR=\\\".\\\" +} else:!symbian { + DEFINES += SRCDIR=\\\"$$PWD\\\" +} + + +mac*:CONFIG+=insignificant_test +contains(QT_CONFIG,xcb):qpa:CONFIG+=insignificant_test # QTBUG-20756 crashes on qpa, xcb diff --git a/tests/auto/gui/painting/qpainter/task217400.png b/tests/auto/gui/painting/qpainter/task217400.png Binary files differnew file mode 100644 index 0000000000..c12a602ba6 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/task217400.png diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp new file mode 100644 index 0000000000..c2c9002023 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -0,0 +1,4697 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include "../../../../shared/util.h" + +#include <qpainter.h> +#include <qapplication.h> +#include <qwidget.h> +#include <qfontmetrics.h> +#include <qbitmap.h> +#include <qimage.h> +#include <qthread.h> +#include <limits.h> +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) +#include <qprinter.h> +#include <math.h> +#endif +#include <qpaintengine.h> +#include <qdesktopwidget.h> +#include <qpixmap.h> + +#include <qpainter.h> + +#include <qlabel.h> + +#include <qqueue.h> + +#include <qgraphicsview.h> +#include <qgraphicsscene.h> +#include <qgraphicsproxywidget.h> +#include <qlayout.h> +#include <qfontdatabase.h> + +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "." +#endif + +Q_DECLARE_METATYPE(QGradientStops) +Q_DECLARE_METATYPE(QLine) +Q_DECLARE_METATYPE(QRect) +Q_DECLARE_METATYPE(QSize) +Q_DECLARE_METATYPE(QPoint) +Q_DECLARE_METATYPE(QPainterPath) + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPainter : public QObject +{ +Q_OBJECT + +public: + tst_QPainter(); + virtual ~tst_QPainter(); + + +public slots: + void init(); + void cleanup(); +private slots: + void getSetCheck(); + void qt_format_text_clip(); + void qt_format_text_boundingRect(); + void drawPixmap_comp_data(); + void drawPixmap_comp(); + void saveAndRestore_data(); + void saveAndRestore(); + + void drawBorderPixmap(); + void drawPixmapFragments(); + + void drawLine_data(); + void drawLine(); + void drawLine_clipped(); + void drawLine_task121143(); + void drawLine_task216948(); + + void drawLine_task190634(); + void drawLine_task229459(); + void drawLine_task234891(); + + void drawRect_data() { fillData(); } + void drawRect(); + void drawRect2(); + + void fillRect(); + void fillRect2(); + void fillRect3(); + void fillRect4(); + + void drawEllipse_data(); + void drawEllipse(); + void drawClippedEllipse_data(); + void drawClippedEllipse(); + + void drawPath_data(); + void drawPath(); + void drawPath2(); + void drawPath3(); + + void drawRoundRect_data() { fillData(); } + void drawRoundRect(); + + void qimageFormats_data(); + void qimageFormats(); + void textOnTransparentImage(); + + void initFrom(); + + void setWindow(); + + void combinedMatrix(); + void renderHints(); + + void disableEnableClipping(); + void setClipRect(); + void setEqualClipRegionAndPath_data(); + void setEqualClipRegionAndPath(); + + void clipRectSaveRestore(); + + void clippedFillPath_data(); + void clippedFillPath(); + void clippedLines_data(); + void clippedLines(); + void clippedPolygon_data(); + void clippedPolygon(); + + void clippedText(); + + void clipBoundingRect(); + + void setOpacity_data(); + void setOpacity(); + + void drawhelper_blend_untransformed_data(); + void drawhelper_blend_untransformed(); + void drawhelper_blend_tiled_untransformed_data(); + void drawhelper_blend_tiled_untransformed(); + + void porterDuff_warning(); + + void drawhelper_blend_color(); + + void childWidgetViewport(); + + void fillRect_objectBoundingModeGradient(); + void fillRect_stretchToDeviceMode(); + void monoImages(); + + void linearGradientSymmetry_data(); + void linearGradientSymmetry(); + void gradientInterpolation(); + + void fpe_pixmapTransform(); + void fpe_zeroLengthLines(); + void fpe_divByZero(); + + void fpe_steepSlopes_data(); + void fpe_steepSlopes(); + void fpe_rasterizeLine_task232012(); + + void fpe_radialGradients(); + + void rasterizer_asserts(); + void rasterizer_negativeCoords(); + + void blendOverFlow_data(); + void blendOverFlow(); + + void largeImagePainting_data(); + void largeImagePainting(); + + void imageScaling_task206785(); + + void outlineFillConsistency(); + + void drawImage_task217400_data(); + void drawImage_task217400(); + void drawImage_1x1(); + void drawImage_task258776(); + void drawRect_task215378(); + void drawRect_task247505(); + + void drawText_subPixelPositionsInRaster_qtbug5053(); + + void drawImage_data(); + void drawImage(); + + void clippedImage(); + + void stateResetBetweenQPainters(); + + void imageCoordinateLimit(); + void imageBlending_data(); + void imageBlending(); + void imageBlending_clipped(); + + void paintOnNullPixmap(); + void checkCompositionMode(); + + void drawPolygon(); + + void inactivePainter(); + + void extendedBlendModes(); + + void zeroOpacity(); + void clippingBug(); + void emptyClip(); + + void taskQT4444_dontOverflowDashOffset(); + + void painterBegin(); + void setPenColorOnImage(); + void setPenColorOnPixmap(); + + void QTBUG5939_attachPainterPrivate(); + + void drawPointScaled(); + + void QTBUG14614_gradientCacheRaceCondition(); + void drawTextOpacity(); + + void QTBUG17053_zeroDashPattern(); + + void drawTextOutsideGuiThread(); + +private: + void fillData(); + void setPenColor(QPainter& p); + QColor baseColor( int k, int intensity=255 ); + QImage getResImage( const QString &dir, const QString &addition, const QString &extension ); + QBitmap getBitmap( const QString &dir, const QString &filename, bool mask ); +}; + +// Testing get/set functions +void tst_QPainter::getSetCheck() +{ + QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); + QPainter obj1; + obj1.begin(&img); + // CompositionMode QPainter::compositionMode() + // void QPainter::setCompositionMode(CompositionMode) + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOver), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOver), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Clear)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Clear), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Source)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Source), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Destination)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Destination), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceIn), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationIn), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceOut), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationOut), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_SourceAtop), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_DestinationAtop), obj1.compositionMode()); + obj1.setCompositionMode(QPainter::CompositionMode(QPainter::CompositionMode_Xor)); + QCOMPARE(QPainter::CompositionMode(QPainter::CompositionMode_Xor), obj1.compositionMode()); + + // const QPen & QPainter::pen() + // void QPainter::setPen(const QPen &) + QPen var3(Qt::red); + obj1.setPen(var3); + QCOMPARE(var3, obj1.pen()); + obj1.setPen(QPen()); + QCOMPARE(QPen(), obj1.pen()); + + // const QBrush & QPainter::brush() + // void QPainter::setBrush(const QBrush &) + QBrush var4(Qt::red); + obj1.setBrush(var4); + QCOMPARE(var4, obj1.brush()); + obj1.setBrush(QBrush()); + QCOMPARE(QBrush(), obj1.brush()); + + // const QBrush & QPainter::background() + // void QPainter::setBackground(const QBrush &) + QBrush var5(Qt::yellow); + obj1.setBackground(var5); + QCOMPARE(var5, obj1.background()); + obj1.setBackground(QBrush()); + QCOMPARE(QBrush(), obj1.background()); + + // bool QPainter::matrixEnabled() + // void QPainter::setMatrixEnabled(bool) + obj1.setMatrixEnabled(false); + QCOMPARE(false, obj1.matrixEnabled()); + obj1.setMatrixEnabled(true); + QCOMPARE(true, obj1.matrixEnabled()); + + // bool QPainter::viewTransformEnabled() + // void QPainter::setViewTransformEnabled(bool) + obj1.setViewTransformEnabled(false); + QCOMPARE(false, obj1.viewTransformEnabled()); + obj1.setViewTransformEnabled(true); + QCOMPARE(true, obj1.viewTransformEnabled()); +} + +Q_DECLARE_METATYPE(QPixmap) +Q_DECLARE_METATYPE(QPolygon) +Q_DECLARE_METATYPE(QBrush) +Q_DECLARE_METATYPE(QPen) +Q_DECLARE_METATYPE(QFont) +Q_DECLARE_METATYPE(QColor) +Q_DECLARE_METATYPE(QRegion) + +tst_QPainter::tst_QPainter() +{ + // QtTestCase sets this to false, but this turns off alpha pixmaps on Unix. + QApplication::setDesktopSettingsAware(TRUE); +} + +tst_QPainter::~tst_QPainter() +{ +} + +void tst_QPainter::init() +{ +} + +void tst_QPainter::cleanup() +{ +} + +/* tests the clipping operations in qt_format_text, making sure + the clip rectangle after the call is the same as before +*/ +void tst_QPainter::qt_format_text_clip() +{ + QVERIFY(1); + QSKIP( "Needs fixing...", SkipAll); + + QWidget *w = new QWidget( 0 ); + + int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine, + Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip, + Qt::AlignVCenter|Qt::TextWordWrap, + Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip, + 0 + }; + + int *m = modes; + while( *m ) { + { + QPainter p( w ); + QRegion clipreg = p.clipRegion(); + bool hasClipping = p.hasClipping(); + qreal tx = p.matrix().dx(); + qreal ty = p.matrix().dy(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + + p.setClipRect( QRect( 5, 5, 50, 50 ) ); + clipreg = p.clipRegion(); + hasClipping = p.hasClipping(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + } + { + QPainter p( w ); + p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) ); + QRegion clipreg = p.clipRegion(); + bool hasClipping = p.hasClipping(); + qreal tx = p.matrix().dx(); + qreal ty = p.matrix().dy(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + + p.setClipRect( QRect( 5, 5, 50, 50 ) ); + clipreg = p.clipRegion(); + hasClipping = p.hasClipping(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + } + { + QPainter p( w ); + QRegion clipreg = p.clipRegion(); + bool hasClipping = p.hasClipping(); + qreal tx = p.matrix().dx(); + qreal ty = p.matrix().dy(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + + p.setClipRect( QRect( 5, 5, 50, 50 )); + clipreg = p.clipRegion(); + hasClipping = p.hasClipping(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + } + { + QPainter p( w ); + p.setMatrix( QMatrix( 2, 1, 3, 4, 5, 6 ) ); + QRegion clipreg = p.clipRegion(); + bool hasClipping = p.hasClipping(); + qreal tx = p.matrix().dx(); + qreal ty = p.matrix().dy(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + + p.setClipRect(QRect( 5, 5, 50, 50 )); + clipreg = p.clipRegion(); + hasClipping = p.hasClipping(); + + p.drawText( 10, 10, 100, 100, *m, + "fooo" ); + + QVERIFY( clipreg == p.clipRegion() ); + QVERIFY( hasClipping == p.hasClipping() ); + QCOMPARE( tx, p.matrix().dx() ); + QCOMPARE( ty, p.matrix().dy() ); + } + ++m; + } + delete w; +} + +/* tests the bounding rect calculations in qt_format_text, making sure + the bounding rect has a reasonable value. +*/ +void tst_QPainter::qt_format_text_boundingRect() +{ + QVERIFY(1); + QSKIP( "Needs fixing...", SkipAll); + + { + const char * strings[] = { + "a\n\nb", + "abc", + "a\n \nb", + "this is a longer string", + "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233", + "aa\327\222\327\233aa", + "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233", + "\327\222\327\233aa", + "linebreakatend\n", + "some text longer than 30 chars with a line break at the end\n", + "some text\nwith line breaks\nin the middle\nand at the end\n", + "foo\n\n\nfoo", + 0 + }; + + int modes[] = { Qt::AlignVCenter|Qt::TextSingleLine, + Qt::AlignVCenter|Qt::TextSingleLine|Qt::TextDontClip, + Qt::AlignVCenter|Qt::TextWordWrap, + Qt::AlignVCenter|Qt::TextWordWrap|Qt::TextDontClip, + Qt::AlignLeft, + Qt::AlignCenter, + Qt::AlignRight, + 0 + }; + + QFont f; + for(int i = 5; i < 15; ++i) { + f.setPointSize(i); + QFontMetrics fm(f); + const char **str = strings; + while( *str ) { + int *m = modes; + while( *m ) { + QRect br = fm.boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) ); + QVERIFY( br.width() < 800 ); + + QRect br2 = fm.boundingRect( br.x(), br.y(), br.width(), br.height(), *m, QString::fromUtf8( *str ) ); + QCOMPARE( br, br2 ); +#if 0 + { + QPrinter printer; + printer.setOutputToFile(TRUE); + printer.setOutputFileName("tmp.prn"); + QPainter p(&printer); + QRect pbr = p.fontMetrics().boundingRect( 0, 0, 2000, 100, *m, QString::fromUtf8( *str ) ); + QCOMPARE(pbr, br); + } +#endif +#if !defined(QT_NO_PRINTER) && !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + { + QPrinter printer(QPrinter::HighResolution); + if (printer.printerName().isEmpty()) { + QSKIP( "No printers installed, skipping bounding rect test", + SkipSingle ); + break; + } + + printer.setOutputFileName("tmp.prn"); + QPainter p(&printer); + QRect pbr = p.fontMetrics().boundingRect( 0, 0, 12000, 600, *m, QString::fromUtf8( *str ) ); + QVERIFY(pbr.width() > 2*br.width()); + QVERIFY(pbr.height() > 2*br.height()); + } +#endif + ++m; + } + ++str; + } + } + } + + { + const char * strings[] = { + "a", + "a\nb", + "a\n\nb", + "abc", +// "a\n \nb", + "this is a longer string", +// "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233", +// "aa\327\222\327\233aa", +// "\327\222\327\223\327\233\327\223\327\222\327\233\327\222\327\223\327\233", +// "\327\222\327\233aa", +// "linebreakatend\n", +// "some text longer than 30 chars with a line break at the end\n", +// "some text\nwith line breaks\nin the middle\nand at the end\n", + "foo\n\n\nfoo", + "a\n\n\n\n\nb", + "a\n\n\n\n\n\nb", +// "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\nPhotoshop Album \343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202" +// "\347\231\273\351\214\262\346\203\205\345\240\261\343\201\214\350\246\213\343\201\244\343\201\213\343\202\211\343\201\252\343\201\204\343\201\213\347\204\241\345\212\271\343\201\252\343\201\237\343\202\201\343\200\201\n\343\202\222\350\265\267\345\213\225\343\201\247\343\201\215\343\201\276\343\201\233\343\202\223\343\200\202\345\206\215\343\202\244\343\203\263\343\202\271\343\203\210\343\203\274\343\203\253\343\201\227\343\201\246\343\201\217\343\201\240\343\201\225\343\201\204\343\200\202", + 0 + }; + + int modes[] = { Qt::AlignVCenter, + Qt::AlignLeft, + Qt::AlignCenter, + Qt::AlignRight, + 0 + }; + + + QFont f; + for(int i = 5; i < 15; ++i) { + f.setPointSize(i); + QFontMetrics fm(f); + const char **str = strings; + while( *str ) { + int *m = modes; + while( *m ) { + QString s = QString::fromUtf8(*str); + QRect br = fm.boundingRect(0, 0, 1000, 1000, *m, s ); + int lines = + s.count("\n"); + int expectedHeight = fm.height()+lines*fm.lineSpacing(); + QCOMPARE(br.height(), expectedHeight); + ++m; + } + ++str; + } + QRect br = fm.boundingRect(0, 0, 100, 0, Qt::TextWordWrap, + "A paragraph with gggggggggggggggggggggggggggggggggggg in the middle."); + QVERIFY(br.height() >= fm.height()+2*fm.lineSpacing()); + } + } +} + + +static const char* const maskSource_data[] = { +"16 13 6 1", +". c None", +"d c #000000", +"# c #999999", +"c c #cccccc", +"b c #ffff00", +"a c #ffffff", +"...#####........", +"..#aaaaa#.......", +".#abcbcba######.", +".#acbcbcaaaaaa#d", +".#abcbcbcbcbcb#d", +"#############b#d", +"#aaaaaaaaaa##c#d", +"#abcbcbcbcbbd##d", +".#abcbcbcbcbcd#d", +".#acbcbcbcbcbd#d", +"..#acbcbcbcbb#dd", +"..#############d", +"...ddddddddddddd"}; + +static const char* const maskResult_data[] = { +"16 13 6 1", +". c #ff0000", +"d c #000000", +"# c #999999", +"c c #cccccc", +"b c #ffff00", +"a c #ffffff", +"...#####........", +"..#aaaaa#.......", +".#abcbcba######.", +".#acbcbcaaaaaa#d", +".#abcbcbcbcbcb#d", +"#############b#d", +"#aaaaaaaaaa##c#d", +"#abcbcbcbcbbd##d", +".#abcbcbcbcbcd#d", +".#acbcbcbcbcbd#d", +"..#acbcbcbcbb#dd", +"..#############d", +"...ddddddddddddd"}; + + +void tst_QPainter::drawPixmap_comp_data() +{ + if (qApp->desktop()->depth() < 24) { + QSKIP("Test only works on 32 bit displays", SkipAll); + return; + } + + QTest::addColumn<uint>("dest"); + QTest::addColumn<uint>("source"); + + QTest::newRow("0% on 0%, 1") << 0x00000000u<< 0x00000000u; + QTest::newRow("0% on 0%, 2") << 0x00007fffu << 0x00ff007fu; + + QTest::newRow("50% on a=0%") << 0x00000000u << 0x7fff0000u; + QTest::newRow("50% on a=50%") << 0x7f000000u << 0x7fff0000u; + QTest::newRow("50% on deadbeef") << 0xdeafbeefu << 0x7fff0000u; + QTest::newRow("deadbeef on a=0%") << 0x00000000u << 0xdeadbeefu; + QTest::newRow("deadbeef on a=50%") << 0x7f000000u << 0xdeadbeefu; + QTest::newRow("50% blue on 50% red") << 0x7fff0000u << 0x7f0000ffu; + QTest::newRow("50% blue on 50% green") << 0x7f00ff00u << 0x7f0000ffu; + QTest::newRow("50% red on 50% green") << 0x7f00ff00u << 0x7fff0000u; + QTest::newRow("0% on 50%") << 0x7fff00ffu << 0x00ffffffu; + QTest::newRow("100% on deadbeef") << 0xdeafbeefu << 0xffabcdefu; + QTest::newRow("100% on a=0%") << 0x00000000u << 0xffabcdefu; +} + +QRgb qt_compose_alpha(QRgb source, QRgb dest) +{ + int r1 = qRed(dest), g1 = qGreen(dest), b1 = qBlue(dest), a1 = qAlpha(dest); + int r2 = qRed(source), g2 = qGreen(source), b2 = qBlue(source), a2 = qAlpha(source); + + int alpha = qMin(a2 + ((255 - a2) * a1 + 127) / 255, 255); + if (alpha == 0) + return qRgba(0, 0, 0, 0); + + return qRgba( + qMin((r2 * a2 + (255 - a2) * r1 * a1 / 255) / alpha, 255), + qMin((g2 * a2 + (255 - a2) * g1 * a1 / 255) / alpha, 255), + qMin((b2 * a2 + (255 - a2) * b1 * a1 / 255) / alpha, 255), + alpha); +} + +/* Tests that drawing masked pixmaps works +*/ +void tst_QPainter::drawPixmap_comp() +{ +#ifdef Q_WS_MAC + QSKIP("Mac has other ideas about alpha composition", SkipAll); +#endif + + QFETCH(uint, dest); + QFETCH(uint, source); + + QRgb expected = qt_compose_alpha(source, dest); + + QColor c1(qRed(dest), qGreen(dest), qBlue(dest), qAlpha(dest)); + QColor c2(qRed(source), qGreen(source), qBlue(source), qAlpha(source)); + + QPixmap destPm(10, 10), srcPm(10, 10); + destPm.fill(c1); + srcPm.fill(c2); + +#if defined(Q_WS_X11) + if (!destPm.x11PictureHandle()) + QSKIP("Requires XRender support", SkipAll); +#endif + + QPainter p(&destPm); + p.drawPixmap(0, 0, srcPm); + p.end(); + + QImage result = destPm.toImage().convertToFormat(QImage::Format_ARGB32); + bool different = false; + for (int y=0; y<result.height(); ++y) + for (int x=0; x<result.width(); ++x) { + bool diff; + if (qAlpha(expected) == 0) { + diff = qAlpha(result.pixel(x, y)) != 0; + } else { + // Compensate for possible roundoff / platform fudge + int off = 1; + QRgb pix = result.pixel(x, y); + diff = (qAbs(qRed(pix) - qRed(expected)) > off) + || (qAbs(qGreen(pix) - qGreen(expected)) > off) + || (qAbs(qBlue(pix) - qBlue(expected)) > off) + || (qAbs(qAlpha(pix) - qAlpha(expected)) > off); + } + if (diff && !different) + qDebug( "Different at %d,%d pixel [%d,%d,%d,%d] expected [%d,%d,%d,%d]", x, y, + qRed(result.pixel(x, y)), qGreen(result.pixel(x, y)), + qBlue(result.pixel(x, y)), qAlpha(result.pixel(x, y)), + qRed(expected), qGreen(expected), qBlue(expected), qAlpha(expected)); + different |= diff; + } + + QVERIFY(!different); +} + +void tst_QPainter::saveAndRestore_data() +{ + QVERIFY(1); + + QTest::addColumn<QFont>("font"); + QTest::addColumn<QPen>("pen"); + QTest::addColumn<QBrush>("brush"); + QTest::addColumn<QColor>("backgroundColor"); + QTest::addColumn<int>("backgroundMode"); + QTest::addColumn<QPoint>("brushOrigin"); + QTest::addColumn<QRegion>("clipRegion"); + QTest::addColumn<QRect>("window"); + QTest::addColumn<QRect>("viewport"); + + QPixmap pixmap(1, 1); + QPainter p(&pixmap); + QFont font = p.font(); + QPen pen = p.pen(); + QBrush brush = p.brush(); + QColor backgroundColor = p.background().color(); + Qt::BGMode backgroundMode = p.backgroundMode(); + QPoint brushOrigin = p.brushOrigin(); + QRegion clipRegion = p.clipRegion(); + QRect window = p.window(); + QRect viewport = p.viewport(); + + QTest::newRow("Original") << font << pen << brush << backgroundColor << int(backgroundMode) + << brushOrigin << clipRegion << window << viewport; + + QFont font2 = font; + font2.setPointSize( 24 ); + QTest::newRow("Modified font.pointSize, brush, backgroundColor, backgroundMode") + << font2 << pen << QBrush(Qt::red) << QColor(Qt::blue) << int(Qt::TransparentMode) + << brushOrigin << clipRegion << window << viewport; + + font2 = font; + font2.setPixelSize( 20 ); + QTest::newRow("Modified font.pixelSize, brushOrigin, pos") + << font2 << pen << brush << backgroundColor << int(backgroundMode) + << QPoint( 50, 32 ) << clipRegion << window << viewport; + + QTest::newRow("Modified clipRegion, window, viewport") + << font << pen << brush << backgroundColor << int(backgroundMode) + << brushOrigin << clipRegion.subtracted(QRect(10,10,50,30)) + << QRect(-500, -500, 500, 500 ) << QRect( 0, 0, 50, 50 ); +} + +void tst_QPainter::saveAndRestore() +{ + QFETCH( QFont, font ); + QFETCH( QPen, pen ); + QFETCH( QBrush, brush ); + QFETCH( QColor, backgroundColor ); + QFETCH( int, backgroundMode ); + QFETCH( QPoint, brushOrigin ); + QFETCH( QRegion, clipRegion ); + QFETCH( QRect, window ); + QFETCH( QRect, viewport ); + + QPixmap pixmap(1, 1); + QPainter painter(&pixmap); + + QFont font_org = painter.font(); + QPen pen_org = painter.pen(); + QBrush brush_org = painter.brush(); + QColor backgroundColor_org = painter.background().color(); + Qt::BGMode backgroundMode_org = painter.backgroundMode(); + QPoint brushOrigin_org = painter.brushOrigin(); + QRegion clipRegion_org = painter.clipRegion(); + QRect window_org = painter.window(); + QRect viewport_org = painter.viewport(); + + painter.save(); + painter.setFont( font ); + painter.setPen( QPen(pen) ); + painter.setBrush( brush ); + painter.setBackground( backgroundColor ); + painter.setBackgroundMode( (Qt::BGMode)backgroundMode ); + painter.setBrushOrigin( brushOrigin ); + painter.setClipRegion( clipRegion ); + painter.setWindow( window ); + painter.setViewport( viewport ); + painter.restore(); + + QCOMPARE( painter.font(), font_org ); + QCOMPARE( painter.font().pointSize(), font_org.pointSize() ); + QCOMPARE( painter.font().pixelSize(), font_org.pixelSize() ); + QCOMPARE( painter.pen(), pen_org ); + QCOMPARE( painter.brush(), brush_org ); + QCOMPARE( painter.background().color(), backgroundColor_org ); + QCOMPARE( painter.backgroundMode(), backgroundMode_org ); + QCOMPARE( painter.brushOrigin(), brushOrigin_org ); + QCOMPARE( painter.clipRegion(), clipRegion_org ); + QCOMPARE( painter.window(), window_org ); + QCOMPARE( painter.viewport(), viewport_org ); +} + +/* + Helper functions +*/ + +QColor tst_QPainter::baseColor( int k, int intensity ) +{ + int r = ( k & 1 ) * intensity; + int g = ( (k>>1) & 1 ) * intensity; + int b = ( (k>>2) & 1 ) * intensity; + return QColor( r, g, b ); +} + +QImage tst_QPainter::getResImage( const QString &dir, const QString &addition, const QString &extension ) +{ + QImage res; + QString resFilename = dir + QString( "/res_%1." ).arg( addition ) + extension; + if ( !res.load( resFilename ) ) { + QWARN(QString("Could not load result data %s %1").arg(resFilename).toLatin1()); + return QImage(); + } + return res; +} + +QBitmap tst_QPainter::getBitmap( const QString &dir, const QString &filename, bool mask ) +{ + QBitmap bm; + QString bmFilename = dir + QString( "/%1.xbm" ).arg( filename ); + if ( !bm.load( bmFilename ) ) { + QWARN(QString("Could not load bitmap '%1'").arg(bmFilename).toLatin1()); + return QBitmap(); + } + if ( mask ) { + QBitmap mask; + QString maskFilename = dir + QString( "/%1-mask.xbm" ).arg( filename ); + if ( !mask.load( maskFilename ) ) { + QWARN(QString("Could not load mask '%1'").arg(maskFilename).toLatin1()); + return QBitmap(); + } + bm.setMask( mask ); + } + return bm; +} + +static int getPaintedPixels(const QImage &image, const QColor &background) +{ + uint color = background.rgba(); + + int pixels = 0; + + for (int y = 0; y < image.height(); ++y) + for (int x = 0; x < image.width(); ++x) + if (image.pixel(x, y) != color) + ++pixels; + + return pixels; +} + +static QRect getPaintedSize(const QImage &image, const QColor &background) +{ + // not the fastest but at least it works.. + int xmin = image.width() + 1; + int xmax = -1; + int ymin = image.height() +1; + int ymax = -1; + + uint color = background.rgba(); + + for ( int y = 0; y < image.height(); ++y ) { + for ( int x = 0; x < image.width(); ++x ) { + QRgb pixel = image.pixel( x, y ); + if ( pixel != color && x < xmin ) + xmin = x; + if ( pixel != color && x > xmax ) + xmax = x; + if ( pixel != color && y < ymin ) + ymin = y; + if ( pixel != color && y > ymax ) + ymax = y; + } + } + + return QRect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1); +} + +static QRect getPaintedSize(const QPixmap &pm, const QColor &background) +{ + return getPaintedSize(pm.toImage(), background); +} + +void tst_QPainter::initFrom() +{ + QWidget *widget = new QWidget(); + QPalette pal = widget->palette(); + pal.setColor(QPalette::Foreground, QColor(255, 0, 0)); + pal.setBrush(QPalette::Background, QColor(0, 255, 0)); + widget->setPalette(pal); + + QFont font = widget->font(); + font.setPointSize(26); + font.setItalic(true); + widget->setFont(font); + + QPixmap pm(100, 100); + QPainter p(&pm); + p.initFrom(widget); + + QCOMPARE(p.font(), font); + QCOMPARE(p.pen().color(), pal.color(QPalette::Foreground)); + QCOMPARE(p.background(), pal.background()); + + delete widget; +} + +void tst_QPainter::drawBorderPixmap() +{ + QPixmap src(79,79); + src.fill(Qt::transparent); + + QImage pm(200,200,QImage::Format_RGB32); + QPainter p(&pm); + p.setTransform(QTransform(-1,0,0,-1,173.5,153.5)); + qDrawBorderPixmap(&p, QRect(0,0,75,105), QMargins(39,39,39,39), src, QRect(0,0,79,79), QMargins(39,39,39,39), + QTileRules(Qt::StretchTile,Qt::StretchTile), 0); +} + +void tst_QPainter::drawPixmapFragments() +{ + QPixmap origPixmap(20, 20); + QPixmap resPixmap(20, 20); + QPainter::PixmapFragment fragments[4] = { {15, 15, 0, 0, 10, 10, 1, 1, 0, 1}, + { 5, 15, 10, 0, 10, 10, 1, 1, 0, 1}, + {15, 5, 0, 10, 10, 10, 1, 1, 0, 1}, + { 5, 5, 10, 10, 10, 10, 1, 1, 0, 1} }; + { + QPainter p(&origPixmap); + p.fillRect(0, 0, 10, 10, Qt::red); + p.fillRect(10, 0, 10, 10, Qt::green); + p.fillRect(0, 10, 10, 10, Qt::blue); + p.fillRect(10, 10, 10, 10, Qt::yellow); + } + { + QPainter p(&resPixmap); + p.drawPixmapFragments(fragments, 4, origPixmap); + } + + QImage origImage = origPixmap.toImage().convertToFormat(QImage::Format_ARGB32); + QImage resImage = resPixmap.toImage().convertToFormat(QImage::Format_ARGB32); + + QVERIFY(resImage.size() == resPixmap.size()); + QVERIFY(resImage.pixel(5, 5) == origImage.pixel(15, 15)); + QVERIFY(resImage.pixel(5, 15) == origImage.pixel(15, 5)); + QVERIFY(resImage.pixel(15, 5) == origImage.pixel(5, 15)); + QVERIFY(resImage.pixel(15, 15) == origImage.pixel(5, 5)); + + + QPainter::PixmapFragment fragment = QPainter::PixmapFragment::create(QPointF(20, 20), QRectF(30, 30, 2, 2)); + QVERIFY(fragment.x == 20); + QVERIFY(fragment.y == 20); + QVERIFY(fragment.sourceLeft == 30); + QVERIFY(fragment.sourceTop == 30); + QVERIFY(fragment.width == 2); + QVERIFY(fragment.height == 2); + QVERIFY(fragment.scaleX == 1); + QVERIFY(fragment.scaleY == 1); + QVERIFY(fragment.rotation == 0); + QVERIFY(fragment.opacity == 1); +} + +void tst_QPainter::drawLine_data() +{ + QTest::addColumn<QLine>("line"); + + QTest::newRow("0-45") << QLine(0, 20, 100, 0); + QTest::newRow("45-90") << QLine(0, 100, 20, 0); + QTest::newRow("90-135") << QLine(20, 100, 0, 0); + QTest::newRow("135-180") << QLine(100, 20, 0, 0); + QTest::newRow("180-225") << QLine(100, 0, 0, 20); + QTest::newRow("225-270") << QLine(20, 0, 0, 100); + QTest::newRow("270-315") << QLine(0, 0, 20, 100); + QTest::newRow("315-360") << QLine(0, 0, 100, 20); +} + +void tst_QPainter::drawLine() +{ + const int offset = 5; + const int epsilon = 1; // allow for one pixel difference + + QFETCH(QLine, line); + + QPixmap pixmapUnclipped(qMin(line.x1(), line.x2()) + + 2*offset + qAbs(line.dx()), + qMin(line.y1(), line.y2()) + + 2*offset + qAbs(line.dy())); + + { // unclipped + pixmapUnclipped.fill(Qt::white); + QPainter p(&pixmapUnclipped); + p.translate(offset, offset); + p.setPen(QPen(Qt::black)); + p.drawLine(line); + p.end(); + + const QRect painted = getPaintedSize(pixmapUnclipped, Qt::white); + + QLine l = line; + l.translate(offset, offset); + QVERIFY(qAbs(painted.width() - qAbs(l.dx())) <= epsilon); + QVERIFY(qAbs(painted.height() - qAbs(l.dy())) <= epsilon); + QVERIFY(qAbs(painted.top() - qMin(l.y1(), l.y2())) <= epsilon); + QVERIFY(qAbs(painted.left() - qMin(l.x1(), l.x2())) <= epsilon); + QVERIFY(qAbs(painted.bottom() - qMax(l.y1(), l.y2())) <= epsilon); + QVERIFY(qAbs(painted.right() - qMax(l.x1(), l.x2())) <= epsilon); + } + + QPixmap pixmapClipped(qMin(line.x1(), line.x2()) + + 2*offset + qAbs(line.dx()), + qMin(line.y1(), line.y2()) + + 2*offset + qAbs(line.dy())); + { // clipped + const QRect clip = QRect(line.p1(), line.p2()).normalized(); + + pixmapClipped.fill(Qt::white); + QPainter p(&pixmapClipped); + p.translate(offset, offset); + p.setClipRect(clip); + p.setPen(QPen(Qt::black)); + p.drawLine(line); + p.end(); + } + + const QImage unclipped = pixmapUnclipped.toImage(); + const QImage clipped = pixmapClipped.toImage(); + QCOMPARE(unclipped, clipped); +} + +void tst_QPainter::drawLine_clipped() +{ + QImage image(16, 1, QImage::Format_ARGB32_Premultiplied); + image.fill(0x0); + + QPainter p(&image); + p.setPen(QPen(Qt::black, 10)); + + // this should fill the whole image + p.drawLine(-1, -1, 17, 1); + p.end(); + + for (int x = 0; x < 16; ++x) + QCOMPARE(image.pixel(x, 0), 0xff000000); +} + +void tst_QPainter::drawLine_task121143() +{ + QPen pen(Qt::black); + + QImage image(5, 5, QImage::Format_ARGB32_Premultiplied); + image.fill(0xffffffff); + QPainter p(&image); + p.setPen(pen); + p.drawLine(QLine(0, 0+4, 0+4, 0)); + p.end(); + + QImage expected(5, 5, QImage::Format_ARGB32_Premultiplied); + expected.fill(0xffffffff); + for (int x = 0; x < 5; ++x) + expected.setPixel(x, 5-x-1, pen.color().rgb()); + + QCOMPARE(image, expected); +} + +void tst_QPainter::drawLine_task190634() +{ + QPen pen(Qt::black, 3); + + QImage image(32, 32, QImage::Format_ARGB32_Premultiplied); + QPainter p(&image); + p.fillRect(0, 0, image.width(), image.height(), Qt::white); + + p.setPen(pen); + p.drawLine(QLineF(2, -1.6, 10, -1.6)); + p.end(); + + const uint *data = reinterpret_cast<uint *>(image.bits()); + + for (int i = 0; i < image.width() * image.height(); ++i) + QCOMPARE(data[i], 0xffffffff); + + p.begin(&image); + p.fillRect(0, 0, image.width(), image.height(), Qt::white); + + p.setPen(pen); + p.drawLine(QLineF(-1.6, 2, -1.6, 10)); + p.end(); + + data = reinterpret_cast<uint *>(image.bits()); + + for (int i = 0; i < image.width() * image.height(); ++i) + QCOMPARE(data[i], 0xffffffff); + + p.begin(&image); + p.fillRect(0, 0, image.width(), image.height(), Qt::white); + + p.setPen(pen); + p.drawLine( QPoint(2,-2), QPoint(3,-5) ); + p.end(); + + data = reinterpret_cast<uint *>(image.bits()); + + for (int i = 0; i < image.width() * image.height(); ++i) + QCOMPARE(data[i], 0xffffffff); +} + +void tst_QPainter::drawLine_task229459() +{ + QImage image(32, 32, QImage::Format_ARGB32_Premultiplied); + image.fill(0x0); + QPen pen(Qt::black, 64); + + QPainter p(&image); + p.setPen(pen); + p.drawLine(-8, -8, 10000000, 10000000); + p.end(); + + QImage expected = image; + expected.fill(0xff000000); + + QCOMPARE(image, expected); +} + +void tst_QPainter::drawLine_task234891() +{ + QImage img(100, 1000, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + QImage expected = img; + + QPainter p(&img); + p.setPen(QPen(QBrush(QColor(255,0,0)), 6)); + p.drawLine(QPointF(25000,100),QPointF(30000,105)); + + p.setPen(QPen(QBrush(QColor(0,255,0)), 6)); + p.drawLine(QPointF(30000,150),QPointF(35000,155)); + + p.setPen(QPen(QBrush(QColor(0,0,255)), 6)); + p.drawLine(QPointF(65000,200),QPointF(66000,205)); + + QCOMPARE(expected, img); +} + +void tst_QPainter::drawLine_task216948() +{ + QImage img(1, 10, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + + QPainter p(&img); + QLine line(10, 0, 10, 10); + p.translate(-10, 0); + p.drawLine(line); + p.end(); + + for (int i = 0; i < img.height(); ++i) + QCOMPARE(img.pixel(0, i), QColor(Qt::black).rgba()); +} + +void tst_QPainter::drawRect() +{ + QFETCH(QRect, rect); + QFETCH(bool, usePen); + + QPixmap pixmap(rect.x() + rect.width() + 10, + rect.y() + rect.height() + 10); + { + pixmap.fill(Qt::white); + QPainter p(&pixmap); + p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); + p.setBrush(Qt::black); + p.drawRect(rect); + p.end(); + + int increment = usePen ? 1 : 0; + + const QRect painted = getPaintedSize(pixmap, Qt::white); + QCOMPARE(painted.width(), rect.width() + increment); + QCOMPARE(painted.height(), rect.height() + increment); + } +} + +void tst_QPainter::drawRect2() +{ + QImage image(64, 64, QImage::Format_ARGB32_Premultiplied); + { + image.fill(0xffffffff); + + QTransform transform(0.368567, 0, 0, 0, 0.368567, 0, 0.0289, 0.0289, 1); + + QPainter p(&image); + p.setTransform(transform); + p.setBrush(Qt::red); + p.setPen(Qt::NoPen); + p.drawRect(QRect(14, 14, 39, 39)); + p.end(); + + QRect fill = getPaintedSize(image, Qt::white); + image.fill(0xffffffff); + + p.begin(&image); + p.setTransform(transform); + p.drawRect(QRect(14, 14, 39, 39)); + p.end(); + + QRect stroke = getPaintedSize(image, Qt::white); + QCOMPARE(stroke.adjusted(1, 1, 0, 0), fill.adjusted(0, 0, 1, 1)); + } +} + +void tst_QPainter::fillRect() +{ + QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); + image.fill(QColor(0, 0, 0, 0).rgba()); + + QPainter p(&image); + + p.fillRect(0, 0, 100, 100, QColor(255, 0, 0, 127)); + +// pixmap.save("bla1.png", "PNG"); + QCOMPARE(getPaintedSize(image, QColor(0, 0, 0, 0)), + QRect(0, 0, 100, 100)); + QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)).isValid(), + QRect().isValid()); + + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(50, 0, 50, 100, QColor(0, 0, 255, 255)); + + QCOMPARE(getPaintedSize(image, QColor(127, 0, 0, 127)), + QRect(50, 0, 50, 100)); + QCOMPARE(getPaintedSize(image, QColor(0, 0, 127, 127)), + QRect(0, 0, 50, 100)); +} + +void tst_QPainter::fillRect2() +{ + QRgb background = 0x0; + + QImage img(1, 20, QImage::Format_ARGB32_Premultiplied); + img.fill(background); + + QPainter p(&img); + + QRectF rect(0, 1, 1.2, 18); + p.fillRect(rect, Qt::black); + + p.end(); + + QCOMPARE(img.pixel(0, 0), background); + QCOMPARE(img.pixel(0, img.height() - 1), background); + + QCOMPARE(img.pixel(0, 1), img.pixel(0, 2)); + QCOMPARE(img.pixel(0, img.height() - 2), img.pixel(0, img.height() - 3)); +} + +void tst_QPainter::fillRect3() +{ + QImage img(1, 1, QImage::Format_ARGB32_Premultiplied); + img.fill(QColor(Qt::black).rgba()); + + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(img.rect(), Qt::transparent); + p.end(); + + QCOMPARE(img.pixel(0, 0), 0U); +} + +void tst_QPainter::fillRect4() +{ + QImage image(100, 1, QImage::Format_ARGB32_Premultiplied); + image.fill(0x0); + + QImage expected = image; + expected.fill(0xffffffff); + + QPainter p(&image); + p.scale(1.1, 1); + p.setPen(Qt::NoPen); + + for (int i = 0; i < 33; ++i) + p.fillRect(QRectF(3 * i, 0, 3, 1), Qt::white); + + p.end(); + + QCOMPARE(image, expected); +} + +void tst_QPainter::drawPath_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QRect>("expectedBounds"); + QTest::addColumn<int>("expectedPixels"); + + { + QPainterPath p; + p.addRect(2, 2, 10, 10); + QTest::newRow("int-aligned rect") << p << QRect(2, 2, 10, 10) << 10 * 10; + } + + { + QPainterPath p; + p.addRect(2.25, 2.25, 10, 10); + QTest::newRow("non-aligned rect") << p << QRect(3, 3, 10, 10) << 10 * 10; + } + + { + QPainterPath p; + p.addRect(2.25, 2.25, 10.5, 10.5); + QTest::newRow("non-aligned rect 2") << p << QRect(3, 3, 10, 10) << 10 * 10; + } + + { + QPainterPath p; + p.addRect(2.5, 2.5, 10, 10); + QTest::newRow("non-aligned rect 3") << p << QRect(3, 3, 10, 10) << 10 * 10; + } + + { + QPainterPath p; + p.addRect(2, 2, 10, 10); + p.addRect(4, 4, 6, 6); + QTest::newRow("rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6; + } + + { + QPainterPath p; + p.addRect(2, 2, 10, 10); + p.addRect(4, 4, 6, 6); + p.addRect(6, 6, 2, 2); + QTest::newRow("rect-in-rect-in-rect") << p << QRect(2, 2, 10, 10) << 10 * 10 - 6 * 6 + 2 * 2; + } +} + +void tst_QPainter::drawPath() +{ + QFETCH(QPainterPath, path); + QFETCH(QRect, expectedBounds); + QFETCH(int, expectedPixels); + + const int offset = 2; + + QImage image(expectedBounds.width() + 2 * offset, expectedBounds.height() + 2 * offset, + QImage::Format_ARGB32_Premultiplied); + image.fill(QColor(Qt::white).rgb()); + + QPainter p(&image); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.translate(offset - expectedBounds.left(), offset - expectedBounds.top()); + p.drawPath(path); + p.end(); + + const QRect paintedBounds = getPaintedSize(image, Qt::white); + + QCOMPARE(paintedBounds.x(), offset); + QCOMPARE(paintedBounds.y(), offset); + QCOMPARE(paintedBounds.width(), expectedBounds.width()); + QCOMPARE(paintedBounds.height(), expectedBounds.height()); + + if (expectedPixels != -1) { + int paintedPixels = getPaintedPixels(image, Qt::white); + QCOMPARE(paintedPixels, expectedPixels); + } +} + +void tst_QPainter::drawPath2() +{ + const int w = 50; + + for (int h = 5; h < 200; ++h) { + QPainterPath p1, p2; + p1.lineTo(w, 0); + p1.lineTo(w, h); + + p2.lineTo(w, h); + p2.lineTo(0, h); + + const int offset = 2; + + QImage image(w + 2 * offset, h + 2 * offset, + QImage::Format_ARGB32_Premultiplied); + image.fill(QColor(Qt::white).rgb()); + + QPainter p(&image); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.translate(offset, offset); + p.drawPath(p1); + p.end(); + + const int p1Pixels = getPaintedPixels(image, Qt::white); + + image.fill(QColor(Qt::white).rgb()); + p.begin(&image); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.translate(offset, offset); + p.drawPath(p2); + p.end(); + + const int p2Pixels = getPaintedPixels(image, Qt::white); + + QCOMPARE(p1Pixels + p2Pixels, w * h); + } +} + +void tst_QPainter::drawPath3() +{ +#if !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN) + QImage imgA(400, 400, QImage::Format_RGB32); +#else + QImage imgA(100, 100, QImage::Format_RGB32); +#endif + imgA.fill(0xffffff); + QImage imgB = imgA; + + QPainterPath path; + for (int y = 0; y < imgA.height(); ++y) { + for (int x = 0; x < imgA.width(); ++x) { + if ((x + y) & 1) { + imgA.setPixel(x, y, 0); + path.addRect(x, y, 1, 1); + } + } + } + + QPainter p(&imgB); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + + p.drawPath(path); + p.end(); + + QVERIFY(imgA == imgB); + + imgA.invertPixels(); + imgB.fill(0xffffff); + + p.begin(&imgB); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + + QRectF rect(0, 0, imgA.width(), imgA.height()); + path.addRect(rect.adjusted(-10, -10, 10, 10)); + p.drawPath(path); + p.end(); + + QVERIFY(imgA == imgB); + + path.setFillRule(Qt::WindingFill); + imgB.fill(0xffffff); + + p.begin(&imgB); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + QRect clip = rect.adjusted(10, 10, -10, -10).toRect(); + p.setClipRect(clip); + p.drawPath(path); + p.end(); + + QCOMPARE(getPaintedPixels(imgB, Qt::white), clip.width() * clip.height()); +} + +void tst_QPainter::drawEllipse_data() +{ + QTest::addColumn<QSize>("size"); + QTest::addColumn<bool>("usePen"); + + // The current drawEllipse algorithm (drawEllipse_midpoint_i in + // qpaintengine_raster.cpp) draws ellipses that are too wide if the + // ratio between width and hight is too large/small (task 114874). Those + // ratios are therefore currently avoided. + for (int w = 10; w < 128; w += 7) { + for (int h = w/2; h < qMin(2*w, 128); h += 13) { + QString s = QString("%1x%2").arg(w).arg(h); + QTest::newRow(QString("%1 with pen").arg(s).toLatin1()) << QSize(w, h) << true; + QTest::newRow(QString("%1 no pen").arg(s).toLatin1()) << QSize(w, h) << false; + } + } +} + +void tst_QPainter::drawEllipse() +{ + QFETCH(QSize, size); + QFETCH(bool, usePen); + + const int offset = 10; + QRect rect(QPoint(offset, offset), size); + + QImage image(size.width() + 2 * offset, size.height() + 2 * offset, + QImage::Format_ARGB32_Premultiplied); + image.fill(QColor(Qt::white).rgb()); + + QPainter p(&image); + p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); + p.setBrush(Qt::black); + p.drawEllipse(rect); + p.end(); + + QPixmap pixmap = QPixmap::fromImage(image); + + const QRect painted = getPaintedSize(pixmap, Qt::white); + + QCOMPARE(painted.x(), rect.x()); + QCOMPARE(painted.y(), rect.y() + (usePen ? 0 : 1)); + QCOMPARE(painted.width(), size.width() + (usePen ? 1 : 0)); + QCOMPARE(painted.height(), size.height() + (usePen ? 1 : -1)); +} + +void tst_QPainter::drawClippedEllipse_data() +{ + QTest::addColumn<QRect>("rect"); + + for (int w = 20; w < 128; w += 7) { + for (int h = w/2; h < qMin(2*w, 128); h += 13) { + QString s = QString("%1x%2").arg(w).arg(h); + QTest::newRow(QString("%1 top").arg(s).toLatin1()) << QRect(0, -h/2, w, h); + QTest::newRow(QString("%1 topright").arg(s).toLatin1()) << QRect(w/2, -h/2, w, h); + QTest::newRow(QString("%1 right").arg(s).toLatin1()) << QRect(w/2, 0, w, h); + QTest::newRow(QString("%1 bottomright").arg(s).toLatin1()) << QRect(w/2, h/2, w, h); + QTest::newRow(QString("%1 bottom").arg(s).toLatin1()) << QRect(0, h/2, w, h); + QTest::newRow(QString("%1 bottomleft").arg(s).toLatin1()) << QRect(-w/2, h/2, w, h); + QTest::newRow(QString("%1 left").arg(s).toLatin1()) << QRect(-w/2, 0, w, h); + QTest::newRow(QString("%1 topleft").arg(s).toLatin1()) << QRect(-w/2, -h/2, w, h); + } + } +} + +void tst_QPainter::drawClippedEllipse() +{ + QFETCH(QRect, rect); + if (sizeof(qreal) != sizeof(double)) + QSKIP("Test only works for qreal==double", SkipAll); + QImage image(rect.width() + 1, rect.height() + 1, + QImage::Format_ARGB32_Premultiplied); + QRect expected = QRect(rect.x(), rect.y(), rect.width()+1, rect.height()+1) + & QRect(0, 0, image.width(), image.height()); + + + image.fill(QColor(Qt::white).rgb()); + QPainter p(&image); + p.drawEllipse(rect); + p.end(); + + QPixmap pixmap = QPixmap::fromImage(image); + const QRect painted = getPaintedSize(pixmap, Qt::white); + + QCOMPARE(painted.x(), expected.x()); + QCOMPARE(painted.y(), expected.y()); + QCOMPARE(painted.width(), expected.width()); + QCOMPARE(painted.height(), expected.height()); + +} + +void tst_QPainter::drawRoundRect() +{ + QFETCH(QRect, rect); + QFETCH(bool, usePen); + +#ifdef Q_WS_MAC + if (QTest::currentDataTag() == QByteArray("rect(6, 12, 3, 14) with pen") || + QTest::currentDataTag() == QByteArray("rect(6, 17, 3, 25) with pen") || + QTest::currentDataTag() == QByteArray("rect(10, 6, 10, 3) with pen") || + QTest::currentDataTag() == QByteArray("rect(10, 12, 10, 14) with pen") || + QTest::currentDataTag() == QByteArray("rect(13, 45, 17, 80) with pen") || + QTest::currentDataTag() == QByteArray("rect(13, 50, 17, 91) with pen") || + QTest::currentDataTag() == QByteArray("rect(17, 6, 24, 3) with pen") || + QTest::currentDataTag() == QByteArray("rect(24, 12, 38, 14) with pen")) + QSKIP("The Mac paint engine is off-by-one on certain rect sizes", SkipSingle); +#endif + QPixmap pixmap(rect.x() + rect.width() + 10, + rect.y() + rect.height() + 10); + { + pixmap.fill(Qt::white); + QPainter p(&pixmap); + p.setPen(usePen ? QPen(Qt::black) : QPen(Qt::NoPen)); + p.setBrush(Qt::black); + p.drawRoundRect(rect); + p.end(); + + int increment = usePen ? 1 : 0; + + const QRect painted = getPaintedSize(pixmap, Qt::white); + QCOMPARE(painted.width(), rect.width() + increment); + QCOMPARE(painted.height(), rect.height() + increment); + } +} + +Q_DECLARE_METATYPE(QImage::Format) + +void tst_QPainter::qimageFormats_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::newRow("QImage::Format_RGB32") << QImage::Format_RGB32; + QTest::newRow("QImage::Format_ARGB32") << QImage::Format_ARGB32; + QTest::newRow("QImage::Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("QImage::Format_RGB16") << QImage::Format_RGB16; + QTest::newRow("Qimage::Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("Qimage::Format_RGB666") << QImage::Format_RGB666; + QTest::newRow("Qimage::Format_RGB555") << QImage::Format_RGB555; + QTest::newRow("Qimage::Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied; + QTest::newRow("Qimage::Format_RGB888") << QImage::Format_RGB888; +} + +/* + Tests that QPainter can paint on various QImage formats. +*/ +void tst_QPainter::qimageFormats() +{ + QFETCH(QImage::Format, format); + + const QSize size(100, 100); + QImage image(size, format); + image.fill(0); + + const QColor testColor(Qt::red); + QPainter p(&image); + QVERIFY(p.isActive()); + p.setBrush(QBrush(testColor)); + p.drawRect(QRect(QPoint(0,0), size)); + QCOMPARE(image.pixel(50, 50), testColor.rgb()); +} + +void tst_QPainter::fillData() +{ + QTest::addColumn<QRect>("rect"); + QTest::addColumn<bool>("usePen"); + + for (int w = 3; w < 50; w += 7) { + for (int h = 3; h < 50; h += 11) { + int x = w/2 + 5; + int y = h/2 + 5; + QTest::newRow(QString("rect(%1, %2, %3, %4) with pen").arg(x).arg(y).arg(w).arg(h).toLatin1()) + << QRect(x, y, w, h) << true; + QTest::newRow(QString("rect(%1, %2, %3, %4) no pen").arg(x).arg(y).arg(w).arg(h).toLatin1()) + << QRect(x, y, w, h) << false; + } + } +} + +/* + Test that drawline works properly after setWindow has been called. +*/ +void tst_QPainter::setWindow() +{ + QPixmap pixmap(600, 600); + pixmap.fill(QColor(Qt::white)); + + QPainter painter(&pixmap); + painter.setWindow(0, 0, 3, 3); + painter.drawLine(1, 1, 2, 2); + + const QRect painted = getPaintedSize(pixmap, Qt::white); + QVERIFY(195 < painted.y() && painted.y() < 205); // correct value is around 200 + QVERIFY(195 < painted.height() && painted.height() < 205); // correct value is around 200 +} + +void tst_QPainter::combinedMatrix() +{ + QPixmap pm(64, 64); + + QPainter p(&pm); + p.setWindow(0, 0, 1, 1); + p.setViewport(32, 0, 32, 32); + + p.translate(0.5, 0.5); + + QMatrix cm = p.combinedMatrix(); + + QPointF pt = QPointF(0, 0) * cm; + + QCOMPARE(pt.x(), 48.0); + QCOMPARE(pt.y(), 16.0); +} + +void tst_QPainter::textOnTransparentImage() +{ + bool foundPixel = false; + QImage image(10, 10, QImage::Format_ARGB32_Premultiplied); + image.fill(qRgba(0, 0, 0, 0)); // transparent + { + QPainter painter(&image); + painter.setPen(QColor(255, 255, 255)); + painter.drawText(0, 10, "W"); + } + for (int x = 0; x < image.width(); ++x) + for (int y = 0; y < image.height(); ++y) + if (image.pixel(x, y) != 0) + foundPixel = true; + QVERIFY(foundPixel); +} + +void tst_QPainter::renderHints() +{ + QImage img(1, 1, QImage::Format_RGB32); + + QPainter p(&img); + + // Turn off all... + p.setRenderHints(QPainter::RenderHints(0xffffffff), false); + QCOMPARE(p.renderHints(), QPainter::RenderHints(0)); + + // Single set/get + p.setRenderHint(QPainter::Antialiasing); + QVERIFY(p.renderHints() & QPainter::Antialiasing); + + p.setRenderHint(QPainter::Antialiasing, false); + QVERIFY(!(p.renderHints() & QPainter::Antialiasing)); + + // Multi set/get + p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + QVERIFY(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform)); + + p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); + QVERIFY(!(p.renderHints() & (QPainter::Antialiasing | QPainter::SmoothPixmapTransform))); +} + +int countPixels(const QImage &img, const QRgb &color) +{ + int count = 0; + for (int y = 0; y < img.height(); ++y) { + for (int x = 0; x < img.width(); ++x) { + count += ((img.pixel(x, y) & 0xffffff) == color); + } + } + return count; +} + +template <typename T> +void testClipping(QImage &img) +{ + QPainterPath a, b; + a.addRect(QRect(2, 2, 4, 4)); + b.addRect(QRect(4, 4, 4, 4)); + QPainter p(&img); + + p.end(); + img.fill(0x0); + p.begin(&img); + p.setClipPath(a); + p.setClipPath(b, Qt::IntersectClip); + + p.setClipping(false); + p.setPen(Qt::NoPen); + p.setBrush(QColor(0xff0000)); + p.drawRect(T(0, 0, 10, 10)); + + p.setClipping(true); + p.setBrush(QColor(0x00ff00)); + p.drawRect(T(0, 0, 10, 10)); + + QCOMPARE(countPixels(img, 0xff0000), 96); + QCOMPARE(countPixels(img, 0x00ff00), 4); +} + +void tst_QPainter::disableEnableClipping() +{ + QImage img(10, 10, QImage::Format_RGB32); + + testClipping<QRectF>(img); + testClipping<QRect>(img); +} + +void tst_QPainter::setClipRect() +{ + QImage img(10, 10, QImage::Format_RGB32); + // simple test to let valgrind check for buffer overflow + { + QPainter p(&img); + p.setClipRect(-10, -10, 100, 100); + p.fillRect(-10, -10, 100, 100, QBrush(QColor(Qt::red))); + } + + // rects with negative width/height + { + QPainter p(&img); + p.setClipRect(QRect(10, 10, -10, 10)); + QVERIFY(p.clipRegion().isEmpty()); + p.setClipRect(QRect(10, 10, 10, -10)); + QVERIFY(p.clipRegion().isEmpty()); + p.setClipRect(QRectF(10.5, 10.5, -10.5, 10.5)); + QVERIFY(p.clipRegion().isEmpty()); + p.setClipRect(QRectF(10.5, 10.5, 10.5, -10.5)); + QVERIFY(p.clipRegion().isEmpty()); + } +} + +/* + This tests the two different clipping approaches in QRasterPaintEngine, + one when using a QRegion and one when using a QPainterPath. They should + give equal results. +*/ +void tst_QPainter::setEqualClipRegionAndPath_data() +{ + QTest::addColumn<QSize>("deviceSize"); + QTest::addColumn<QRegion>("region"); + + QTest::newRow("empty") << QSize(100, 100) << QRegion(); + QTest::newRow("simple rect") << QSize(100, 100) + << QRegion(QRect(5, 5, 10, 10)); + + QVector<QRect> rects; + QRegion region; + + rects << QRect(5, 5, 10, 10) << QRect(20, 20, 10, 10); + region.setRects(rects.constData(), rects.size()); + QTest::newRow("two rects") << QSize(100, 100) << region; + + rects.clear(); + rects << QRect(5, 5, 10, 10) << QRect(20, 5, 10, 10); + region.setRects(rects.constData(), rects.size()); + QTest::newRow("two x-adjacent rects") << QSize(100, 100) << region; + + rects.clear(); + rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); + region.setRects(rects.constData(), rects.size()); + QTest::newRow("two x-adjacent rects 2") << QSize(100, 100) << region; + + rects.clear(); + rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); + region.setRects(rects.constData(), rects.size()); + QTest::newRow("two x-adjacent rects 3") << QSize(50, 50) << region; + + rects.clear(); + rects << QRect(0, 0, 10, 100) << QRect(12, 0, 10, 100); + region.setRects(rects.constData(), rects.size()); + QTest::newRow("two x-adjacent rects 4") << QSize(101, 101) << region; + + region = QRegion(QRect(0, 0, 200, 200), QRegion::Ellipse); + + QTest::newRow("ellipse") << QSize(190, 200) << region; + + region ^= QRect(50, 50, 50, 50); + QTest::newRow("ellipse 2") << QSize(200, 200) << region; +} + +void tst_QPainter::setEqualClipRegionAndPath() +{ + QFETCH(QSize, deviceSize); + QFETCH(QRegion, region); + + QPainterPath path; + path.addRegion(region); + + QImage img1(deviceSize.width(), deviceSize.height(), + QImage::Format_ARGB32); + QImage img2(deviceSize.width(), deviceSize.height(), + QImage::Format_ARGB32); + img1.fill(0x12345678); + img2.fill(0x12345678); + + { + QPainter p(&img1); + p.setClipRegion(region); + p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red)); + } + { + QPainter p(&img2); + p.setClipPath(path); + p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red)); + } + +#if 0 + if (img1 != img2) { + img1.save("setEqualClipRegionAndPath_1.xpm", "XPM"); + img2.save("setEqualClipRegionAndPath_2.xpm", "XPM"); + } +#endif + QCOMPARE(img1, img2); + +#if 0 + // rotated + img1.fill(0x12345678); + img2.fill(0x12345678); + + { + QPainter p(&img1); + p.rotate(25); + p.setClipRegion(region); + p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red)); + } + { + QPainter p(&img2); + p.rotate(25); + p.setClipPath(path); + p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red)); + } + +#if 1 + if (img1 != img2) { + img1.save("setEqualClipRegionAndPath_1.xpm", "XPM"); + img2.save("setEqualClipRegionAndPath_2.xpm", "XPM"); + } +#endif + QCOMPARE(img1, img2); +#endif + + img1.fill(0x12345678); + img2.fill(0x12345678); + + // simple intersectclip + img1.fill(0x12345678); + img2.fill(0x12345678); + { + QPainter p(&img1); + p.setClipRegion(region); + p.setClipRegion(region, Qt::IntersectClip); + p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red)); + } + { + QPainter p(&img2); + p.setClipPath(path); + p.setClipPath(path, Qt::IntersectClip); + p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red)); + } +#if 0 + if (img1 != img2) { + img1.save("setEqualClipRegionAndPath_1.png", "PNG"); + img2.save("setEqualClipRegionAndPath_2.png", "PNG"); + } +#endif + QCOMPARE(img1, img2); + + img1.fill(0x12345678); + img2.fill(0x12345678); + { + QPainter p(&img1); + p.setClipPath(path); + p.setClipRegion(region, Qt::IntersectClip); + p.fillRect(0, 0, img1.width(), img1.height(), QColor(Qt::red)); + } + { + QPainter p(&img2); + p.setClipRegion(region); + p.setClipPath(path, Qt::IntersectClip); + p.fillRect(0, 0, img2.width(), img2.height(), QColor(Qt::red)); + } +#if 0 + if (img1 != img2) { + img1.save("setEqualClipRegionAndPath_1.xpm", "XPM"); + img2.save("setEqualClipRegionAndPath_2.xpm", "XPM"); + } +#endif + QCOMPARE(img1, img2); + +} + +void tst_QPainter::clippedFillPath_data() +{ + QTest::addColumn<QSize>("imageSize"); + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QRect>("clipRect"); + QTest::addColumn<QBrush>("brush"); + QTest::addColumn<QPen>("pen"); + + QLinearGradient gradient(QPoint(0, 0), QPoint(100, 100)); + gradient.setColorAt(0, Qt::red); + gradient.setColorAt(1, Qt::blue); + + + QPen pen2(QColor(223, 223, 0, 223)); + pen2.setWidth(2); + + QPainterPath path; + path.addRect(QRect(15, 15, 50, 50)); + QTest::newRow("simple rect 0") << QSize(100, 100) << path + << QRect(15, 15, 49, 49) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("simple rect 1") << QSize(100, 100) << path + << QRect(15, 15, 50, 50) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("simple rect 2") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("simple rect 3") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(QColor(Qt::blue)) + << QPen(Qt::NoPen); + QTest::newRow("simple rect 4") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(gradient) + << pen2; + + path = QPainterPath(); + path.addEllipse(QRect(15, 15, 50, 50)); + QTest::newRow("ellipse 0") << QSize(100, 100) << path + << QRect(15, 15, 49, 49) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("ellipse 1") << QSize(100, 100) << path + << QRect(15, 15, 50, 50) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("ellipse 2") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("ellipse 3") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(QColor(Qt::blue)) + << QPen(Qt::NoPen); + QTest::newRow("ellipse 4") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(gradient) + << pen2; + + path = QPainterPath(); + path.addRoundRect(QRect(15, 15, 50, 50), 20); + QTest::newRow("round rect 0") << QSize(100, 100) << path + << QRect(15, 15, 49, 49) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("round rect 1") << QSize(100, 100) << path + << QRect(15, 15, 50, 50) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("round rect 2") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("round rect 3") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(QColor(Qt::blue)) + << QPen(Qt::NoPen); + QTest::newRow("round rect 4") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(gradient) + << pen2; + + path = QPainterPath(); + path.moveTo(15, 50); + path.cubicTo(40, 50, 40, 15, 65, 50); + path.lineTo(15, 50); + QTest::newRow("cubic 0") << QSize(100, 100) << path + << QRect(15, 15, 49, 49) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("cubic 1") << QSize(100, 100) << path + << QRect(15, 15, 50, 50) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("cubic 2") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(Qt::NoBrush) + << QPen(Qt::black); + QTest::newRow("cubic 3") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(QColor(Qt::blue)) + << QPen(Qt::NoPen); + QTest::newRow("cubic 4") << QSize(100, 100) << path + << QRect(15, 15, 51, 51) + << QBrush(gradient) + << pen2; +} + +void tst_QPainter::clippedFillPath() +{ + QFETCH(QSize, imageSize); + QFETCH(QPainterPath, path); + QFETCH(QRect, clipRect); + QPainterPath clipPath; + clipPath.addRect(clipRect); + QFETCH(QBrush, brush); + QFETCH(QPen, pen); + + const int width = imageSize.width(); + const int height = imageSize.height(); + + QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPath(path); + } + + QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipPath(clipPath); + painter.drawPath(path); + } + +#if 0 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); + + // repeat with antialiasing + + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPath(path); + } + + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipPath(clipPath); + painter.drawPath(path); + } + +#if 1 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); + +} + +void tst_QPainter::clippedLines_data() +{ + QTest::addColumn<QSize>("imageSize"); + QTest::addColumn<QLineF>("line"); + QTest::addColumn<QRect>("clipRect"); + QTest::addColumn<QPen>("pen"); + + QPen pen2(QColor(223, 223, 0, 223)); + pen2.setWidth(2); + + QVector<QLineF> lines; + lines << QLineF(15, 15, 65, 65) + << QLineF(14, 14, 66, 66) + << QLineF(16, 16, 64, 64) + << QLineF(65, 65, 15, 15) + << QLineF(66, 66, 14, 14) + << QLineF(64, 64, 14, 14) + << QLineF(15, 50, 15, 64) + << QLineF(15, 50, 15, 65) + << QLineF(15, 50, 15, 66) + << QLineF(15, 50, 64, 50) + << QLineF(15, 50, 65, 50) + << QLineF(15, 50, 66, 50); + + foreach (QLineF line, lines) { + QString desc = QString("line (%1, %2, %3, %4) %5").arg(line.x1()) + .arg(line.y1()).arg(line.x2()).arg(line.y2()); + QTest::newRow(qPrintable(desc.arg(0))) << QSize(100, 100) << line + << QRect(15, 15, 49, 49) + << QPen(Qt::black); + QTest::newRow(qPrintable(desc.arg(1))) << QSize(100, 100) << line + << QRect(15, 15, 50, 50) + << QPen(Qt::black); + QTest::newRow(qPrintable(desc.arg(2))) << QSize(100, 100) << line + << QRect(15, 15, 51, 51) + << QPen(Qt::black); + QTest::newRow(qPrintable(desc.arg(3))) << QSize(100, 100) << line + << QRect(15, 15, 51, 51) + << QPen(Qt::NoPen); + QTest::newRow(qPrintable(desc.arg(4))) << QSize(100, 100) << line + << QRect(15, 15, 51, 51) + << pen2; + } +} + +void tst_QPainter::clippedLines() +{ + QFETCH(QSize, imageSize); + QFETCH(QLineF, line); + QFETCH(QRect, clipRect); + QPainterPath clipPath; + clipPath.addRect(clipRect); + QFETCH(QPen, pen); + + const int width = imageSize.width(); + const int height = imageSize.height(); + + QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setPen(pen); + painter.setClipRect(clipRect); + painter.drawLine(line); + painter.drawLine(line.toLine()); + } + + QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setPen(pen); + painter.setClipPath(clipPath); + painter.drawLine(line); + painter.drawLine(line.toLine()); + } + +#if 0 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); + + // repeat with antialiasing + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setClipRect(clipRect); + painter.drawLine(line); + painter.drawLine(line.toLine()); + } + + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setClipPath(clipPath); + painter.drawLine(line); + painter.drawLine(line.toLine()); + } + +#if 0 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); +} + +void tst_QPainter::clippedPolygon_data() +{ + clippedFillPath_data(); +}; + +void tst_QPainter::clippedPolygon() +{ + QFETCH(QSize, imageSize); + QFETCH(QPainterPath, path); + QPolygonF polygon = path.toFillPolygon(); + QFETCH(QRect, clipRect); + QPainterPath clipPath; + clipPath.addRect(clipRect); + QFETCH(QPen, pen); + QFETCH(QBrush, brush); + + const int width = imageSize.width(); + const int height = imageSize.height(); + + QImage clippedRect(width, height, QImage::Format_ARGB32_Premultiplied); + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPolygon(polygon); + painter.drawPolygon(polygon.toPolygon()); + } + + QImage clippedPath(width, height, QImage::Format_ARGB32_Premultiplied); + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPolygon(polygon); + painter.drawPolygon(polygon.toPolygon()); + } + +#if 0 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); + + // repeat with antialiasing + + clippedRect.fill(0x12345678); + { + QPainter painter(&clippedRect); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPolygon(polygon); + painter.drawPolygon(polygon.toPolygon()); + } + + clippedPath.fill(0x12345678); + { + QPainter painter(&clippedPath); + painter.setRenderHint(QPainter::Antialiasing); + painter.setPen(pen); + painter.setBrush(brush); + painter.setClipRect(clipRect); + painter.drawPolygon(polygon); + painter.drawPolygon(polygon.toPolygon()); + } + +#if 0 + if (clippedRect != clippedPath) { + clippedRect.save(QString("clippedRect.png"), "PNG"); + clippedPath.save(QString("clippedPath.png"), "PNG"); + } +#endif + QCOMPARE(clippedRect, clippedPath); +} + +// this just draws some text that should be clipped in the raster +// paint engine. +void tst_QPainter::clippedText() +{ + for (char ch = 'A'; ch < 'Z'; ++ch) { + //qDebug() << ch; + QFont f; + f.setPixelSize(24); + QFontMetrics metrics(f); + QRect textRect = metrics.boundingRect(QChar(ch)); + + if (textRect.width() <= 8) + continue; + if (textRect.height() <= 8) + continue; + + QRect imageRect = textRect.adjusted(4, 4, -4, -4); + + QImage image(imageRect.size(), QImage::Format_ARGB32_Premultiplied); + + image.fill(qRgba(255, 255, 255, 255)); + { + QPainter painter(&image); + painter.setFont(f); + painter.setPen(Qt::black); + + painter.drawText(0, 0, QChar(ch)); + } + + image.fill(qRgba(255, 255, 255, 255)); + { + QPainter painter(&image); + painter.setFont(f); + painter.setPen(Qt::black); + + painter.drawText(-imageRect.topLeft(), QChar(ch)); + } + + bool foundPixel = false; + for (int x = 0; x < image.width(); ++x) + for (int y = 0; y < image.height(); ++y) + if (image.pixel(x, y) != 0) + foundPixel = true; + // can't QVERIFY(foundPixel) as sometimes all pixels are clipped + // away. For example for 'O' + // just call /some/ function to prevent the compiler from optimizing + // foundPixel away + QString::number(foundPixel); + + //image.save(QString("debug") + ch + ".xpm"); + } + + QVERIFY(true); // reached, don't trigger any valgrind errors +} + +void tst_QPainter::setOpacity_data() +{ + QTest::addColumn<QImage::Format>("destFormat"); + QTest::addColumn<QImage::Format>("srcFormat"); + + QTest::newRow("ARGB32P on ARGB32P") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_ARGB32_Premultiplied; + + QTest::newRow("ARGB32 on ARGB32") << QImage::Format_ARGB32 + << QImage::Format_ARGB32; + + QTest::newRow("RGB32 on RGB32") << QImage::Format_RGB32 + << QImage::Format_RGB32; + + QTest::newRow("RGB16 on RGB16") << QImage::Format_RGB16 + << QImage::Format_RGB16; + + QTest::newRow("ARGB8565_Premultiplied on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied + << QImage::Format_ARGB8565_Premultiplied; + + QTest::newRow("RGB555 on RGB555") << QImage::Format_RGB555 + << QImage::Format_RGB555; + + QTest::newRow("RGB666 on RGB666") << QImage::Format_RGB666 + << QImage::Format_RGB666; + + QTest::newRow("ARGB8555_Premultiplied on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied + << QImage::Format_ARGB8555_Premultiplied; + + QTest::newRow("RGB888 on RGB888") << QImage::Format_RGB888 + << QImage::Format_RGB888; + + QTest::newRow("RGB32 on RGB16") << QImage::Format_RGB16 + << QImage::Format_RGB32; + + QTest::newRow("RGB32 on ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied + << QImage::Format_RGB32; + + QTest::newRow("RGB32 on RGB666") << QImage::Format_RGB666 + << QImage::Format_RGB32; + + QTest::newRow("RGB32 on RGB555") << QImage::Format_RGB555 + << QImage::Format_RGB32; + + QTest::newRow("RGB32 on ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied + << QImage::Format_RGB32; + + QTest::newRow("RGB32 on RGB888") << QImage::Format_RGB888 + << QImage::Format_RGB32; + + QTest::newRow("RGB16 on RGB32") << QImage::Format_RGB32 + << QImage::Format_RGB16; + + QTest::newRow("ARGB8565_Premultiplied on RGB32") << QImage::Format_RGB32 + << QImage::Format_ARGB8565_Premultiplied; + + QTest::newRow("RGB666 on RGB32") << QImage::Format_RGB32 + << QImage::Format_RGB666; + + QTest::newRow("RGB555 on RGB32") << QImage::Format_RGB32 + << QImage::Format_RGB555; + + QTest::newRow("ARGB8555_Premultiplied on RGB32") << QImage::Format_RGB32 + << QImage::Format_ARGB8555_Premultiplied; + + QTest::newRow("RGB888 on RGB32") << QImage::Format_RGB32 + << QImage::Format_RGB888; + + QTest::newRow("RGB555 on RGB888") << QImage::Format_RGB888 + << QImage::Format_RGB555; + + QTest::newRow("RGB666 on RGB888") << QImage::Format_RGB888 + << QImage::Format_RGB666; + + QTest::newRow("RGB444 on RGB444") << QImage::Format_RGB444 + << QImage::Format_RGB444; +} + +void tst_QPainter::setOpacity() +{ + QFETCH(QImage::Format, destFormat); + QFETCH(QImage::Format, srcFormat); + + const QSize imageSize(12, 12); + const QRect imageRect(QPoint(0, 0), imageSize); + QColor destColor = Qt::black; + QColor srcColor = Qt::white; + + QImage dest(imageSize, destFormat); + QImage src(imageSize, srcFormat); + + QPainter p; + p.begin(&dest); + p.fillRect(imageRect, destColor); + p.end(); + + p.begin(&src); + p.fillRect(imageRect, srcColor); + p.end(); + + p.begin(&dest); + p.setOpacity(0.5); + p.drawImage(imageRect, src, imageRect); + p.end(); + + QImage actual = dest.convertToFormat(QImage::Format_RGB32); + + for (int y = 0; y < actual.height(); ++y) { + QRgb *p = (QRgb *)actual.scanLine(y); + for (int x = 0; x < actual.width(); ++x) { + QVERIFY(qAbs(qRed(p[x]) - 127) <= 0xf); + QVERIFY(qAbs(qGreen(p[x]) - 127) <= 0xf); + QVERIFY(qAbs(qBlue(p[x]) - 127) <= 0xf); + } + } +} + +void tst_QPainter::drawhelper_blend_untransformed_data() +{ + setOpacity_data(); +} + +void tst_QPainter::drawhelper_blend_untransformed() +{ + QFETCH(QImage::Format, destFormat); + QFETCH(QImage::Format, srcFormat); + + const int size = 128; + const QSize imageSize(size, size); + const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing + + QColor destColor(127, 127, 127); + QColor srcColor(Qt::white); + + QImage dest(imageSize, destFormat); + QImage src(imageSize, srcFormat); + + QPainter p; + p.begin(&src); + p.fillRect(paintRect, srcColor); + p.end(); + + QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4 + << 0.5 << 0.6 << 0.9 << 1.0); + foreach (qreal opacity, opacities) { + p.begin(&dest); + p.fillRect(paintRect, destColor); + + p.setOpacity(opacity); + p.drawImage(paintRect, src, paintRect); + p.end(); + + // sanity check: make sure all pixels are equal + QImage expected(size - 2, size, destFormat); + p.begin(&expected); + p.fillRect(0, 0, expected.width(), expected.height(), + QColor(dest.pixel(1, 0))); + p.end(); + + const QImage subDest(dest.bits() + dest.depth() / 8, + dest.width() - 2, dest.height(), + dest.bytesPerLine(), dest.format()); + + if (dest.format() == QImage::Format_ARGB8565_Premultiplied || + dest.format() == QImage::Format_ARGB8555_Premultiplied) { + // Test skipped due to rounding errors... + continue; + } +#if 0 + if (subDest != expected) { + qDebug() << "size" << size << "opacity" << opacity; + for (int j = 0; j < expected.height(); ++j) { + for (int i = 0; i < expected.width(); ++i) { + if (expected.pixel(i,j) != subDest.pixel(i,j)) + qDebug() << i << j << hex << expected.pixel(i, j) + << subDest.pixel(i, j); + } + } + } +#endif + QCOMPARE(subDest, expected); + } +} + +void tst_QPainter::drawhelper_blend_tiled_untransformed_data() +{ + setOpacity_data(); +} + +void tst_QPainter::drawhelper_blend_tiled_untransformed() +{ + QFETCH(QImage::Format, destFormat); + QFETCH(QImage::Format, srcFormat); + + const int size = 128; + const QSize imageSize(size, size); + const QRect paintRect(1, 0, size - 2, size); // needs alignment and tailing + + QColor destColor(127, 127, 127); + QColor srcColor(Qt::white); + + QImage dest(imageSize, destFormat); + QImage src(imageSize / 2, srcFormat); + + QPainter p; + p.begin(&src); + p.fillRect(QRect(QPoint(0, 0), imageSize/ 2), srcColor); + p.end(); + + const QBrush brush(src); + + QList<qreal> opacities = (QList<qreal>() << 0.0 << 0.1 << 0.01 << 0.4 + << 0.5 << 0.6 << 0.9 << 1.0); + foreach (qreal opacity, opacities) { + p.begin(&dest); + p.fillRect(paintRect, destColor); + + p.setOpacity(opacity); + p.fillRect(paintRect, brush); + p.end(); + + // sanity check: make sure all pixels are equal + QImage expected(size - 2, size, destFormat); + p.begin(&expected); + p.fillRect(0, 0, expected.width(), expected.height(), + QColor(dest.pixel(1, 0))); + p.end(); + + const QImage subDest(dest.bits() + dest.depth() / 8, + dest.width() - 2, dest.height(), + dest.bytesPerLine(), dest.format()); + + if (dest.format() == QImage::Format_ARGB8565_Premultiplied || + dest.format() == QImage::Format_ARGB8555_Premultiplied) { + // Skipping test due to rounding errors. Test needs rewrite + continue; + } +#if 0 + if (subDest != expected) { + qDebug() << "size" << size << "opacity" << opacity; + for (int j = 0; j < expected.height(); ++j) { + for (int i = 0; i < expected.width(); ++i) { + if (expected.pixel(i,j) != subDest.pixel(i,j)) + qDebug() << i << j << hex << expected.pixel(i, j) + << subDest.pixel(i, j); + } + } + } +#endif + QCOMPARE(subDest, expected); + } +} + +static QPaintEngine::PaintEngineFeatures no_porter_duff() +{ + QPaintEngine::PaintEngineFeatures features = QPaintEngine::AllFeatures; + return features & ~QPaintEngine::PorterDuff; +} + +class DummyPaintEngine : public QPaintEngine, public QPaintDevice +{ +public: + DummyPaintEngine() : QPaintEngine(no_porter_duff()) {} + virtual bool begin(QPaintDevice *) { return true; } + virtual bool end() { return true; } + + virtual void updateState(const QPaintEngineState &) {} + virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {} + + virtual Type type() const { return User; } + + virtual QPaintEngine *paintEngine() const { return (QPaintEngine *)this; } + + virtual int metric(PaintDeviceMetric metric) const { Q_UNUSED(metric); return 0; }; +}; + +static bool success; + +void porterDuff_warningChecker(QtMsgType type, const char *msg) +{ + if (type == QtWarningMsg && msg == QLatin1String("QPainter::setCompositionMode: PorterDuff modes not supported on device")) + success = false; +} + +void tst_QPainter::porterDuff_warning() +{ + QtMsgHandler old = qInstallMsgHandler(porterDuff_warningChecker); + DummyPaintEngine dummy; + QPainter p(&dummy); + + success = true; + p.setCompositionMode(QPainter::CompositionMode_Source); + QVERIFY(success); + + success = true; + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + QVERIFY(success); + + success = true; + p.setCompositionMode(QPainter::CompositionMode_DestinationOver); + QVERIFY(!success); + + QVERIFY(qInstallMsgHandler(old) == porterDuff_warningChecker); +} + +class quint24 +{ +public: + inline quint24(quint32 v) + { + data[0] = qBlue(v); + data[1] = qGreen(v); + data[2] = qRed(v); + } + + inline operator quint32 () + { + return qRgb(data[2], data[1], data[0]); + } + + inline bool operator==(const quint24 &v) const { + return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]); + } + + uchar data[3]; +} Q_PACKED; + +void tst_QPainter::drawhelper_blend_color() +{ + QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied); + dest.fill(0xff000000); + + { + QPainter p(&dest); + p.fillRect(0, 0, dest.width(), dest.height(), QColor(255, 0, 0, 127)); + } + + QImage expected(32, 32, QImage::Format_ARGB8555_Premultiplied); + expected.fill(0xff3c007f); + + QCOMPARE(dest.pixel(1, 1), expected.pixel(1, 1)); + QCOMPARE(dest, expected); +} + +class ViewportTestWidget : public QWidget +{ +public: + ViewportTestWidget(QWidget *parent = 0) : QWidget(parent), hasPainted(false) {} + QSize sizeHint() const { + return QSize(100, 100); + } + + QRect viewport; + bool hasPainted; + +protected: + void paintEvent(QPaintEvent *) { + hasPainted = true; + QPainter p(this); + viewport = p.viewport(); + } +}; + +void tst_QPainter::childWidgetViewport() +{ + QWidget parent; + parent.setAutoFillBackground(true); + parent.resize(200, 200); + ViewportTestWidget child(&parent); + child.setAutoFillBackground(true); + parent.show(); + parent.update(); + qApp->processEvents(); + + if (child.hasPainted) { + QCOMPARE(child.viewport, QRect(QPoint(0, 0), child.sizeHint())); + } else { + qWarning("Failed to ensure that paintEvent has been run. Could not run test."); + } +} + +void tst_QPainter::fillRect_objectBoundingModeGradient() +{ + QImage a(10, 10, QImage::Format_ARGB32_Premultiplied); + a.fill(0x0); + QImage b = a; + + QLinearGradient g(QPoint(0, 0), QPoint(0, 1)); + g.setColorAt(0, Qt::red); + g.setColorAt(1, Qt::blue); + g.setCoordinateMode(QGradient::ObjectBoundingMode); + + QPainter p(&a); + p.fillRect(QRect(0, 0, a.width(), a.height()), g); + p.end(); + + QPainterPath path; + path.addRect(0, 0, a.width(), a.height()); + + p.begin(&b); + p.fillPath(path, g); + p.end(); + + QCOMPARE(a, b); +} + +void tst_QPainter::fillRect_stretchToDeviceMode() +{ + QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); + + QLinearGradient g(QPoint(0, 0), QPoint(0, 1)); + g.setCoordinateMode(QGradient::StretchToDeviceMode); + + QPainter p(&img); + p.fillRect(img.rect(), g); + p.end(); + + for (int i = 1; i < img.height(); ++i) + QVERIFY(img.pixel(0, i) != img.pixel(0, i-1)); +} + +void tst_QPainter::monoImages() +{ + Qt::GlobalColor colorPairs[][2] = { + { Qt::white, Qt::black }, + { Qt::color0, Qt::color1 }, + { Qt::red, Qt::blue } + }; + + const int numColorPairs = sizeof(colorPairs) / sizeof(QRgb[2]); + + QImage transparent(2, 2, QImage::Format_ARGB32_Premultiplied); + transparent.fill(0x0); + + for (int i = 1; i < QImage::NImageFormats; ++i) { + for (int j = 0; j < numColorPairs; ++j) { + const QImage::Format format = QImage::Format(i); + if (format == QImage::Format_Indexed8) + continue; + + QImage img(2, 2, format); + + if (img.colorCount() > 0) { + img.setColor(0, QColor(colorPairs[j][0]).rgba()); + img.setColor(1, QColor(colorPairs[j][1]).rgba()); + } + + img.fill(0x0); + QPainter p(&img); + p.fillRect(0, 0, 2, 2, colorPairs[j][0]); + p.fillRect(0, 0, 1, 1, colorPairs[j][1]); + p.fillRect(1, 1, 1, 1, colorPairs[j][1]); + p.end(); + + QImage original = img; + + p.begin(&img); + p.drawImage(0, 0, transparent); + p.end(); + + // drawing a transparent image on top of another image + // should not change the image + QCOMPARE(original, img); + + if (img.colorCount() == 0) + continue; + + for (int k = 0; k < 2; ++k) { + QPainter p(&img); + p.fillRect(0, 0, 2, 2, colorPairs[j][k]); + p.end(); + + QImage argb32p(2, 2, QImage::Format_ARGB32_Premultiplied); + p.begin(&argb32p); + p.fillRect(0, 0, 2, 2, colorPairs[j][k]); + p.end(); + + QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); + + // drawing argb32p image on mono image + p.begin(&img); + p.drawImage(0, 0, argb32p); + p.end(); + + QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); + + // drawing mono image on argb32p image + p.begin(&argb32p); + p.drawImage(0, 0, img); + p.end(); + + QCOMPARE(argb32p, img.convertToFormat(argb32p.format())); + } + } + } +} + +#if !defined(Q_OS_IRIX) && !defined(Q_OS_AIX) && !defined(Q_CC_MSVC) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_SYMBIAN) +#include <fenv.h> + +static const QString fpeExceptionString(int exception) +{ +#ifdef FE_INEXACT + if (exception & FE_INEXACT) + return QLatin1String("Inexact result"); +#endif + if (exception & FE_UNDERFLOW) + return QLatin1String("Underflow"); + if (exception & FE_OVERFLOW) + return QLatin1String("Overflow"); + if (exception & FE_DIVBYZERO) + return QLatin1String("Divide by zero"); + if (exception & FE_INVALID) + return QLatin1String("Invalid operation"); + return QLatin1String("No exception"); +} + +class FpExceptionChecker +{ +public: + FpExceptionChecker(int exceptionMask) + : m_exceptionMask(exceptionMask) + { + feclearexcept(m_exceptionMask); + } + + ~FpExceptionChecker() + { + const int exceptions = fetestexcept(m_exceptionMask); + QVERIFY2(!exceptions, qPrintable(QLatin1String("Floating point exception: ") + fpeExceptionString(exceptions))); + } + +private: + int m_exceptionMask; +}; + +void fpe_rasterizeLine_task232012() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + QPainter p(&img); + + p.setBrush(Qt::black); + p.drawRect(QRectF(0, 0, 5, 0)); + p.drawRect(QRectF(0, 0, 0, 5)); +} + +void fpe_pixmapTransform() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + + QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); + + QPainter p(&img); + + const qreal scaleFactor = 0.001; + const int translateDistance = 1000000; + + p.setPen(Qt::red); + p.setBrush(QBrush(Qt::red,Qt::Dense6Pattern)); + + for (int i = 0; i < 2; ++i) { + p.setRenderHint(QPainter::SmoothPixmapTransform, i); + + p.resetTransform(); + p.scale(1.1, 1.1); + p.translate(translateDistance, 0); + p.drawRect(-translateDistance, 0, 100, 100); + + p.resetTransform(); + p.scale(scaleFactor, scaleFactor); + p.drawRect(QRectF(0, 0, 1 / scaleFactor, 1 / scaleFactor)); + } +} + +void fpe_zeroLengthLines() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + + QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); + + QPainter p(&img); + + p.setPen(QPen(Qt::black, 3)); + p.drawLine(64, 64, 64, 64); +} + +void fpe_divByZero() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + + QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); + + QPainter p(&img); + + p.setRenderHint(QPainter::Antialiasing); + + p.drawRect(QRectF(10, 10, 100, 0)); + p.drawRect(QRectF(10, 10, 0, 100)); + + p.drawRect(QRect(10, 10, 100, 0)); + p.drawRect(QRect(10, 10, 0, 100)); + + p.fillRect(QRectF(10, 10, 100, 0), Qt::black); + p.fillRect(QRectF(10, 10, 0, 100), Qt::black); + + p.fillRect(QRect(10, 10, 100, 0), Qt::black); + p.fillRect(QRect(10, 10, 0, 100), Qt::black); +} + +void fpe_steepSlopes() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + + QImage img(1024, 1024, QImage::Format_ARGB32_Premultiplied); + + QFETCH(QTransform, transform); + QFETCH(QLineF, line); + QFETCH(bool, antialiased); + + QPainter p(&img); + + p.setPen(QPen(Qt::black, 1)); + p.setRenderHint(QPainter::Antialiasing, antialiased); + p.setTransform(transform); + + p.drawLine(line); +} + +void fpe_radialGradients() +{ + FpExceptionChecker checker(FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID | FE_DIVBYZERO); + + QImage img(21, 21, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + + double m = img.width() * 0.5; + + QPainter p(&img); + p.setRenderHints(QPainter::Antialiasing); + p.setPen(Qt::NoPen); + p.setBrush(QRadialGradient(m, m, m)); + p.drawEllipse(img.rect()); +} + +#define FPE_TEST(x) \ +void tst_QPainter::x() \ +{ \ + ::x(); \ +} +#else +#define FPE_TEST(x) \ +void tst_QPainter::x() \ +{ \ + QSKIP("Floating point exception checking (fenv.h) not available", SkipAll); \ +} +#endif + +FPE_TEST(fpe_rasterizeLine_task232012) +FPE_TEST(fpe_pixmapTransform) +FPE_TEST(fpe_zeroLengthLines) +FPE_TEST(fpe_divByZero) +FPE_TEST(fpe_steepSlopes) +FPE_TEST(fpe_radialGradients) + +void tst_QPainter::fpe_steepSlopes_data() +{ + QTest::addColumn<QTransform>("transform"); + QTest::addColumn<QLineF>("line"); + QTest::addColumn<bool>("antialiased"); + + { + const qreal dsin = 0.000014946676875461832484392500630665523431162000633776187896728515625; + const qreal dcos = 0.9999999998882984630910186751862056553363800048828125; + + const QTransform transform = QTransform(QMatrix(dcos, dsin, -dsin, dcos, 64, 64)); + const QLineF line(2, 2, 2, 6); + + QTest::newRow("task 207147 aa") << transform << line << true; + QTest::newRow("task 207147 no aa") << transform << line << false; + } + + { + QTransform transform; + transform.rotate(0.0000001); + const QLineF line(5, 5, 10, 5); + + QTest::newRow("task 166702 aa") << transform << line << true; + QTest::newRow("task 166702 no aa") << transform << line << false; + } + + { + const QTransform transform; + const QLineF line(2.5, 2.5, 2.5 + 1/256., 60000.5); + + QTest::newRow("steep line aa") << transform << line << true; + QTest::newRow("steep line no aa") << transform << line << false; + } + + { + const QTransform transform; + const QLineF line(2.5, 2.5, 2.5 + 1/256., 1024); + + QTest::newRow("steep line 2 aa") << transform << line << true; + QTest::newRow("steep line 2 no aa") << transform << line << false; + } + + { + const QTransform transform; + const QLineF line(2.5, 2.5, 2.5 + 1/64., 1024); + + QTest::newRow("steep line 3 aa") << transform << line << true; + QTest::newRow("steep line 3 no aa") << transform << line << false; + } +} + +qreal randf() +{ + return rand() / (RAND_MAX + 1.0); +} + +QPointF randInRect(const QRectF &rect) +{ + const qreal x = rect.left() + rect.width() * randf(); + const qreal y = rect.top() + rect.height() * randf(); + + return QPointF(x, y); +} + +void tst_QPainter::rasterizer_asserts() +{ + QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); + + QRectF middle(QPointF(0, 0), img.size()); + QRectF left = middle.translated(-middle.width(), 0); + QRectF right = middle.translated(middle.width(), 0); + + QPainter p(&img); + img.fill(Qt::white); + p.setCompositionMode(QPainter::CompositionMode_Destination); + for (int i = 0; i < 100000; ++i) { + QPainterPath path; + path.moveTo(randInRect(middle)); + path.lineTo(randInRect(left)); + path.lineTo(randInRect(right)); + + p.fillPath(path, Qt::black); + } +} + +void tst_QPainter::rasterizer_negativeCoords() +{ + QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + + QImage original = img; + + QPainter p(&img); + p.rotate(90); + p.fillRect(0, 0, 70, 50, Qt::black); + + // image should not have changed + QCOMPARE(img.pixel(0, 0), 0x0U); + QCOMPARE(img, original); +} + +void tst_QPainter::blendOverFlow_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::addColumn<int>("width"); + QTest::addColumn<int>("height"); + + QImage::Format format = QImage::Format_ARGB8555_Premultiplied; + QTest::newRow("555,1,1") << format << 1 << 1; + QTest::newRow("555,2,2") << format << 2 << 2; + QTest::newRow("555,10,10") << format << 10 << 10; + + format = QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("565,1,1") << format << 1 << 1; + QTest::newRow("565,2,2") << format << 2 << 2; + QTest::newRow("565,10,10") << format << 10 << 10; +} + +void tst_QPainter::blendOverFlow() +{ + QFETCH(QImage::Format, format); + QFETCH(int, width); + QFETCH(int, height); + + QImage dest(width, height, format); + QImage src(width, height, format); + + { + QPainter p(&dest); + p.fillRect(0, 0, width, height, Qt::green); + } + QImage expected = dest; + + { + QPainter p(&src); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, width, height, QColor(0, 255, 0, 6)); + } + + { + QPainter p(&dest); + p.drawImage(0, 0, src); + } + + QCOMPARE(dest.pixel(0, 0), expected.pixel(0, 0)); + QCOMPARE(dest, expected); +} + +void tst_QPainter::largeImagePainting_data() +{ + QTest::addColumn<int>("width"); + QTest::addColumn<int>("height"); + QTest::addColumn<bool>("antialiased"); + + QTest::newRow("tall") << 1 << 32767 << false; + QTest::newRow("tall aa") << 1 << 32767 << true; + QTest::newRow("wide") << 32767 << 1 << false; + QTest::newRow("wide aa") << 32767 << 1 << true; +} + +void tst_QPainter::largeImagePainting() +{ + QPainterPath path; + path.addRect(0, 0, 1, 1); + path.addRect(2, 0, 1, 1); + path.addRect(0, 2, 1, 1); + + QFETCH(int, width); + QFETCH(int, height); + QFETCH(bool, antialiased); + + QImage img(width, height, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + + QPainter p(&img); + p.setPen(Qt::NoPen); + p.setBrush(Qt::white); + + p.setRenderHint(QPainter::Antialiasing, antialiased); + + for (int i = 0; i < img.width(); i += 4) { + p.drawPath(path); + p.translate(4, 0); + } + + p.resetMatrix(); + + for (int i = 4; i < img.height(); i += 4) { + p.translate(0, 4); + p.drawPath(path); + } + + for (int i = 0; i < img.width(); ++i) { + if (i % 2) + QCOMPARE(img.pixel(i, 0), 0x0U); + else + QCOMPARE(img.pixel(i, 0), 0xffffffffU); + } + + for (int i = 1; i < img.height(); ++i) { + if (i % 2) + QCOMPARE(img.pixel(0, i), 0x0U); + else + QCOMPARE(img.pixel(0, i), 0xffffffffU); + } +} + +void tst_QPainter::imageScaling_task206785() +{ + QImage src(32, 2, QImage::Format_ARGB32_Premultiplied); + src.fill(0xffffffff); + + QImage dst(128, 128, QImage::Format_ARGB32_Premultiplied); + + QImage expected(128, 128, QImage::Format_ARGB32_Premultiplied); + expected.fill(0xffffffff); + + for (int i = 1; i < 5; ++i) { + qreal scale = i / qreal(5); + + dst.fill(0xff000000); + + QPainter p(&dst); + p.scale(dst.width() / qreal(src.width()), scale); + + for (int y = 0; y * scale < dst.height(); ++y) + p.drawImage(0, y, src); + + p.end(); + + QCOMPARE(dst, expected); + } +} + +#define FOR_EACH_NEIGHBOR_8 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if (dx != 0 || dy != 0) +#define FOR_EACH_NEIGHBOR_4 for (int dx = -1; dx <= 1; ++dx) for (int dy = -1; dy <= 1; ++dy) if ((dx == 0) != (dy == 0)) + +uint qHash(const QPoint &point) +{ + return qHash(qMakePair(point.x(), point.y())); +} + +bool verifyOutlineFillConsistency(const QImage &img, QRgb outside, QRgb inside, QRgb outline) +{ + if (img.pixel(img.width() / 2, img.height() / 2) != inside) + return false; + + int x = img.width() / 2; + int y = img.height() / 2; + + while (img.pixel(++x, y) == inside) + ; + + if (img.pixel(x, y) != outline) + return false; + + QQueue<QPoint> discovered; + discovered.enqueue(QPoint(x, y)); + + QVector<bool> visited(img.width() * img.height()); + visited.fill(false); + + while (!discovered.isEmpty()) { + QPoint p = discovered.dequeue(); + QRgb pixel = img.pixel(p.x(), p.y()); + + bool &v = visited[p.y() * img.width() + p.x()]; + if (v) + continue; + v = true; + + if (pixel == outline) { + FOR_EACH_NEIGHBOR_8 { + QPoint x(p.x() + dx, p.y() + dy); + discovered.enqueue(x); + } + } else { + FOR_EACH_NEIGHBOR_4 { + if ((dx == 0) == (dy == 0)) + continue; + QRgb neighbor = img.pixel(p.x() + dx, p.y() + dy); + if ((pixel == inside && neighbor == outside) || + (pixel == outside && neighbor == inside)) + return false; + } + } + } + + return true; +} + +#undef FOR_EACH_NEIGHBOR_8 +#undef FOR_EACH_NEIGHBOR_4 + +void tst_QPainter::outlineFillConsistency() +{ + QSKIP("currently broken...", SkipAll); + return; + + QImage dst(256, 256, QImage::Format_ARGB32_Premultiplied); + + QPolygonF poly; + poly << QPointF(5, -100) << QPointF(-70, 20) << QPointF(95, 25); + + QPen pen(Qt::red); + QBrush brush(Qt::black); + + QRgb background = 0xffffffff; + for (int i = 0; i < 360; ++i) { + dst.fill(background); + + QPainter p(&dst); + p.translate(dst.width() / 2, dst.height() / 2); + + QPolygonF copy = poly; + for (int j = 0; j < copy.size(); ++j) + copy[j] = QTransform().rotate(i).map(copy[j]); + + p.setPen(pen); + p.setBrush(brush); + p.drawPolygon(copy); + p.end(); + +#if 0 + if (!verifyOutlineFillConsistency(dst, background, p.brush().color().rgba(), p.pen().color().rgba())) + dst.save(QString("outlineFillConsistency-%1.png").arg(i)); +#endif + + QVERIFY(verifyOutlineFillConsistency(dst, background, brush.color().rgba(), pen.color().rgba())); + } +} + +void tst_QPainter::drawImage_task217400_data() +{ + QTest::addColumn<QImage::Format>("format"); + + QTest::newRow("444") << QImage::Format_ARGB4444_Premultiplied; + QTest::newRow("555") << QImage::Format_ARGB8555_Premultiplied; + QTest::newRow("565") << QImage::Format_ARGB8565_Premultiplied; +// QTest::newRow("666") << QImage::Format_ARGB6666_Premultiplied; + QTest::newRow("888p") << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("888") << QImage::Format_ARGB32; +} + +void tst_QPainter::drawImage_task217400() +{ + QFETCH(QImage::Format, format); + + const QImage src = QImage(QString(SRCDIR) + "/task217400.png") + .convertToFormat(format); + QVERIFY(!src.isNull()); + + QImage expected(src.size(), format); + { + QPainter p(&expected); + p.fillRect(0, 0, expected.width(), expected.height(), Qt::white); + p.drawImage(0, 0, src); + } + + for (int i = 1; i <= 4; ++i) { + QImage dest(src.width() + i, src.height(), format); + { + QPainter p(&dest); + p.fillRect(0, 0, dest.width(), dest.height(), Qt::white); + p.drawImage(i, 0, src); + } + + const QImage result = dest.copy(i, 0, src.width(), src.height()); + +#if 0 + if (result != expected) { + qDebug("i=%i", i); + result.save("result.png"); + expected.save("expected.png"); + } +#endif + QCOMPARE(result, expected); + } +} + +void tst_QPainter::drawImage_task258776() +{ + QImage src(16, 16, QImage::Format_RGB888); + QImage dest(33, 33, QImage::Format_RGB888); + src.fill(0x00ff00); + dest.fill(0x0000ff); + + QPainter painter(&dest); + painter.drawImage(QRectF(0.499, 0.499, 32, 32), src, QRectF(0, 0, 16, 16)); + painter.end(); + + QImage expected(33, 33, QImage::Format_RGB32); + expected.fill(0xff0000); + + painter.begin(&expected); + painter.drawImage(QRectF(0, 0, 32, 32), src); + painter.end(); + + dest = dest.convertToFormat(QImage::Format_RGB32); + + dest.save("dest.png"); + expected.save("expected.png"); + QCOMPARE(dest, expected); +} + +void tst_QPainter::clipRectSaveRestore() +{ + QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + + QPainter p(&img); + p.setClipRect(QRect(0, 0, 10, 10)); + p.save(); + p.setClipRect(QRect(5, 5, 5, 5), Qt::IntersectClip); + p.restore(); + p.fillRect(0, 0, 64, 64, Qt::black); + p.end(); + + QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba()); +} + +void tst_QPainter::clippedImage() +{ + QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + + QImage src(16, 16, QImage::Format_RGB32); + src.fill(QColor(Qt::red).rgba()); + + QPainter p(&img); + p.setClipRect(QRect(1, 1, 14, 14)); + p.drawImage(0, 0, src); + p.end(); + + QCOMPARE(img.pixel(0, 0), 0x0U); + QCOMPARE(img.pixel(1, 1), src.pixel(1, 1)); +} + +void tst_QPainter::stateResetBetweenQPainters() +{ + QImage img(16, 16, QImage::Format_ARGB32); + + { + QPainter p(&img); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, 16, 16, Qt::red); + } + + { + QPainter p2(&img); + p2.fillRect(0, 0, 16, 16, QColor(0, 0, 255, 63)); + } + + img.save("foo.png"); + + QVERIFY(img.pixel(0, 0) != qRgba(0, 0, 255, 63)); + QVERIFY(qRed(img.pixel(0, 0)) > 0); // We didn't erase the red channel... + QVERIFY(qBlue(img.pixel(0, 0)) < 255); // We blended the blue channel +} + +void tst_QPainter::drawRect_task215378() +{ + QImage img(11, 11, QImage::Format_ARGB32_Premultiplied); + img.fill(QColor(Qt::white).rgba()); + + QPainter p(&img); + p.setPen(QColor(127, 127, 127, 127)); + p.drawRect(0, 0, 10, 10); + p.end(); + + QCOMPARE(img.pixel(0, 0), img.pixel(1, 0)); + QCOMPARE(img.pixel(0, 0), img.pixel(0, 1)); + QVERIFY(img.pixel(0, 0) != img.pixel(1, 1)); +} + +void tst_QPainter::drawRect_task247505() +{ + QImage a(10, 10, QImage::Format_ARGB32_Premultiplied); + a.fill(0); + QImage b = a; + + QPainter p(&a); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.drawRect(QRectF(10, 0, -10, 10)); + p.end(); + p.begin(&b); + p.setPen(Qt::NoPen); + p.setBrush(Qt::black); + p.drawRect(QRectF(0, 0, 10, 10)); + p.end(); + + QCOMPARE(a, b); +} + +void tst_QPainter::drawImage_data() +{ + QTest::addColumn<int>("x"); + QTest::addColumn<int>("y"); + QTest::addColumn<int>("w"); + QTest::addColumn<int>("h"); + QTest::addColumn<QImage::Format>("srcFormat"); + QTest::addColumn<QImage::Format>("dstFormat"); + + for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) { + for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) { + if (dstFormat == QImage::Format_Indexed8) + continue; + for (int odd_x = 0; odd_x <= 1; ++odd_x) { + for (int odd_width = 0; odd_width <= 1; ++odd_width) { + QString description = + QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4") + .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width); + + QTest::newRow(qPrintable(description)) << (10 + odd_x) << 10 << (20 + odd_width) << 20 + << QImage::Format(srcFormat) + << QImage::Format(dstFormat); + } + } + } + } +} + +bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background) +{ + int imgWidth = img.width(); + int imgHeight = img.height(); + for (int i = 0; i < imgHeight; ++i) { + for (int j = 0; j < imgWidth; ++j) { + uint pixel = img.pixel(j, i); + bool outside = j < x || j >= (x + w) || i < y || i >= (y + h); + if (outside != (pixel == background)) { + //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside); + return false; + } + } + } + + return true; +} + +void tst_QPainter::drawImage() +{ + QFETCH(int, x); + QFETCH(int, y); + QFETCH(int, w); + QFETCH(int, h); + QFETCH(QImage::Format, srcFormat); + QFETCH(QImage::Format, dstFormat); + + QImage dst(40, 40, QImage::Format_RGB32); + dst.fill(0xffffffff); + + dst = dst.convertToFormat(dstFormat); + uint background = dst.pixel(0, 0); + + QImage src(w, h, QImage::Format_RGB32); + src.fill(0xff000000); + src = src.convertToFormat(srcFormat); + + QPainter p(&dst); + p.drawImage(x, y, src); + p.end(); + + QVERIFY(verifyImage(dst, x, y, w, h, background)); +} + +void tst_QPainter::imageCoordinateLimit() +{ + QImage img(64, 40000, QImage::Format_MonoLSB); + QPainter p(&img); + p.drawText(10, 36000, QLatin1String("foo")); + p.setPen(QPen(Qt::black, 2)); + p.drawLine(10, 0, 60, 40000); + + p.setRenderHint(QPainter::Antialiasing); + p.drawLine(10, 0, 60, 40000); +} + + +void tst_QPainter::imageBlending_data() +{ + QTest::addColumn<QImage::Format>("sourceFormat"); + QTest::addColumn<QImage::Format>("destFormat"); + QTest::addColumn<int>("error"); + + int error_rgb565 = ((1<<3) + (1<<2) + (1<<3)); + QTest::newRow("rgb565_on_rgb565") << QImage::Format_RGB16 + << QImage::Format_RGB16 + << 0; + QTest::newRow("argb8565_on_rgb565") << QImage::Format_ARGB8565_Premultiplied + << QImage::Format_RGB16 + << error_rgb565; + + QTest::newRow("rgb32_on_rgb565") << QImage::Format_RGB32 + << QImage::Format_RGB16 + << error_rgb565; + + QTest::newRow("argb32pm_on_rgb565") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_RGB16 + << error_rgb565; +} + +int diffColor(quint32 ap, quint32 bp) +{ + int a = qAlpha(ap) - qAlpha(bp); + int r = qRed(ap) - qRed(bp); + int b = qBlue(ap) - qBlue(bp); + int g = qBlue(ap) - qBlue(bp); + + return qAbs(a) + qAbs(r) + qAbs(g) + qAbs(b); +} + +// this test assumes premultiplied pixels... + +void tst_QPainter::imageBlending() +{ + QFETCH(QImage::Format, sourceFormat); + QFETCH(QImage::Format, destFormat); + QFETCH(int, error); + + QImage dest; + { + QImage orig_dest(6, 6, QImage::Format_ARGB32_Premultiplied); + orig_dest.fill(0); + QPainter p(&orig_dest); + p.fillRect(0, 0, 6, 3, QColor::fromRgbF(1, 0, 0)); + p.fillRect(3, 0, 3, 6, QColor::fromRgbF(0, 0, 1, 0.5)); + p.end(); + dest = orig_dest.convertToFormat(destFormat); + + // An image like this: (r = red, m = magenta, b = light alpha blue, 0 = transparent) + // r r r m m m + // r r r m m m + // r r r m m m + // 0 0 0 b b b + // 0 0 0 b b b + // 0 0 0 b b b + } + + QImage source; + { + QImage orig_source(6, 6, QImage::Format_ARGB32_Premultiplied); + orig_source.fill(0); + QPainter p(&orig_source); + p.fillRect(1, 1, 4, 4, QColor::fromRgbF(0, 1, 0, 0.5)); + p.fillRect(2, 2, 2, 2, QColor::fromRgbF(0, 1, 0)); + p.end(); + source = orig_source.convertToFormat(sourceFormat); + + // An image like this: (0 = transparent, . = green at 0.5 alpha, g = opaque green. + // 0 0 0 0 0 0 + // 0 . . . . 0 + // 0 . g g . 0 + // 0 . g g . 0 + // 0 . . . . 0 + // 0 0 0 0 0 0 + } + + QPainter p(&dest); + p.drawImage(0, 0, source); + p.end(); + + // resulting image: + // r r r m m m + // r r. r. m. m. m + // r r. g g m. m + // 0 . g g b. b + // 0 . . b. b. b + // 0 0 0 b b b + + // the g pixels, always green.. + QVERIFY(diffColor(dest.pixel(2, 2), 0xff00ff00) <= error); // g + + if (source.hasAlphaChannel()) { + QVERIFY(diffColor(dest.pixel(0, 0), 0xffff0000) <= error); // r + QVERIFY(diffColor(dest.pixel(5, 0), 0xff7f007f) <= error); // m + QVERIFY(diffColor(dest.pixel(1, 1), 0xff7f7f00) <= error); // r. + QVERIFY(diffColor(dest.pixel(4, 1), 0xff3f7f3f) <= error); // m. + if (dest.hasAlphaChannel()) { + QVERIFY(diffColor(dest.pixel(1, 3), 0x7f007f00) <= error); // . + QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b. + QVERIFY(diffColor(dest.pixel(4, 3), 0x7f007f3f) <= error); // b. + QVERIFY(diffColor(dest.pixel(4, 4), 0x7f00007f) <= error); // b + QVERIFY(diffColor(dest.pixel(4, 0), 0) <= 0); // 0 + } + } else { + QVERIFY(diffColor(dest.pixel(0, 0), 0xff000000) <= 0); + QVERIFY(diffColor(dest.pixel(1, 1), 0xff007f00) <= error); + } +} + +void tst_QPainter::imageBlending_clipped() +{ + QImage src(20, 20, QImage::Format_RGB16); + QPainter p(&src); + p.fillRect(src.rect(), Qt::red); + p.end(); + + QImage dst(40, 20, QImage::Format_RGB16); + p.begin(&dst); + p.fillRect(dst.rect(), Qt::white); + p.end(); + + QImage expected = dst; + + p.begin(&dst); + p.setClipRect(QRect(23, 0, 20, 20)); + + // should be completely clipped + p.drawImage(QRectF(3, 0, 20, 20), src); + p.end(); + + // dst should be left unchanged + QCOMPARE(dst, expected); +} + +void tst_QPainter::paintOnNullPixmap() +{ + QPixmap pix(16, 16); + + QPixmap textPixmap; + QPainter p(&textPixmap); + p.drawPixmap(10, 10, pix); + p.end(); + + QPixmap textPixmap2(16,16); + p.begin(&textPixmap2); + p.end(); +} + +void tst_QPainter::checkCompositionMode() +{ + QImage refImage(50,50,QImage::Format_ARGB32); + QPainter painter(&refImage); + painter.fillRect(QRect(0,0,50,50),Qt::blue); + + QImage testImage(50,50,QImage::Format_ARGB32); + QPainter p(&testImage); + p.fillRect(QRect(0,0,50,50),Qt::red); + p.save(); + p.setCompositionMode(QPainter::CompositionMode_SourceOut); + p.restore(); + p.fillRect(QRect(0,0,50,50),Qt::blue); + + QCOMPARE(refImage.pixel(20,20),testImage.pixel(20,20)); +} + +static QLinearGradient inverseGradient(QLinearGradient g) +{ + QLinearGradient g2 = g; + + QGradientStops stops = g.stops(); + + QGradientStops inverse; + foreach (QGradientStop stop, stops) + inverse << QGradientStop(1 - stop.first, stop.second); + + g2.setStops(inverse); + return g2; +} + +void tst_QPainter::linearGradientSymmetry_data() +{ + QTest::addColumn<QGradientStops>("stops"); + + if (sizeof(qreal) != sizeof(float)) { + QGradientStops stops; + stops << qMakePair(qreal(0.0), QColor(Qt::blue)); + stops << qMakePair(qreal(0.2), QColor(220, 220, 220, 0)); + stops << qMakePair(qreal(0.6), QColor(Qt::red)); + stops << qMakePair(qreal(0.9), QColor(220, 220, 220, 255)); + stops << qMakePair(qreal(1.0), QColor(Qt::black)); + QTest::newRow("multiple stops") << stops; + } + + { + QGradientStops stops; + stops << qMakePair(qreal(0.0), QColor(Qt::blue)); + stops << qMakePair(qreal(1.0), QColor(Qt::black)); + QTest::newRow("two stops") << stops; + } + + if (sizeof(qreal) != sizeof(float)) { + QGradientStops stops; + stops << qMakePair(qreal(0.3), QColor(Qt::blue)); + stops << qMakePair(qreal(0.6), QColor(Qt::black)); + QTest::newRow("two stops 2") << stops; + } +} + +void tst_QPainter::linearGradientSymmetry() +{ +#ifdef Q_WS_QWS + QSKIP("QWS has limited resolution in the gradient color table", SkipAll); +#else + QFETCH(QGradientStops, stops); + + QImage a(64, 8, QImage::Format_ARGB32_Premultiplied); + QImage b(64, 8, QImage::Format_ARGB32_Premultiplied); + + a.fill(0); + b.fill(0); + + QLinearGradient gradient(QRectF(b.rect()).topLeft(), QRectF(b.rect()).topRight()); + gradient.setStops(stops); + + QPainter pa(&a); + pa.fillRect(a.rect(), gradient); + pa.end(); + + QPainter pb(&b); + pb.fillRect(b.rect(), inverseGradient(gradient)); + pb.end(); + + b = b.mirrored(true); + QCOMPARE(a, b); +#endif +} + +void tst_QPainter::gradientInterpolation() +{ + QImage image(256, 8, QImage::Format_ARGB32_Premultiplied); + QPainter painter; + + QLinearGradient gradient(QRectF(image.rect()).topLeft(), QRectF(image.rect()).topRight()); + gradient.setColorAt(0.0, QColor(255, 0, 0, 0)); + gradient.setColorAt(1.0, Qt::blue); + + image.fill(0); + painter.begin(&image); + painter.fillRect(image.rect(), gradient); + painter.end(); + + const QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(3)); + + for (int i = 0; i < 256; ++i) { + QCOMPARE(qAlpha(line[i]), qBlue(line[i])); // bright blue + QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha + QCOMPARE(qRed(line[i]), 0); // no red component + QCOMPARE(qGreen(line[i]), 0); // no green component + } + + gradient.setInterpolationMode(QGradient::ComponentInterpolation); + + image.fill(0); + painter.begin(&image); + painter.fillRect(image.rect(), gradient); + painter.end(); + + for (int i = 1; i < 256; ++i) { + if (i < 128) { + QVERIFY(qRed(line[i]) >= qBlue(line[i])); // red is dominant + } else { + QVERIFY(qRed(line[i]) <= qBlue(line[i])); // blue is dominant + } + QVERIFY((qRed(line[i]) - 0.5) * (qAlpha(line[i - 1]) - 0.5) <= (qRed(line[i - 1]) + 0.5) * (qAlpha(line[i]) + 0.5)); // decreasing red + QVERIFY((qBlue(line[i]) + 0.5) * (qAlpha(line[i - 1]) + 0.5) >= (qBlue(line[i - 1]) - 0.5) * (qAlpha(line[i]) - 0.5)); // increasing blue + QVERIFY(qAbs(qAlpha(line[i]) - i) < 3); // linear alpha + QCOMPARE(qGreen(line[i]), 0); // no green component + } +} + +void tst_QPainter::drawPolygon() +{ + QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); + + QPainterPathStroker stroker; + stroker.setWidth(1.5); + + QPainterPath path; + path.moveTo(2, 34); + path.lineTo(34, 2); + + QPolygonF poly = stroker.createStroke(path).toFillPolygon(); + + img.fill(0xffffffff); + QPainter p(&img); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(Qt::red); + p.setPen(Qt::NoPen); + p.drawPolygon(poly); + p.translate(64, 64); + p.drawPolygon(poly); + p.end(); + + QImage a = img.copy(); + + img.fill(0xffffffff); + p.begin(&img); + p.setRenderHint(QPainter::Antialiasing); + p.setBrush(Qt::red); + p.setPen(Qt::NoPen); + p.translate(64, 64); + p.drawPolygon(poly); + p.resetTransform(); + p.drawPolygon(poly); + p.end(); + + QCOMPARE(a, img); +} + +void tst_QPainter::inactivePainter() +{ + // This test succeeds if it doesn't segfault. + + QPainter p; + QPainterPath path; + QRegion region(QRect(20, 20, 60, 40)); + QPolygonF polygon(QVector<QPointF>() << QPointF(0, 0) << QPointF(12, 0) << QPointF(8, 6)); + path.addPolygon(polygon); + + p.save(); + p.restore(); + + p.background(); + p.setBackground(QBrush(Qt::blue)); + + p.brush(); + p.setBrush(Qt::red); + p.setBrush(Qt::NoBrush); + p.setBrush(QBrush(Qt::white, Qt::DiagCrossPattern)); + + p.backgroundMode(); + p.setBackgroundMode(Qt::OpaqueMode); + + p.boundingRect(QRectF(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!")); + p.boundingRect(QRect(0, 0, 100, 20), Qt::AlignCenter, QLatin1String("Hello, World!")); + + p.brushOrigin(); + p.setBrushOrigin(QPointF(12, 34)); + p.setBrushOrigin(QPoint(12, 34)); + + p.clipPath(); + p.clipRegion(); + p.hasClipping(); + p.setClipPath(path); + p.setClipRect(QRectF(42, 42, 42, 42)); + p.setClipRect(QRect(42, 42, 42, 42)); + p.setClipRegion(region); + p.setClipping(true); + + p.combinedMatrix(); + p.combinedTransform(); + + p.compositionMode(); + p.setCompositionMode(QPainter::CompositionMode_Plus); + + p.device(); + p.deviceMatrix(); + p.deviceTransform(); + + p.font(); + p.setFont(QFont(QLatin1String("Times"), 24)); + + p.fontInfo(); + p.fontMetrics(); + + p.layoutDirection(); + p.setLayoutDirection(Qt::RightToLeft); + + p.opacity(); + p.setOpacity(0.75); + + p.pen(); + p.setPen(QPen(Qt::red)); + p.setPen(Qt::green); + p.setPen(Qt::NoPen); + + p.renderHints(); + p.setRenderHint(QPainter::Antialiasing, true); + p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); + + p.resetMatrix(); + p.resetTransform(); + p.rotate(1); + p.scale(2, 2); + p.shear(-1, 1); + p.translate(3, 14); + + p.viewTransformEnabled(); + p.setViewTransformEnabled(true); + + p.viewport(); + p.setViewport(QRect(10, 10, 620, 460)); + + p.window(); + p.setWindow(QRect(10, 10, 620, 460)); + + p.worldMatrix(); + p.setWorldMatrix(QMatrix().translate(43, 21), true); + p.setWorldMatrixEnabled(true); + + p.transform(); + p.setTransform(QTransform().translate(12, 34), true); + + p.worldTransform(); + p.setWorldTransform(QTransform().scale(0.5, 0.5), true); +} + +bool testCompositionMode(int src, int dst, int expected, QPainter::CompositionMode op, qreal opacity = 1.0) +{ + // The test image needs to be large enough to test SIMD code + const QSize imageSize(100, 100); + + QImage actual(imageSize, QImage::Format_ARGB32_Premultiplied); + actual.fill(QColor(dst, dst, dst).rgb()); + + QPainter p(&actual); + p.setCompositionMode(op); + p.setOpacity(opacity); + p.fillRect(QRect(QPoint(), imageSize), QColor(src, src, src)); + p.end(); + + if (qRed(actual.pixel(0, 0)) != expected) { + qDebug("Fail: mode %d, src[%d] dst [%d] actual [%d] expected [%d]", op, + src, dst, qRed(actual.pixel(0, 0)), expected); + return false; + } else { + QImage refImage(imageSize, QImage::Format_ARGB32_Premultiplied); + refImage.fill(QColor(expected, expected, expected).rgb()); + return actual == refImage; + } +} + +void tst_QPainter::extendedBlendModes() +{ + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode(127, 128, 255, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode(127, 0, 127, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus)); + QVERIFY(testCompositionMode(128, 128, 255, QPainter::CompositionMode_Plus)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(127, 0, 37, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(255, 0, 75, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode(127, 255, 127, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode(255, 127, 127, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Multiply)); + QVERIFY(testCompositionMode(127, 127, 63, QPainter::CompositionMode_Multiply)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode( 63, 0, 63, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode( 0, 63, 63, QPainter::CompositionMode_Screen)); + QVERIFY(testCompositionMode(127, 127, 191, QPainter::CompositionMode_Screen)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Overlay)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Overlay)); + QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_Overlay)); + QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Overlay)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode( 63, 255, 63, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode(255, 63, 63, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode( 63, 127, 63, QPainter::CompositionMode_Darken)); + QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_Darken)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode( 63, 63, 63, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode( 63, 255, 255, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode(255, 63, 255, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Lighten)); + QVERIFY(testCompositionMode(127, 63, 127, QPainter::CompositionMode_Lighten)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorDodge)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorDodge)); + QVERIFY(testCompositionMode( 63, 127, 169, QPainter::CompositionMode_ColorDodge)); + QVERIFY(testCompositionMode(191, 127, 255, QPainter::CompositionMode_ColorDodge)); + QVERIFY(testCompositionMode(127, 191, 255, QPainter::CompositionMode_ColorDodge)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_ColorBurn)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_ColorBurn)); + QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_ColorBurn)); + QVERIFY(testCompositionMode(128, 128, 2, QPainter::CompositionMode_ColorBurn)); + QVERIFY(testCompositionMode(191, 127, 84, QPainter::CompositionMode_ColorBurn)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_HardLight)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_HardLight)); + QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_HardLight)); + QVERIFY(testCompositionMode( 63, 63, 31, QPainter::CompositionMode_HardLight)); + QVERIFY(testCompositionMode(127, 63, 63, QPainter::CompositionMode_HardLight)); + + QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_SoftLight)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_SoftLight)); + QVERIFY(testCompositionMode(127, 127, 126, QPainter::CompositionMode_SoftLight)); + QVERIFY(testCompositionMode( 63, 63, 39, QPainter::CompositionMode_SoftLight)); + QVERIFY(testCompositionMode(127, 63, 62, QPainter::CompositionMode_SoftLight)); + + QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode(127, 127, 0, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode(127, 128, 1, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode(127, 63, 64, QPainter::CompositionMode_Difference)); + QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Difference)); + + QVERIFY(testCompositionMode(255, 255, 0, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode(255, 0, 255, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode(127, 127, 127, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode( 63, 127, 127, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode( 63, 63, 95, QPainter::CompositionMode_Exclusion)); + QVERIFY(testCompositionMode(191, 191, 96, QPainter::CompositionMode_Exclusion)); +} + +void tst_QPainter::zeroOpacity() +{ + QImage source(1, 1, QImage::Format_ARGB32_Premultiplied); + source.fill(0xffffffff); + + QImage target(1, 1, QImage::Format_RGB32); + target.fill(0xff000000); + + QPainter p(&target); + p.setOpacity(0.0); + p.drawImage(0, 0, source); + p.end(); + + QCOMPARE(target.pixel(0, 0), 0xff000000); +} + +void tst_QPainter::clippingBug() +{ + QImage img(32, 32, QImage::Format_ARGB32_Premultiplied); + img.fill(0); + + QImage expected = img; + QPainter p(&expected); + p.fillRect(1, 1, 30, 30, Qt::red); + p.end(); + + QPainterPath path; + path.addRect(1, 1, 30, 30); + path.addRect(1, 1, 30, 30); + path.addRect(1, 1, 30, 30); + + p.begin(&img); + p.setClipPath(path); + p.fillRect(0, 0, 32, 32, Qt::red); + p.end(); + + QCOMPARE(img, expected); +} + +void tst_QPainter::emptyClip() +{ + QImage img(64, 64, QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + p.setRenderHints(QPainter::Antialiasing); + p.setClipRect(0, 32, 64, 0); + p.fillRect(0, 0, 64, 64, Qt::white); + + QPainterPath path; + path.lineTo(64, 0); + path.lineTo(64, 64); + path.lineTo(40, 64); + path.lineTo(40, 80); + path.lineTo(0, 80); + + p.fillPath(path, Qt::green); +} + +void tst_QPainter::drawImage_1x1() +{ + QImage source(1, 1, QImage::Format_ARGB32_Premultiplied); + source.fill(0xffffffff); + + QImage img(32, 32, QImage::Format_ARGB32_Premultiplied); + img.fill(0xff000000); + QPainter p(&img); + p.drawImage(QRectF(0.9, 0.9, 32, 32), source); + p.end(); + + QImage expected = img; + expected.fill(0xff000000); + p.begin(&expected); + p.fillRect(1, 1, 31, 31, Qt::white); + p.end(); + + QCOMPARE(img, expected); +} + +void tst_QPainter::taskQT4444_dontOverflowDashOffset() +{ + QPainter p; + + QPen pen; + pen.setWidth(2); + pen.setStyle(Qt::DashDotLine); + + QPointF point[4]; + point[0] = QPointF(182.50868749707968,347.78457234212630); + point[1] = QPointF(182.50868749707968,107.22501998401277); + point[2] = QPointF(182.50868749707968,107.22501998401277); + point[3] = QPointF(520.46600762283651,107.22501998401277); + + QImage crashImage(QSize(1000, 120), QImage::Format_ARGB32_Premultiplied); + p.begin(&crashImage); + p.setPen(pen); + p.drawLines(point, 2); + p.end(); + + QVERIFY(true); // Don't crash +} + +void tst_QPainter::painterBegin() +{ + QImage nullImage; + QImage indexed8Image(16, 16, QImage::Format_Indexed8); + QImage rgb32Image(16, 16, QImage::Format_RGB32); + QImage argb32Image(16, 16, QImage::Format_ARGB32_Premultiplied); + + QPainter p; + + // Painting on null image should fail. + QVERIFY(!p.begin(&nullImage)); + + // Check that the painter is not messed up by using it on another image. + QVERIFY(p.begin(&rgb32Image)); + QVERIFY(p.end()); + + // If painting on indexed8 image fails, the painter state should still be OK. + if (p.begin(&indexed8Image)) + QVERIFY(p.end()); + QVERIFY(p.begin(&rgb32Image)); + QVERIFY(p.end()); + + // Try opening a painter on the two different images. + QVERIFY(p.begin(&rgb32Image)); + QVERIFY(!p.begin(&argb32Image)); + QVERIFY(p.end()); + + // Try opening two painters on the same image. + QVERIFY(p.begin(&rgb32Image)); + QPainter q; + QVERIFY(!q.begin(&rgb32Image)); + QVERIFY(!q.end()); + QVERIFY(p.end()); + + // Try ending an inactive painter. + QVERIFY(!p.end()); +} + +void tst_QPainter::setPenColor(QPainter& p) +{ + p.setPen(Qt::NoPen); + + // Setting color, then style + // Should work even though the pen is "NoPen with color", temporarily. + QPen newPen(p.pen()); + newPen.setColor(Qt::red); + QCOMPARE(p.pen().style(), newPen.style()); + QCOMPARE(p.pen().style(), Qt::NoPen); + p.setPen(newPen); + + QCOMPARE(p.pen().color().name(), QString("#ff0000")); + + QPen newPen2(p.pen()); + newPen2.setStyle(Qt::SolidLine); + p.setPen(newPen2); + + QCOMPARE(p.pen().color().name(), QString("#ff0000")); +} + +void tst_QPainter::setPenColorOnImage() +{ + QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); + QPainter p(&img); + setPenColor(p); +} + +void tst_QPainter::setPenColorOnPixmap() +{ + QPixmap pix(10, 10); + QPainter p(&pix); + setPenColor(p); +} + +class TestProxy : public QGraphicsProxyWidget +{ +public: + TestProxy() : QGraphicsProxyWidget() {} + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + { + QGraphicsProxyWidget::paint(painter, option, widget); + deviceTransform = painter->deviceTransform(); + } + QTransform deviceTransform; +}; + +class TestWidget : public QWidget +{ +Q_OBJECT +public: + TestWidget() : QWidget(), painted(false) {} + void paintEvent(QPaintEvent *) + { + QPainter p(this); + deviceTransform = p.deviceTransform(); + worldTransform = p.worldTransform(); + painted = true; + } + QTransform deviceTransform; + QTransform worldTransform; + bool painted; +}; + +void tst_QPainter::QTBUG5939_attachPainterPrivate() +{ + QWidget *w = new QWidget(); + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsView *view = new QGraphicsView(scene, w); + view->move(50 ,50); + TestProxy *proxy = new TestProxy(); + TestWidget *widget = new TestWidget(); + proxy->setWidget(widget); + scene->addItem(proxy); + proxy->rotate(45); + w->resize(scene->sceneRect().size().toSize()); + + w->show(); + QTRY_VERIFY(widget->painted); + + QVERIFY(widget->worldTransform.isIdentity()); + QCOMPARE(widget->deviceTransform, proxy->deviceTransform); +} + +void tst_QPainter::clipBoundingRect() +{ + QPixmap pix(500, 500); + + QPainter p(&pix); + + // Test a basic rectangle + p.setClipRect(100, 100, 200, 100); + QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); + p.setClipRect(120, 120, 20, 20, Qt::IntersectClip); + QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + + // Test a basic float rectangle + p.setClipRect(QRectF(100, 100, 200, 100)); + QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); + p.setClipRect(QRectF(120, 120, 20, 20), Qt::IntersectClip); + QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + + // Test a basic path + region + QPainterPath path; + path.addRect(100, 100, 200, 100); + p.setClipPath(path); + QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200))); + p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip); + QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100))); + + p.setClipRect(0, 0, 500, 500); + p.translate(250, 250); + for (int i=0; i<360; ++i) { + p.rotate(1); + p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip); + } + QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200))); + QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500))); + +} + +void tst_QPainter::drawText_subPixelPositionsInRaster_qtbug5053() +{ +#if !defined(Q_WS_MAC) || !defined(QT_MAC_USE_COCOA) + QSKIP("Only Mac/Cocoa supports sub pixel positions in raster engine currently", SkipAll); +#endif + QFontMetricsF fm(qApp->font()); + + QImage baseLine(fm.width(QChar::fromLatin1('e')), fm.height(), QImage::Format_RGB32); + baseLine.fill(Qt::white); + { + QPainter p(&baseLine); + p.drawText(0, fm.ascent(), QString::fromLatin1("e")); + } + + bool foundDifferentRasterization = false; + for (int i=1; i<12; ++i) { + QImage comparison(baseLine.size(), QImage::Format_RGB32); + comparison.fill(Qt::white); + + { + QPainter p(&comparison); + p.drawText(QPointF(i / 12.0, fm.ascent()), QString::fromLatin1("e")); + } + + if (comparison != baseLine) { + foundDifferentRasterization = true; + break; + } + } + + QVERIFY(foundDifferentRasterization); +} + +void tst_QPainter::drawPointScaled() +{ + QImage image(32, 32, QImage::Format_RGB32); + image.fill(0xffffffff); + + QPainter p(&image); + + p.scale(0.1, 0.1); + + QPen pen; + pen.setWidth(1000); + pen.setColor(Qt::red); + + p.setPen(pen); + p.drawPoint(0, 0); + p.end(); + + QCOMPARE(image.pixel(16, 16), 0xffff0000); +} + +class GradientProducer : public QThread +{ +protected: + void run(); +}; + +void GradientProducer::run() +{ + QImage image(1, 1, QImage::Format_RGB32); + QPainter p(&image); + + for (int i = 0; i < 1000; ++i) { + QLinearGradient g; + g.setColorAt(0, QColor(i % 256, 0, 0)); + g.setColorAt(1, Qt::white); + + p.fillRect(image.rect(), g); + } +} + +void tst_QPainter::QTBUG14614_gradientCacheRaceCondition() +{ + const int threadCount = 16; + GradientProducer producers[threadCount]; + for (int i = 0; i < threadCount; ++i) + producers[i].start(); + for (int i = 0; i < threadCount; ++i) + producers[i].wait(); +} + +void tst_QPainter::drawTextOpacity() +{ + QImage image(32, 32, QImage::Format_RGB32); + image.fill(0xffffffff); + + QPainter p(&image); + p.setPen(QColor("#6F6F6F")); + p.setOpacity(0.5); + p.drawText(5, 30, QLatin1String("Qt")); + p.end(); + + QImage copy = image; + image.fill(0xffffffff); + + p.begin(&image); + p.setPen(QColor("#6F6F6F")); + p.drawLine(-10, -10, -1, -1); + p.setOpacity(0.5); + p.drawText(5, 30, QLatin1String("Qt")); + p.end(); + + QCOMPARE(image, copy); +} + +void tst_QPainter::QTBUG17053_zeroDashPattern() +{ + QImage image(32, 32, QImage::Format_RGB32); + image.fill(0xffffffff); + + QImage original = image; + + QVector<qreal> pattern; + pattern << qreal(0) << qreal(0); + + QPainter p(&image); + QPen pen(Qt::black, 2.0); + pen.setDashPattern(pattern); + + p.setPen(pen); + p.drawLine(0, 0, image.width(), image.height()); + + QCOMPARE(image, original); +} + +class TextDrawerThread : public QThread +{ +public: + void run(); + QImage rendering; +}; + +void TextDrawerThread::run() +{ + rendering = QImage(100, 100, QImage::Format_ARGB32_Premultiplied); + rendering.fill(0); + QPainter p(&rendering); + p.fillRect(10, 10, 100, 100, Qt::blue); + p.setPen(Qt::green); + p.drawText(20, 20, "some text"); + p.end(); +} + +void tst_QPainter::drawTextOutsideGuiThread() +{ + if (!QFontDatabase::supportsThreadedFontRendering()) + QSKIP("No threaded font rendering", SkipAll); + + QImage referenceRendering(100, 100, QImage::Format_ARGB32_Premultiplied); + referenceRendering.fill(0); + QPainter p(&referenceRendering); + p.fillRect(10, 10, 100, 100, Qt::blue); + p.setPen(Qt::green); + p.drawText(20, 20, "some text"); + p.end(); + + TextDrawerThread t; + t.start(); + t.wait(); + + QCOMPARE(referenceRendering, t.rendering); +} + +QTEST_MAIN(tst_QPainter) + +#include "tst_qpainter.moc" diff --git a/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro b/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro new file mode 100644 index 0000000000..ce2d341e92 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/utils/createImages/createImages.pro @@ -0,0 +1,11 @@ +###################################################################### +# Automatically generated by qmake (1.02a) Thu Apr 18 18:56:53 2002 +###################################################################### + +TEMPLATE = app +CONFIG -= moc + +# Input +SOURCES += main.cpp + + diff --git a/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp b/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp new file mode 100644 index 0000000000..418c385717 --- /dev/null +++ b/tests/auto/gui/painting/qpainter/utils/createImages/main.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <qapplication.h> +#include <qpixmap.h> +#include <qpainter.h> +#include <qbitmap.h> + +static QColor baseColor( int k, int intensity ) +{ + int r = ( k & 1 ) * intensity; + int g = ( (k>>1) & 1 ) * intensity; + int b = ( (k>>2) & 1 ) * intensity; + return QColor( r, g, b ); +} + +static QPixmap createDestPixmap() +{ + const int colorbands = 3; + const int intensities = 4; + QPixmap pm( 32, colorbands*intensities*4 ); + QPainter painter; + painter.begin( &pm ); + for ( int i=0; i<colorbands; i++ ) { + for ( int j=0; j<intensities; j++ ) { + int intensity = 255 * (j+1) / intensities; // 25%, 50%, 75% and 100% + for ( int k=0; k<8; k++ ) { + QColor col = baseColor( k, intensity ); + painter.setPen( QPen( col, 1 ) ); + painter.setBrush( col ); + painter.drawRect( k*4, j*4 + i*intensities*4, 4, 4 ); + } + } + } + painter.end(); + return pm; +} + +static QBitmap createDestBitmap() +{ + // create a bitmap that looks like: + // (0 is color0 and 1 is color1) + // 00001111 + // 00001111 + // 00001111 + // 00001111 + // 00001111 + // 00001111 + // 00001111 + // 00001111 + QBitmap bm( 8, 8 ); + QPainter painter; + painter.begin( &bm ); + painter.setPen( QPen( Qt::color0, 4 ) ); + painter.drawLine( 2, 0, 2, 8 ); + painter.setPen( QPen( Qt::color1, 4 ) ); + painter.drawLine( 6, 0, 6, 8 ); + painter.end(); + return bm; +} + +static QBitmap createSrcBitmap( int size, int border ) +{ + // create the source bitmap that looks like + // (for size=4 and border=2): + // + // + // 1111 + // 1111 + // 0000 + // 0000 + // + // + // If \a border is 0, the bitmap does not have a mask, otherwise the inner + // part is masked. + // \a size specifies the size of the inner (i.e. masked) part. It should be + // a multiple of 2. + int size2 = size/2; + int totalSize = 2 * ( size2 + border ); + QBitmap bm( totalSize, totalSize ); + QPainter painter; + painter.begin( &bm ); + painter.setPen( QPen( Qt::color0, 1 ) ); + painter.setBrush( Qt::color0 ); + painter.drawRect( border, size2+border, size, size2 ); + painter.setPen( QPen( Qt::color1, 1 ) ); + painter.setBrush( Qt::color1 ); + painter.drawRect( border, border, size, size2 ); + painter.end(); + if ( border > 0 ) { + QBitmap mask( totalSize, totalSize, TRUE ); + QPainter painter; + painter.begin( &mask ); + painter.setPen( QPen( Qt::color1, 1 ) ); + painter.setBrush( Qt::color1 ); + painter.drawRect( border, border, size, size ); + painter.end(); + bm.setMask( mask ); + } + return bm; +} + + +int main( int argc, char **argv ) +{ + QApplication a( argc, argv ); + + // input for tst_QPainter::drawLine_rop_bitmap() + { + QBitmap dst = createDestBitmap(); + dst.save( "../../drawLine_rop_bitmap/dst.xbm", "XBM" ); + } + + // input for tst_QPainter::drawPixmap_rop_bitmap() + { + QBitmap dst = createDestBitmap(); + QBitmap src1 = createSrcBitmap( 4, 2 ); + QBitmap src2 = createSrcBitmap( 4, 0 ); + dst.save( "../../drawPixmap_rop_bitmap/dst.xbm", "XBM" ); + src1.save( "../../drawPixmap_rop_bitmap/src1.xbm", "XBM" ); + src1.mask()->save( "../../drawPixmap_rop_bitmap/src1-mask.xbm", "XBM" ); + src2.save( "../../drawPixmap_rop_bitmap/src2.xbm", "XBM" ); + } + + // input for tst_QPainter::drawPixmap_rop() + { + QPixmap dst1 = createDestPixmap(); + QPixmap dst2 = createDestPixmap(); + dst2.resize( 32, 32 ); + QBitmap src1 = createSrcBitmap( 32, 0 ); + + QBitmap src_tmp = createSrcBitmap( 32, 0 ).xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) ); + src_tmp.resize( 32, 48 ); + QBitmap src2 = src_tmp.xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) ); + QBitmap mask( 32, 48, TRUE ); + { + QPainter painter; + painter.begin( &mask ); + painter.setPen( QPen( Qt::color1, 1 ) ); + painter.setBrush( Qt::color1 ); + painter.drawRect( 0, 16, 32, 32 ); + painter.end(); + } + src2.setMask( mask ); + + QBitmap src3 = createSrcBitmap( 32, 0 ).xForm( QWMatrix( 1, 0, 0, -1, 0, 0 ) ); + + dst1.save( "../../drawPixmap_rop/dst1.png", "PNG" ); + dst2.save( "../../drawPixmap_rop/dst2.png", "PNG" ); + src1.save( "../../drawPixmap_rop/src1.xbm", "XBM" ); + src2.save( "../../drawPixmap_rop/src2.xbm", "XBM" ); + src2.mask()->save( "../../drawPixmap_rop/src2-mask.xbm", "XBM" ); + src3.save( "../../drawPixmap_rop/src3.xbm", "XBM" ); + } +} diff --git a/tests/auto/gui/painting/qpainterpath/.gitignore b/tests/auto/gui/painting/qpainterpath/.gitignore new file mode 100644 index 0000000000..4e0e797989 --- /dev/null +++ b/tests/auto/gui/painting/qpainterpath/.gitignore @@ -0,0 +1,2 @@ +tst_qpainterpath +data diff --git a/tests/auto/gui/painting/qpainterpath/qpainterpath.pro b/tests/auto/gui/painting/qpainterpath/qpainterpath.pro new file mode 100644 index 0000000000..9708222c99 --- /dev/null +++ b/tests/auto/gui/painting/qpainterpath/qpainterpath.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_qpainterpath.cpp + + + diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp new file mode 100644 index 0000000000..33315adc06 --- /dev/null +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -0,0 +1,1332 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qfile.h> +#include <qpainterpath.h> +#include <qpen.h> + +#define _USE_MATH_DEFINES +#include <math.h> + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPainterPath : public QObject +{ + Q_OBJECT + +public: + +private slots: + void getSetCheck(); + void swap(); + + void contains_QPointF_data(); + void contains_QPointF(); + + void contains_QRectF_data(); + void contains_QRectF(); + + void intersects_QRectF_data(); + void intersects_QRectF(); + + void testContainsAndIntersects_data(); + void testContainsAndIntersects(); + + void testSimplified_data(); + void testSimplified(); + + void testStroker_data(); + void testStroker(); + + void currentPosition(); + + void testOperatorEquals(); + void testOperatorEquals_fuzzy(); + void testOperatorDatastream(); + + void testArcMoveTo_data(); + void testArcMoveTo(); + void setElementPositionAt(); + + void testOnPath_data(); + void testOnPath(); + + void pointAtPercent_data(); + void pointAtPercent(); + + void angleAtPercent(); + + void arcWinding_data(); + void arcWinding(); + + void testToFillPolygons(); + + void testNaNandInfinites(); + + void closing(); + + void operators_data(); + void operators(); + + void connectPathDuplicatePoint(); + void connectPathMoveTo(); + + void translate(); + + void lineWithinBounds(); +}; + +// Testing get/set functions +void tst_QPainterPath::getSetCheck() +{ + QPainterPathStroker obj1; + // qreal QPainterPathStroker::width() + // void QPainterPathStroker::setWidth(qreal) + obj1.setWidth(0.0); + QCOMPARE(qreal(1.0), obj1.width()); // Pathstroker sets with to 1 if <= 0 + obj1.setWidth(0.5); + QCOMPARE(qreal(0.5), obj1.width()); + obj1.setWidth(1.1); + QCOMPARE(qreal(1.1), obj1.width()); + + // qreal QPainterPathStroker::miterLimit() + // void QPainterPathStroker::setMiterLimit(qreal) + obj1.setMiterLimit(0.0); + QCOMPARE(qreal(0.0), obj1.miterLimit()); + obj1.setMiterLimit(1.1); + QCOMPARE(qreal(1.1), obj1.miterLimit()); + + // qreal QPainterPathStroker::curveThreshold() + // void QPainterPathStroker::setCurveThreshold(qreal) + obj1.setCurveThreshold(0.0); + QCOMPARE(qreal(0.0), obj1.curveThreshold()); + obj1.setCurveThreshold(1.1); + QCOMPARE(qreal(1.1), obj1.curveThreshold()); +} + +void tst_QPainterPath::swap() +{ + QPainterPath p1; + p1.addRect( 0, 0,10,10); + QPainterPath p2; + p2.addRect(10,10,10,10); + p1.swap(p2); + QCOMPARE(p1.boundingRect().toRect(), QRect(10,10,10,10)); + QCOMPARE(p2.boundingRect().toRect(), QRect( 0, 0,10,10)); +} + +Q_DECLARE_METATYPE(QPainterPath) +Q_DECLARE_METATYPE(QPointF) +Q_DECLARE_METATYPE(QRectF) + +void tst_QPainterPath::currentPosition() +{ + QPainterPath p; + + QCOMPARE(p.currentPosition(), QPointF()); + + p.moveTo(100, 100); + QCOMPARE(p.currentPosition(), QPointF(100, 100)); + + p.lineTo(200, 200); + QCOMPARE(p.currentPosition(), QPointF(200, 200)); + + p.cubicTo(300, 200, 200, 300, 500, 500); + QCOMPARE(p.currentPosition(), QPointF(500, 500)); +} + +void tst_QPainterPath::contains_QPointF_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QPointF>("pt"); + QTest::addColumn<bool>("contained"); + + QPainterPath path; + path.addRect(0, 0, 100, 100); + + // ##### + // # # + // # # + // # # + // ##### + + QTest::newRow("[0,0] in [0,0,100,100]") << path << QPointF(0, 0) << true; + + QTest::newRow("[99,0] in [0,0,100,100]") << path << QPointF(99, 0) << true; + QTest::newRow("[0,99] in [0,0,100,100]") << path << QPointF(0, 99) << true; + QTest::newRow("[99,99] in [0,0,100,100]") << path << QPointF(99, 99) << true; + + QTest::newRow("[99.99,0] in [0,0,100,100]") << path << QPointF(99.99, 0) << true; + QTest::newRow("[0,99.99] in [0,0,100,100]") << path << QPointF(0, 99.99) << true; + QTest::newRow("[99.99,99.99] in [0,0,100,100]") << path << QPointF(99.99, 99.99) << true; + + QTest::newRow("[0.01,0.01] in [0,0,100,100]") << path << QPointF(0.01, 0.01) << true; + QTest::newRow("[0,0.01] in [0,0,100,100]") << path << QPointF(0, 0.01) << true; + QTest::newRow("[0.01,0] in [0,0,100,100]") << path << QPointF(0.01, 0) << true; + + QTest::newRow("[-0.01,-0.01] in [0,0,100,100]") << path << QPointF(-0.01, -0.01) << false; + QTest::newRow("[-0,-0.01] in [0,0,100,100]") << path << QPointF(0, -0.01) << false; + QTest::newRow("[-0.01,0] in [0,0,100,100]") << path << QPointF(-0.01, 0) << false; + + + QTest::newRow("[-10,0] in [0,0,100,100]") << path << QPointF(-10, 0) << false; + QTest::newRow("[100,0] in [0,0,100,100]") << path << QPointF(100, 0) << false; + + QTest::newRow("[0,-10] in [0,0,100,100]") << path << QPointF(0, -10) << false; + QTest::newRow("[0,100] in [0,0,100,100]") << path << QPointF(0, 100) << false; + + QTest::newRow("[100.1,0] in [0,0,100,100]") << path << QPointF(100.1, 0) << false; + QTest::newRow("[0,100.1] in [0,0,100,100]") << path << QPointF(0, 100.1) << false; + + path.addRect(50, 50, 100, 100); + + // ##### + // # # + // # ##### + // # # # # + // ##### # + // # # + // ##### + + QTest::newRow("[49,49] in 2 rects") << path << QPointF(49,49) << true; + QTest::newRow("[50,50] in 2 rects") << path << QPointF(50,50) << false; + QTest::newRow("[100,100] in 2 rects") << path << QPointF(100,100) << true; + + path.setFillRule(Qt::WindingFill); + QTest::newRow("[50,50] in 2 rects (winding)") << path << QPointF(50,50) << true; + + path.addEllipse(0, 0, 150, 150); + + // ##### + // ## ## + // # ##### + // # # # # + // ##### # + // ## ## + // ##### + + QTest::newRow("[50,50] in complex (winding)") << path << QPointF(50, 50) << true; + + path.setFillRule(Qt::OddEvenFill); + QTest::newRow("[50,50] in complex (windinf)") << path << QPointF(50, 50) << true; + QTest::newRow("[49,49] in complex") << path << QPointF(49,49) << false; + QTest::newRow("[100,100] in complex") << path << QPointF(49,49) << false; + + + // unclosed triangle + path = QPainterPath(); + path.moveTo(100, 100); + path.lineTo(130, 70); + path.lineTo(150, 110); + + QTest::newRow("[100,100] in triangle") << path << QPointF(100, 100) << true; + QTest::newRow("[140,100] in triangle") << path << QPointF(140, 100) << true; + QTest::newRow("[130,80] in triangle") << path << QPointF(130, 80) << true; + + QTest::newRow("[110,80] in triangle") << path << QPointF(110, 80) << false; + QTest::newRow("[150,100] in triangle") << path << QPointF(150, 100) << false; + QTest::newRow("[120,110] in triangle") << path << QPointF(120, 110) << false; + + QRectF base_rect(0, 0, 20, 20); + + path = QPainterPath(); + path.addEllipse(base_rect); + + // not strictly precise, but good enougth to verify fair precision. + QPainterPath inside; + inside.addEllipse(base_rect.adjusted(5, 5, -5, -5)); + QPolygonF inside_poly = inside.toFillPolygon(); + for (int i=0; i<inside_poly.size(); ++i) + QTest::newRow("inside_ellipse") << path << inside_poly.at(i) << true; + + QPainterPath outside; + outside.addEllipse(base_rect.adjusted(-5, -5, 5, 5)); + QPolygonF outside_poly = outside.toFillPolygon(); + for (int i=0; i<outside_poly.size(); ++i) + QTest::newRow("outside_ellipse") << path << outside_poly.at(i) << false; + + path = QPainterPath(); + base_rect = QRectF(50, 50, 200, 200); + path.addEllipse(base_rect); + path.setFillRule(Qt::WindingFill); + + QTest::newRow("topleft outside ellipse") << path << base_rect.topLeft() << false; + QTest::newRow("topright outside ellipse") << path << base_rect.topRight() << false; + QTest::newRow("bottomright outside ellipse") << path << base_rect.bottomRight() << false; + QTest::newRow("bottomleft outside ellipse") << path << base_rect.bottomLeft() << false; + + // Test horizontal curve segment + path = QPainterPath(); + path.moveTo(100, 100); + path.cubicTo(120, 100, 180, 100, 200, 100); + path.lineTo(150, 200); + path.closeSubpath(); + + QTest::newRow("horizontal cubic, out left") << path << QPointF(0, 100) << false; + QTest::newRow("horizontal cubic, out right") << path << QPointF(300, 100) <<false; + QTest::newRow("horizontal cubic, in mid") << path << QPointF(150, 100) << true; + + path = QPainterPath(); + path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0)); + QTest::newRow("huge ellipse, qreal=float crash") << path << QPointF(1100000.35, 1098000.2) << true; + +} + +void tst_QPainterPath::contains_QPointF() +{ + QFETCH(QPainterPath, path); + QFETCH(QPointF, pt); + QFETCH(bool, contained); + + QCOMPARE(path.contains(pt), contained); +} + +void tst_QPainterPath::contains_QRectF_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QRectF>("rect"); + QTest::addColumn<bool>("contained"); + + QPainterPath path; + path.addRect(0, 0, 100, 100); + + QTest::newRow("same rect") << path << QRectF(0.1, 0.1, 99, 99) << true; // ### + QTest::newRow("outside") << path << QRectF(-1, -1, 100, 100) << false; + QTest::newRow("covers") << path << QRectF(-1, -1, 102, 102) << false; + QTest::newRow("left") << path << QRectF(-10, 50, 5, 5) << false; + QTest::newRow("top") << path << QRectF(50, -10, 5, 5) << false; + QTest::newRow("right") << path << QRectF(110, 50, 5, 5) << false; + QTest::newRow("bottom") << path << QRectF(50, 110, 5, 5) << false; + + path.addRect(50, 50, 100, 100); + + QTest::newRow("r1 top") << path << QRectF(0.1, 0.1, 99, 49) << true; + QTest::newRow("r1 left") << path << QRectF(0.1, 0.1, 49, 99) << true; + QTest::newRow("r2 right") << path << QRectF(100.01, 50.1, 49, 99) << true; + QTest::newRow("r2 bottom") << path << QRectF(50.1, 100.1, 99, 49) << true; + QTest::newRow("inside 2 rects") << path << QRectF(51, 51, 48, 48) << false; + QTest::newRow("topRight 2 rects") << path << QRectF(100, 0, 49, 49) << false; + QTest::newRow("bottomLeft 2 rects") << path << QRectF(0, 100, 49, 49) << false; + + path.setFillRule(Qt::WindingFill); + QTest::newRow("inside 2 rects (winding)") << path << QRectF(51, 51, 48, 48) << true; + + path.addEllipse(0, 0, 150, 150); + QTest::newRow("topRight 2 rects") << path << QRectF(100, 25, 24, 24) << true; + QTest::newRow("bottomLeft 2 rects") << path << QRectF(25, 100, 24, 24) << true; + + path.setFillRule(Qt::OddEvenFill); + QTest::newRow("inside 2 rects") << path << QRectF(50, 50, 49, 49) << false; +} + +void tst_QPainterPath::contains_QRectF() +{ + QFETCH(QPainterPath, path); + QFETCH(QRectF, rect); + QFETCH(bool, contained); + + QCOMPARE(path.contains(rect), contained); +} + +static inline QPainterPath rectPath(qreal x, qreal y, qreal w, qreal h) +{ + QPainterPath path; + path.addRect(x, y, w, h); + path.closeSubpath(); + return path; +} + +static inline QPainterPath ellipsePath(qreal x, qreal y, qreal w, qreal h) +{ + QPainterPath path; + path.addEllipse(x, y, w, h); + path.closeSubpath(); + return path; +} + +static inline QPainterPath linePath(qreal x1, qreal y1, qreal x2, qreal y2) +{ + QPainterPath path; + path.moveTo(x1, y1); + path.lineTo(x2, y2); + return path; +} + +void tst_QPainterPath::intersects_QRectF_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QRectF>("rect"); + QTest::addColumn<bool>("intersects"); + + QPainterPath path; + path.addRect(0, 0, 100, 100); + + QTest::newRow("same rect") << path << QRectF(0.1, 0.1, 99, 99) << true; // ### + QTest::newRow("outside") << path << QRectF(-1, -1, 100, 100) << true; + QTest::newRow("covers") << path << QRectF(-1, -1, 102, 102) << true; + QTest::newRow("left") << path << QRectF(-10, 50, 5, 5) << false; + QTest::newRow("top") << path << QRectF(50, -10, 5, 5) << false; + QTest::newRow("right") << path << QRectF(110, 50, 5, 5) << false; + QTest::newRow("bottom") << path << QRectF(50, 110, 5, 5) << false; + + path.addRect(50, 50, 100, 100); + + QTest::newRow("r1 top") << path << QRectF(0.1, 0.1, 99, 49) << true; + QTest::newRow("r1 left") << path << QRectF(0.1, 0.1, 49, 99) << true; + QTest::newRow("r2 right") << path << QRectF(100.01, 50.1, 49, 99) << true; + QTest::newRow("r2 bottom") << path << QRectF(50.1, 100.1, 99, 49) << true; + QTest::newRow("inside 2 rects") << path << QRectF(51, 51, 48, 48) << false; + + path.setFillRule(Qt::WindingFill); + QTest::newRow("inside 2 rects (winding)") << path << QRectF(51, 51, 48, 48) << true; + + path.addEllipse(0, 0, 150, 150); + QTest::newRow("topRight 2 rects") << path << QRectF(100, 25, 24, 24) << true; + QTest::newRow("bottomLeft 2 rects") << path << QRectF(25, 100, 24, 24) << true; + + QTest::newRow("horizontal line") << linePath(0, 0, 10, 0) << QRectF(1, -1, 2, 2) << true; + QTest::newRow("vertical line") << linePath(0, 0, 0, 10) << QRectF(-1, 1, 2, 2) << true; + + path = QPainterPath(); + path.addEllipse(QRectF(-5000.0, -5000.0, 1500000.0, 1500000.0)); + QTest::newRow("huge ellipse, qreal=float crash") << path << QRectF(1100000.35, 1098000.2, 1500000.0, 1500000.0) << true; +} + +void tst_QPainterPath::intersects_QRectF() +{ + QFETCH(QPainterPath, path); + QFETCH(QRectF, rect); + QFETCH(bool, intersects); + + QCOMPARE(path.intersects(rect), intersects); +} + + +void tst_QPainterPath::testContainsAndIntersects_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QPainterPath>("candidate"); + QTest::addColumn<bool>("contained"); + QTest::addColumn<bool>("intersects"); + + QTest::newRow("rect vs small ellipse (upper left)") << rectPath(0, 0, 100, 100) << ellipsePath(0, 0, 50, 50) << false << true; + QTest::newRow("rect vs small ellipse (upper right)") << rectPath(0, 0, 100, 100) << ellipsePath(50, 0, 50, 50) << false << true; + QTest::newRow("rect vs small ellipse (lower right)") << rectPath(0, 0, 100, 100) << ellipsePath(50, 50, 50, 50) << false << true; + QTest::newRow("rect vs small ellipse (lower left)") << rectPath(0, 0, 100, 100) << ellipsePath(0, 50, 50, 50) << false << true; + QTest::newRow("rect vs small ellipse (centered)") << rectPath(0, 0, 100, 100) << ellipsePath(25, 25, 50, 50) << true << true; + QTest::newRow("rect vs equal ellipse") << rectPath(0, 0, 100, 100) << ellipsePath(0, 0, 100, 100) << false << true; + QTest::newRow("rect vs big ellipse") << rectPath(0, 0, 100, 100) << ellipsePath(-10, -10, 120, 120) << false << true; + + QPainterPath twoEllipses = ellipsePath(0, 0, 100, 100).united(ellipsePath(200, 0, 100, 100)); + + QTest::newRow("rect vs two small ellipses") << rectPath(0, 0, 100, 100) << ellipsePath(25, 25, 50, 50).united(ellipsePath(225, 25, 50, 50)) << false << true; + QTest::newRow("rect vs two equal ellipses") << rectPath(0, 0, 100, 100) << twoEllipses << false << true; + + QTest::newRow("rect vs self") << rectPath(0, 0, 100, 100) << rectPath(0, 0, 100, 100) << false << true; + QTest::newRow("ellipse vs self") << ellipsePath(0, 0, 100, 100) << ellipsePath(0, 0, 100, 100) << false << true; + + QPainterPath twoRects = rectPath(0, 0, 100, 100).united(rectPath(200, 0, 100, 100)); + QTest::newRow("two rects vs small ellipse (upper left)") << twoRects << ellipsePath(0, 0, 50, 50) << false << true; + QTest::newRow("two rects vs small ellipse (upper right)") << twoRects << ellipsePath(50, 0, 50, 50) << false << true; + QTest::newRow("two rects vs small ellipse (lower right)") << twoRects << ellipsePath(50, 50, 50, 50) << false << true; + QTest::newRow("two rects vs small ellipse (lower left)") << twoRects << ellipsePath(0, 50, 50, 50) << false << true; + QTest::newRow("two rects vs small ellipse (centered)") << twoRects << ellipsePath(25, 25, 50, 50) << true << true; + QTest::newRow("two rects vs equal ellipse") << twoRects << ellipsePath(0, 0, 100, 100) << false << true; + QTest::newRow("two rects vs big ellipse") << twoRects << ellipsePath(-10, -10, 120, 120) << false << true; + + QTest::newRow("two rects vs two small ellipses") << twoRects << ellipsePath(25, 25, 50, 50).united(ellipsePath(225, 25, 50, 50)) << true << true; + QTest::newRow("two rects vs two equal ellipses") << twoRects << ellipsePath(0, 0, 100, 100).united(ellipsePath(200, 0, 100, 100)) << false << true; + + QTest::newRow("two rects vs self") << twoRects << twoRects << false << true; + QTest::newRow("two ellipses vs self") << twoEllipses << twoEllipses << false << true; + + QPainterPath windingRect = rectPath(0, 0, 100, 100); + windingRect.addRect(25, 25, 100, 50); + windingRect.setFillRule(Qt::WindingFill); + + QTest::newRow("rect with winding rule vs tall rect") << windingRect << rectPath(40, 20, 20, 60) << true << true; + QTest::newRow("rect with winding rule vs self") << windingRect << windingRect << false << true; + + QPainterPath thickFrame = rectPath(0, 0, 100, 100).subtracted(rectPath(25, 25, 50, 50)); + QPainterPath thinFrame = rectPath(10, 10, 80, 80).subtracted(rectPath(15, 15, 70, 70)); + + QTest::newRow("thin frame in thick frame") << thickFrame << thinFrame << true << true; + QTest::newRow("rect in thick frame") << thickFrame << rectPath(40, 40, 20, 20) << false << false; + QTest::newRow("rect in thin frame") << thinFrame << rectPath(40, 40, 20, 20) << false << false; + + QPainterPath ellipses; + ellipses.addEllipse(0, 0, 10, 10); + ellipses.addEllipse(4, 4, 2, 2); + ellipses.setFillRule(Qt::WindingFill); + + // the definition of QPainterPath::intersects() and contains() is fill-area based, + QTest::newRow("line in rect") << rectPath(0, 0, 100, 100) << linePath(10, 10, 90, 90) << true << true; + QTest::newRow("horizontal line in rect") << rectPath(0, 0, 100, 100) << linePath(10, 50, 90, 50) << true << true; + QTest::newRow("vertical line in rect") << rectPath(0, 0, 100, 100) << linePath(50, 10, 50, 90) << true << true; + + QTest::newRow("line through rect") << rectPath(0, 0, 100, 100) << linePath(-10, -10, 110, 110) << false << true; + QTest::newRow("line through rect 2") << rectPath(0, 0, 100, 100) << linePath(-10, 0, 110, 100) << false << true; + QTest::newRow("line through rect 3") << rectPath(0, 0, 100, 100) << linePath(5, 10, 110, 100) << false << true; + QTest::newRow("line through rect 4") << rectPath(0, 0, 100, 100) << linePath(-10, 0, 90, 90) << false << true; + + QTest::newRow("horizontal line through rect") << rectPath(0, 0, 100, 100) << linePath(-10, 50, 110, 50) << false << true; + QTest::newRow("vertical line through rect") << rectPath(0, 0, 100, 100) << linePath(50, -10, 50, 110) << false << true; + + QTest::newRow("line vs line") << linePath(0, 0, 10, 10) << linePath(10, 0, 0, 10) << false << true; + + QTest::newRow("line in rect with hole") << rectPath(0, 0, 10, 10).subtracted(rectPath(2, 2, 6, 6)) << linePath(4, 4, 6, 6) << false << false; + QTest::newRow("line in ellipse") << ellipses << linePath(3, 5, 7, 5) << false << true; + QTest::newRow("line in ellipse 2") << ellipses << linePath(4.5, 5, 5.5, 5) << true << true; + + QTest::newRow("winding ellipse") << ellipses << ellipsePath(4, 4, 2, 2) << false << true; + QTest::newRow("winding ellipse 2") << ellipses << ellipsePath(4.5, 4.5, 1, 1) << true << true; + ellipses.setFillRule(Qt::OddEvenFill); + QTest::newRow("odd even ellipse") << ellipses << ellipsePath(4, 4, 2, 2) << false << true; + QTest::newRow("odd even ellipse 2") << ellipses << ellipsePath(4.5, 4.5, 1, 1) << false << false; +} + +void tst_QPainterPath::testContainsAndIntersects() +{ + QFETCH(QPainterPath, path); + QFETCH(QPainterPath, candidate); + QFETCH(bool, contained); + QFETCH(bool, intersects); + + QCOMPARE(path.intersects(candidate), intersects); + QCOMPARE(path.contains(candidate), contained); +} + +void tst_QPainterPath::testSimplified_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<int>("elements"); + + QTest::newRow("rect") << rectPath(0, 0, 10, 10) << 5; + + QPainterPath twoRects = rectPath(0, 0, 10, 10); + twoRects.addPath(rectPath(5, 0, 10, 10)); + QTest::newRow("two rects (odd)") << twoRects << 10; + + twoRects.setFillRule(Qt::WindingFill); + QTest::newRow("two rects (winding)") << twoRects << 5; + + QPainterPath threeSteps = rectPath(0, 0, 10, 10); + threeSteps.addPath(rectPath(0, 10, 20, 10)); + threeSteps.addPath(rectPath(0, 20, 30, 10)); + + QTest::newRow("three rects (steps)") << threeSteps << 9; +} + +void tst_QPainterPath::testSimplified() +{ + QFETCH(QPainterPath, path); + QFETCH(int, elements); + + QPainterPath simplified = path.simplified(); + + QCOMPARE(simplified.elementCount(), elements); + + QVERIFY(simplified.subtracted(path).isEmpty()); + QVERIFY(path.subtracted(simplified).isEmpty()); +} + +void tst_QPainterPath::testStroker_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QPen>("pen"); + QTest::addColumn<QPainterPath>("stroke"); + + QTest::newRow("line 1") << linePath(2, 2, 10, 2) << QPen(Qt::black, 2, Qt::SolidLine, Qt::FlatCap) << rectPath(2, 1, 8, 2); + QTest::newRow("line 2") << linePath(2, 2, 10, 2) << QPen(Qt::black, 2, Qt::SolidLine, Qt::SquareCap) << rectPath(1, 1, 10, 2); + + QTest::newRow("rect") << rectPath(1, 1, 8, 8) << QPen(Qt::black, 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin) << rectPath(0, 0, 10, 10).subtracted(rectPath(2, 2, 6, 6)); + + QTest::newRow("dotted line") << linePath(0, 0, 10, 0) << QPen(Qt::black, 2, Qt::DotLine) << rectPath(-1, -1, 4, 2).united(rectPath(5, -1, 4, 2)); +} + +void tst_QPainterPath::testStroker() +{ + QFETCH(QPainterPath, path); + QFETCH(QPen, pen); + QFETCH(QPainterPath, stroke); + + QPainterPathStroker stroker; + stroker.setWidth(pen.widthF()); + stroker.setCapStyle(pen.capStyle()); + stroker.setJoinStyle(pen.joinStyle()); + stroker.setMiterLimit(pen.miterLimit()); + stroker.setDashPattern(pen.style()); + stroker.setDashOffset(pen.dashOffset()); + + QPainterPath result = stroker.createStroke(path); + + // check if stroke == result + QVERIFY(result.subtracted(stroke).isEmpty()); + QVERIFY(stroke.subtracted(result).isEmpty()); +} + +void tst_QPainterPath::testOperatorEquals() +{ + QPainterPath empty1; + QPainterPath empty2; + QVERIFY(empty1 == empty2); + + QPainterPath rect1; + rect1.addRect(100, 100, 100, 100); + QVERIFY(rect1 == rect1); + QVERIFY(rect1 != empty1); + + QPainterPath rect2; + rect2.addRect(100, 100, 100, 100); + QVERIFY(rect1 == rect2); + + rect2.setFillRule(Qt::WindingFill); + QVERIFY(rect1 != rect2); + + QPainterPath ellipse1; + ellipse1.addEllipse(50, 50, 100, 100); + QVERIFY(rect1 != ellipse1); + + QPainterPath ellipse2; + ellipse2.addEllipse(50, 50, 100, 100); + QVERIFY(ellipse1 == ellipse2); +} + +void tst_QPainterPath::testOperatorEquals_fuzzy() +{ + // if operator== returns true for two paths it should + // also return true when the same transform is applied to both paths + { + QRectF a(100, 100, 100, 50); + QRectF b = a.translated(1e-14, 1e-14); + + QPainterPath pa; + pa.addRect(a); + QPainterPath pb; + pb.addRect(b); + + QVERIFY(pa == pb); + + QTransform transform; + transform.translate(-100, -100); + + QVERIFY(transform.map(pa) == transform.map(pb)); + } + + // higher tolerance for error when path's bounding rect is big + { + QRectF a(1, 1, 1e6, 0.5e6); + QRectF b = a.translated(1e-7, 1e-7); + + QPainterPath pa; + pa.addRect(a); + QPainterPath pb; + pb.addRect(b); + + QVERIFY(pa == pb); + + QTransform transform; + transform.translate(-1, -1); + + QVERIFY(transform.map(pa) == transform.map(pb)); + } + + // operator== should return true for a path that has + // been transformed and then inverse transformed + { + QPainterPath a; + a.addRect(0, 0, 100, 100); + + QTransform transform; + transform.translate(100, 20); + transform.scale(1.5, 1.5); + + QPainterPath b = transform.inverted().map(transform.map(a)); + + QVERIFY(a == b); + } + + { + QPainterPath a; + a.lineTo(10, 0); + a.lineTo(10, 10); + a.lineTo(0, 10); + + QPainterPath b; + b.lineTo(10, 0); + b.moveTo(10, 10); + b.lineTo(0, 10); + + QVERIFY(a != b); + } +} + +void tst_QPainterPath::testOperatorDatastream() +{ + QPainterPath path; + path.addEllipse(0, 0, 100, 100); + path.addRect(0, 0, 100, 100); + path.setFillRule(Qt::WindingFill); + + // Write out + { + QFile data("data"); + bool ok = data.open(QFile::WriteOnly); + QVERIFY(ok); + QDataStream stream(&data); + stream << path; + } + + QPainterPath other; + // Read in + { + QFile data("data"); + bool ok = data.open(QFile::ReadOnly); + QVERIFY(ok); + QDataStream stream(&data); + stream >> other; + } + + QVERIFY(other == path); +} + +void tst_QPainterPath::closing() +{ + // lineto's + { + QPainterPath triangle(QPoint(100, 100)); + + triangle.lineTo(200, 100); + triangle.lineTo(200, 200); + QCOMPARE(triangle.elementCount(), 3); + + triangle.closeSubpath(); + QCOMPARE(triangle.elementCount(), 4); + QCOMPARE(triangle.elementAt(3).type, QPainterPath::LineToElement); + + triangle.moveTo(300, 300); + QCOMPARE(triangle.elementCount(), 5); + QCOMPARE(triangle.elementAt(4).type, QPainterPath::MoveToElement); + + triangle.lineTo(400, 300); + triangle.lineTo(400, 400); + QCOMPARE(triangle.elementCount(), 7); + + triangle.closeSubpath(); + QCOMPARE(triangle.elementCount(), 8); + + // this will should trigger implicit moveto... + triangle.lineTo(600, 300); + QCOMPARE(triangle.elementCount(), 10); + QCOMPARE(triangle.elementAt(8).type, QPainterPath::MoveToElement); + QCOMPARE(triangle.elementAt(9).type, QPainterPath::LineToElement); + + triangle.lineTo(600, 700); + QCOMPARE(triangle.elementCount(), 11); + } + + // curveto's + { + QPainterPath curves(QPoint(100, 100)); + + curves.cubicTo(200, 100, 100, 200, 200, 200); + QCOMPARE(curves.elementCount(), 4); + + curves.closeSubpath(); + QCOMPARE(curves.elementCount(), 5); + QCOMPARE(curves.elementAt(4).type, QPainterPath::LineToElement); + + curves.moveTo(300, 300); + QCOMPARE(curves.elementCount(), 6); + QCOMPARE(curves.elementAt(5).type, QPainterPath::MoveToElement); + + curves.cubicTo(400, 300, 300, 400, 400, 400); + QCOMPARE(curves.elementCount(), 9); + + curves.closeSubpath(); + QCOMPARE(curves.elementCount(), 10); + + // should trigger implicit moveto.. + curves.cubicTo(100, 800, 800, 100, 800, 800); + QCOMPARE(curves.elementCount(), 14); + QCOMPARE(curves.elementAt(10).type, QPainterPath::MoveToElement); + QCOMPARE(curves.elementAt(11).type, QPainterPath::CurveToElement); + } + + { + QPainterPath rects; + rects.addRect(100, 100, 100, 100); + + QCOMPARE(rects.elementCount(), 5); + QCOMPARE(rects.elementAt(0).type, QPainterPath::MoveToElement); + QCOMPARE(rects.elementAt(4).type, QPainterPath::LineToElement); + + rects.addRect(300, 100, 100,100); + QCOMPARE(rects.elementCount(), 10); + QCOMPARE(rects.elementAt(5).type, QPainterPath::MoveToElement); + QCOMPARE(rects.elementAt(9).type, QPainterPath::LineToElement); + + rects.lineTo(0, 0); + QCOMPARE(rects.elementCount(), 12); + QCOMPARE(rects.elementAt(10).type, QPainterPath::MoveToElement); + QCOMPARE(rects.elementAt(11).type, QPainterPath::LineToElement); + } + + { + QPainterPath ellipses; + ellipses.addEllipse(100, 100, 100, 100); + + QCOMPARE(ellipses.elementCount(), 13); + QCOMPARE(ellipses.elementAt(0).type, QPainterPath::MoveToElement); + QCOMPARE(ellipses.elementAt(10).type, QPainterPath::CurveToElement); + + ellipses.addEllipse(300, 100, 100,100); + QCOMPARE(ellipses.elementCount(), 26); + QCOMPARE(ellipses.elementAt(13).type, QPainterPath::MoveToElement); + QCOMPARE(ellipses.elementAt(23).type, QPainterPath::CurveToElement); + + ellipses.lineTo(0, 0); + QCOMPARE(ellipses.elementCount(), 28); + QCOMPARE(ellipses.elementAt(26).type, QPainterPath::MoveToElement); + QCOMPARE(ellipses.elementAt(27).type, QPainterPath::LineToElement); + } + + { + QPainterPath path; + path.moveTo(10, 10); + path.lineTo(40, 10); + path.lineTo(25, 20); + path.lineTo(10 + 1e-13, 10 + 1e-13); + QCOMPARE(path.elementCount(), 4); + path.closeSubpath(); + QCOMPARE(path.elementCount(), 4); + } +} + +void tst_QPainterPath::testArcMoveTo_data() +{ + QTest::addColumn<QRectF>("rect"); + QTest::addColumn<qreal>("angle"); + + QList<QRectF> rects; + rects << QRectF(100, 100, 100, 100) + << QRectF(100, 100, -100, 100) + << QRectF(100, 100, 100, -100) + << QRectF(100, 100, -100, -100); + + for (int domain=0; domain<rects.size(); ++domain) { + for (int i=-360; i<=360; ++i) { + QTest::newRow("test") << rects.at(domain) << (qreal) i; + } + + // test low angles + QTest::newRow("test") << rects.at(domain) << (qreal) 1e-10; + QTest::newRow("test") << rects.at(domain) << (qreal)-1e-10; + } +} + +void tst_QPainterPath::operators_data() +{ + QTest::addColumn<QPainterPath>("test"); + QTest::addColumn<QPainterPath>("expected"); + + QPainterPath a; + QPainterPath b; + a.addRect(0, 0, 100, 100); + b.addRect(50, 50, 100, 100); + + QTest::newRow("a & b") << (a & b) << a.intersected(b); + QTest::newRow("a | b") << (a | b) << a.united(b); + QTest::newRow("a + b") << (a + b) << a.united(b); + QTest::newRow("a - b") << (a - b) << a.subtracted(b); + + QPainterPath c = a; + QTest::newRow("a &= b") << (a &= b) << a.intersected(b); + c = a; + QTest::newRow("a |= b") << (a |= b) << a.united(b); + c = a; + QTest::newRow("a += b") << (a += b) << a.united(b); + c = a; + QTest::newRow("a -= b") << (a -= b) << a.subtracted(b); +} + +void tst_QPainterPath::operators() +{ + QFETCH(QPainterPath, test); + QFETCH(QPainterPath, expected); + + QCOMPARE(test, expected); +} + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +#define ANGLE(t) ((t) * 2 * M_PI / 360.0) + + +static inline bool pathFuzzyCompare(double p1, double p2) +{ + return qAbs(p1 - p2) < 0.001; +} + + +static inline bool pathFuzzyCompare(float p1, float p2) +{ + return qAbs(p1 - p2) < 0.001; +} + + +void tst_QPainterPath::testArcMoveTo() +{ + QFETCH(QRectF, rect); + QFETCH(qreal, angle); + + QPainterPath path; + path.arcMoveTo(rect, angle); + path.arcTo(rect, angle, 30); + path.arcTo(rect, angle + 30, 30); + + QPointF pos = path.elementAt(0); + + QVERIFY((path.elementCount()-1) % 3 == 0); + + qreal x_radius = rect.width() / 2.0; + qreal y_radius = rect.height() / 2.0; + + QPointF shouldBe = rect.center() + + QPointF(x_radius * cos(ANGLE(angle)), -y_radius * sin(ANGLE(angle))); + + qreal iw = 1 / rect.width(); + qreal ih = 1 / rect.height(); + + QVERIFY(pathFuzzyCompare(pos.x() * iw, shouldBe.x() * iw)); + QVERIFY(pathFuzzyCompare(pos.y() * ih, shouldBe.y() * ih)); +} + +void tst_QPainterPath::testOnPath_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<qreal>("start"); + QTest::addColumn<qreal>("middle"); + QTest::addColumn<qreal>("end"); + + QPainterPath path = QPainterPath(QPointF(153, 199)); + path.cubicTo(QPointF(147, 61), QPointF(414, 18), + QPointF(355, 201)); + + QTest::newRow("First case") << path + << qreal(93.0) + << qreal(4.0) + << qreal(252.13); + + path = QPainterPath(QPointF(328, 197)); + path.cubicTo(QPointF(150, 50), QPointF(401, 50), + QPointF(225, 197)); + QTest::newRow("Second case") << path + << qreal(140.0) + << qreal(0.0) + << qreal(220.0); + + path = QPainterPath(QPointF(328, 197)); + path.cubicTo(QPointF(101 , 153), QPointF(596, 151), + QPointF(353, 197)); + QTest::newRow("Third case") << path + << qreal(169.0) + << qreal(0.22) + << qreal(191.0); + + path = QPainterPath(QPointF(153, 199)); + path.cubicTo(QPointF(59, 53), QPointF(597, 218), + QPointF(355, 201)); + QTest::newRow("Fourth case") << path + << qreal(122.0) + << qreal(348.0) + << qreal(175.0); + +} + +#define SIGN(x) ((x < 0)?-1:1) +void tst_QPainterPath::testOnPath() +{ + QFETCH(QPainterPath, path); + QFETCH(qreal, start); + QFETCH(qreal, middle); + QFETCH(qreal, end); + + int signStart = SIGN(start); + int signMid = SIGN(middle); + int signEnd = SIGN(end); + + static const qreal diff = 3; + + qreal angle = path.angleAtPercent(0); + QCOMPARE(SIGN(angle), signStart); + QVERIFY(qAbs(angle-start) < diff); + + angle = path.angleAtPercent(0.5); + QCOMPARE(SIGN(angle), signMid); + QVERIFY(qAbs(angle-middle) < diff); + + angle = path.angleAtPercent(1); + QCOMPARE(SIGN(angle), signEnd); + QVERIFY(qAbs(angle-end) < diff); +} + +void tst_QPainterPath::pointAtPercent_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<qreal>("percent"); + QTest::addColumn<QPointF>("point"); + + QPainterPath path; + path.lineTo(100, 0); + + QTest::newRow("Case 1") << path << qreal(0.2) << QPointF(20, 0); + QTest::newRow("Case 2") << path << qreal(0.5) << QPointF(50, 0); + QTest::newRow("Case 3") << path << qreal(0.0) << QPointF(0, 0); + QTest::newRow("Case 4") << path << qreal(1.0) << QPointF(100, 0); + + path = QPainterPath(); + path.lineTo(0, 100); + + QTest::newRow("Case 5") << path << qreal(0.2) << QPointF(0, 20); + QTest::newRow("Case 6") << path << qreal(0.5) << QPointF(0, 50); + QTest::newRow("Case 7") << path << qreal(0.0) << QPointF(0, 0); + QTest::newRow("Case 8") << path << qreal(1.0) << QPointF(0, 100); + + path.lineTo(300, 100); + + QTest::newRow("Case 9") << path << qreal(0.25) << QPointF(0, 100); + QTest::newRow("Case 10") << path << qreal(0.5) << QPointF(100, 100); + QTest::newRow("Case 11") << path << qreal(0.75) << QPointF(200, 100); + + path = QPainterPath(); + path.addEllipse(0, 0, 100, 100); + + QTest::newRow("Case 12") << path << qreal(0.0) << QPointF(100, 50); + QTest::newRow("Case 13") << path << qreal(0.25) << QPointF(50, 100); + QTest::newRow("Case 14") << path << qreal(0.5) << QPointF(0, 50); + QTest::newRow("Case 15") << path << qreal(0.75) << QPointF(50, 0); + QTest::newRow("Case 16") << path << qreal(1.0) << QPointF(100, 50); + + path = QPainterPath(); + QRectF rect(241, 273, 185, 228); + path.addEllipse(rect); + QTest::newRow("Case 17") << path << qreal(1.0) << QPointF(rect.right(), qreal(0.5) * (rect.top() + rect.bottom())); + + path = QPainterPath(); + path.moveTo(100, 100); + QTest::newRow("Case 18") << path << qreal(0.0) << QPointF(100, 100); + QTest::newRow("Case 19") << path << qreal(1.0) << QPointF(100, 100); +} + +void tst_QPainterPath::pointAtPercent() +{ + QFETCH(QPainterPath, path); + QFETCH(qreal, percent); + QFETCH(QPointF, point); + + QPointF result = path.pointAtPercent(percent); + QVERIFY(pathFuzzyCompare(point.x() , result.x())); + QVERIFY(pathFuzzyCompare(point.y() , result.y())); +} + +void tst_QPainterPath::setElementPositionAt() +{ + QPainterPath path(QPointF(42., 42.)); + QCOMPARE(path.elementCount(), 1); + QVERIFY(path.elementAt(0).type == QPainterPath::MoveToElement); + QCOMPARE(path.elementAt(0).x, qreal(42.)); + QCOMPARE(path.elementAt(0).y, qreal(42.)); + + QPainterPath copy = path; + copy.setElementPositionAt(0, qreal(0), qreal(0)); + QCOMPARE(copy.elementCount(), 1); + QVERIFY(copy.elementAt(0).type == QPainterPath::MoveToElement); + QCOMPARE(copy.elementAt(0).x, qreal(0)); + QCOMPARE(copy.elementAt(0).y, qreal(0)); + + QCOMPARE(path.elementCount(), 1); + QVERIFY(path.elementAt(0).type == QPainterPath::MoveToElement); + QCOMPARE(path.elementAt(0).x, qreal(42.)); + QCOMPARE(path.elementAt(0).y, qreal(42.)); +} + +void tst_QPainterPath::angleAtPercent() +{ + for (int angle = 0; angle < 360; ++angle) { + QLineF line = QLineF::fromPolar(100, angle); + QPainterPath path; + path.moveTo(line.p1()); + path.lineTo(line.p2()); + + QCOMPARE(path.angleAtPercent(0.5), line.angle()); + } +} + +void tst_QPainterPath::arcWinding_data() +{ + QTest::addColumn<QPainterPath>("path"); + QTest::addColumn<QPointF>("point"); + QTest::addColumn<bool>("inside"); + + QPainterPath a; + a.addEllipse(0, 0, 100, 100); + a.addRect(50, 50, 100, 100); + + QTest::newRow("Case A (oddeven)") << a << QPointF(55, 55) << false; + a.setFillRule(Qt::WindingFill); + QTest::newRow("Case A (winding)") << a << QPointF(55, 55) << true; + + QPainterPath b; + b.arcMoveTo(0, 0, 100, 100, 10); + b.arcTo(0, 0, 100, 100, 10, 360); + b.addRect(50, 50, 100, 100); + + QTest::newRow("Case B (oddeven)") << b << QPointF(55, 55) << false; + b.setFillRule(Qt::WindingFill); + QTest::newRow("Case B (winding)") << b << QPointF(55, 55) << false; + + QPainterPath c; + c.arcMoveTo(0, 0, 100, 100, 0); + c.arcTo(0, 0, 100, 100, 0, 360); + c.addRect(50, 50, 100, 100); + + QTest::newRow("Case C (oddeven)") << c << QPointF(55, 55) << false; + c.setFillRule(Qt::WindingFill); + QTest::newRow("Case C (winding)") << c << QPointF(55, 55) << false; + + QPainterPath d; + d.arcMoveTo(0, 0, 100, 100, 10); + d.arcTo(0, 0, 100, 100, 10, -360); + d.addRect(50, 50, 100, 100); + + QTest::newRow("Case D (oddeven)") << d << QPointF(55, 55) << false; + d.setFillRule(Qt::WindingFill); + QTest::newRow("Case D (winding)") << d << QPointF(55, 55) << true; + + QPainterPath e; + e.arcMoveTo(0, 0, 100, 100, 0); + e.arcTo(0, 0, 100, 100, 0, -360); + e.addRect(50, 50, 100, 100); + + QTest::newRow("Case E (oddeven)") << e << QPointF(55, 55) << false; + e.setFillRule(Qt::WindingFill); + QTest::newRow("Case E (winding)") << e << QPointF(55, 55) << true; +} + +void tst_QPainterPath::arcWinding() +{ + QFETCH(QPainterPath, path); + QFETCH(QPointF, point); + QFETCH(bool, inside); + + QCOMPARE(path.contains(point), inside); +} + +void tst_QPainterPath::testToFillPolygons() +{ + QPainterPath path; + path.lineTo(QPointF(0, 50)); + path.lineTo(QPointF(50, 50)); + + path.moveTo(QPointF(70, 50)); + path.lineTo(QPointF(70, 100)); + path.lineTo(QPointF(40, 100)); + + const QList<QPolygonF> polygons = path.toFillPolygons(); + QCOMPARE(polygons.size(), 2); + QCOMPARE(polygons.first().count(QPointF(70, 50)), 0); +} + +void tst_QPainterPath::testNaNandInfinites() +{ + QPainterPath path1; + QPainterPath path2 = path1; + + QPointF p1 = QPointF(qSNaN(), 1); + QPointF p2 = QPointF(qQNaN(), 1); + QPointF p3 = QPointF(qQNaN(), 1); + QPointF pInf = QPointF(qInf(), 1); + + // all these operations with NaN/Inf should be ignored + // can't test operator>> reliably, as we can't create a path with NaN to << later + + path1.moveTo(p1); + path1.moveTo(qSNaN(), qQNaN()); + path1.moveTo(pInf); + + path1.lineTo(p1); + path1.lineTo(qSNaN(), qQNaN()); + path1.lineTo(pInf); + + path1.cubicTo(p1, p2, p3); + path1.cubicTo(p1, QPointF(1, 1), QPointF(2, 2)); + path1.cubicTo(pInf, QPointF(10, 10), QPointF(5, 1)); + + path1.quadTo(p1, p2); + path1.quadTo(QPointF(1, 1), p3); + path1.quadTo(QPointF(1, 1), pInf); + + path1.arcTo(QRectF(p1, p2), 5, 5); + path1.arcTo(QRectF(pInf, QPointF(1, 1)), 5, 5); + + path1.addRect(QRectF(p1, p2)); + path1.addRect(QRectF(pInf, QPointF(1, 1))); + + path1.addEllipse(QRectF(p1, p2)); + path1.addEllipse(QRectF(pInf, QPointF(1, 1))); + + QCOMPARE(path1, path2); + + path1.lineTo(QPointF(1, 1)); + QVERIFY(path1 != path2); +} + +void tst_QPainterPath::connectPathDuplicatePoint() +{ + QPainterPath a; + a.moveTo(10, 10); + a.lineTo(20, 20); + + QPainterPath b; + b.moveTo(20, 20); + b.lineTo(30, 10); + + a.connectPath(b); + + QPainterPath c; + c.moveTo(10, 10); + c.lineTo(20, 20); + c.lineTo(30, 10); + + QCOMPARE(c, a); +} + +void tst_QPainterPath::connectPathMoveTo() +{ + QPainterPath path1; + QPainterPath path2; + QPainterPath path3; + QPainterPath path4; + + path1.moveTo(1,1); + + path2.moveTo(4,4); + path2.lineTo(5,6); + path2.lineTo(6,7); + + path3.connectPath(path2); + + path4.lineTo(5,5); + + path1.connectPath(path2); + + QVERIFY(path1.elementAt(0).type == QPainterPath::MoveToElement); + QVERIFY(path2.elementAt(0).type == QPainterPath::MoveToElement); + QVERIFY(path3.elementAt(0).type == QPainterPath::MoveToElement); + QVERIFY(path4.elementAt(0).type == QPainterPath::MoveToElement); +} + +void tst_QPainterPath::translate() +{ + QPainterPath path; + + // Path with no elements. + QCOMPARE(path.currentPosition(), QPointF()); + path.translate(50.5, 50.5); + QCOMPARE(path.currentPosition(), QPointF()); + QCOMPARE(path.translated(50.5, 50.5).currentPosition(), QPointF()); + + // path.isEmpty(), but we have one MoveTo element that should be translated. + path.moveTo(50, 50); + QCOMPARE(path.currentPosition(), QPointF(50, 50)); + path.translate(99.9, 99.9); + QCOMPARE(path.currentPosition(), QPointF(149.9, 149.9)); + path.translate(-99.9, -99.9); + QCOMPARE(path.currentPosition(), QPointF(50, 50)); + QCOMPARE(path.translated(-50, -50).currentPosition(), QPointF(0, 0)); + + // Complex path. + QRegion shape(100, 100, 300, 200, QRegion::Ellipse); + shape -= QRect(225, 175, 50, 50); + QPainterPath complexPath; + complexPath.addRegion(shape); + QVector<QPointF> untranslatedElements; + for (int i = 0; i < complexPath.elementCount(); ++i) + untranslatedElements.append(QPointF(complexPath.elementAt(i))); + + const QPainterPath untranslatedComplexPath(complexPath); + const QPointF offset(100, 100); + complexPath.translate(offset); + + for (int i = 0; i < complexPath.elementCount(); ++i) + QCOMPARE(QPointF(complexPath.elementAt(i)) - offset, untranslatedElements.at(i)); + + QCOMPARE(complexPath.translated(-offset), untranslatedComplexPath); +} + + +void tst_QPainterPath::lineWithinBounds() +{ + const int iteration_count = 3; + volatile const qreal yVal = 0.5; + QPointF a(0.0, yVal); + QPointF b(1000.0, yVal); + QPointF c(2000.0, yVal); + QPointF d(3000.0, yVal); + QPainterPath path; + path.moveTo(QPointF(0, yVal)); + path.cubicTo(QPointF(1000.0, yVal), QPointF(2000.0, yVal), QPointF(3000.0, yVal)); + for(int i=0; i<=iteration_count; i++) { + qreal actual = path.pointAtPercent(qreal(i) / iteration_count).y(); + QVERIFY(actual == yVal); // don't use QCOMPARE, don't want fuzzy comparison + } +} + + +QTEST_APPLESS_MAIN(tst_QPainterPath) + +#include "tst_qpainterpath.moc" diff --git a/tests/auto/gui/painting/qpainterpathstroker/.gitignore b/tests/auto/gui/painting/qpainterpathstroker/.gitignore new file mode 100644 index 0000000000..e171c5da31 --- /dev/null +++ b/tests/auto/gui/painting/qpainterpathstroker/.gitignore @@ -0,0 +1 @@ +tst_qpainterpathstroker diff --git a/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro b/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro new file mode 100644 index 0000000000..b6f62a2eee --- /dev/null +++ b/tests/auto/gui/painting/qpainterpathstroker/qpainterpathstroker.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_qpainterpathstroker.cpp + + + diff --git a/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp b/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp new file mode 100644 index 0000000000..288263e5d7 --- /dev/null +++ b/tests/auto/gui/painting/qpainterpathstroker/tst_qpainterpathstroker.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qfile.h> +#include <QPainterPathStroker> + +#define _USE_MATH_DEFINES +#include <math.h> + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPainterPathStroker : public QObject +{ + Q_OBJECT + +public: + +private slots: + void strokeEmptyPath(); +}; + +void tst_QPainterPathStroker::strokeEmptyPath() +{ + QPainterPath path; + path.moveTo(10, 10); + path.lineTo(10, 10); + QPainterPathStroker stroker; + QCOMPARE(stroker.createStroke(path), path); +} + +QTEST_APPLESS_MAIN(tst_QPainterPathStroker) + +#include "tst_qpainterpathstroker.moc" diff --git a/tests/auto/gui/painting/qpathclipper/.gitignore b/tests/auto/gui/painting/qpathclipper/.gitignore new file mode 100644 index 0000000000..a689eef0f6 --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/.gitignore @@ -0,0 +1 @@ +tst_qpathclipper diff --git a/tests/auto/gui/painting/qpathclipper/pathcompare.h b/tests/auto/gui/painting/qpathclipper/pathcompare.h new file mode 100644 index 0000000000..d80c189665 --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/pathcompare.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PATHCOMPARE_H +#define PATHCOMPARE_H + +#include <qmath.h> + +namespace QPathCompare { + +static const int precision = 8; +static const qreal epsilon = qPow(0.1, precision); + +static inline bool fuzzyIsZero(qreal x, qreal relative) +{ + if (qAbs(relative) < epsilon) + return qAbs(x) < epsilon; + else + return qAbs(x / relative) < epsilon; +} + +static bool fuzzyCompare(const QPointF &a, const QPointF &b) +{ + const QPointF delta = a - b; + + const qreal x = qMax(qAbs(a.x()), qAbs(b.x())); + const qreal y = qMax(qAbs(a.y()), qAbs(b.y())); + + return fuzzyIsZero(delta.x(), x) && fuzzyIsZero(delta.y(), y); +} + +static bool isClosed(const QPainterPath &path) +{ + if (path.elementCount() == 0) + return false; + + QPointF first = path.elementAt(0); + QPointF last = path.elementAt(path.elementCount() - 1); + + return fuzzyCompare(first, last); +} + +// rotation and direction independent path comparison +// allows paths to be shifted or reversed relative to each other +static bool comparePaths(const QPainterPath &actual, const QPainterPath &expected) +{ + const int endActual = isClosed(actual) ? actual.elementCount() - 1 : actual.elementCount(); + const int endExpected = isClosed(expected) ? expected.elementCount() - 1 : expected.elementCount(); + + if (endActual != endExpected) + return false; + + for (int i = 0; i < endActual; ++i) { + int k = 0; + for (k = 0; k < endActual; ++k) { + int i1 = k; + int i2 = (i + k) % endActual; + + QPointF a = actual.elementAt(i1); + QPointF b = expected.elementAt(i2); + + if (!fuzzyCompare(a, b)) + break; + } + + if (k == endActual) + return true; + + for (k = 0; k < endActual; ++k) { + int i1 = k; + int i2 = (i + endActual - k) % endActual; + + QPointF a = actual.elementAt(i1); + QPointF b = expected.elementAt(i2); + + if (!fuzzyCompare(a, b)) + break; + } + + if (k == endActual) + return true; + } + + return false; +} + +} + +#endif diff --git a/tests/auto/gui/painting/qpathclipper/paths.cpp b/tests/auto/gui/painting/qpathclipper/paths.cpp new file mode 100644 index 0000000000..950c34614e --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/paths.cpp @@ -0,0 +1,734 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "paths.h" + +QPainterPath Paths::rect() +{ + QPainterPath path; + + path.moveTo(45.885571, 62.857143); + path.lineTo(154.11442, 62.857143); + path.cubicTo(162.1236, 62.857143, + 168.57142, 70.260744, + 168.57142, 79.457144); + path.lineTo(168.57142, 123.4); + path.cubicTo(168.57142, 132.5964, + 162.1236, 140, + 154.11442, 140); + path.lineTo(45.885571, 140); + path.cubicTo(37.876394, 140, + 31.428572, 132.5964, + 31.428572, 123.4); + path.lineTo(31.428572, 79.457144); + path.cubicTo(31.428572,70.260744, + 37.876394,62.857143, + 45.885571,62.857143); + path.closeSubpath(); + return path; +} + +QPainterPath Paths::rect6() +{ + QPainterPath path; + + path.moveTo(45.885571, 62.857143); + path.lineTo(154.11442, 62.857143); + path.cubicTo(162.1236, 62.857143, + 168.57142, 70.260744, + 168.57142, 79.457144); + path.lineTo(168.57142, 123.4); + path.cubicTo(168.57142, 132.5964, + 162.1236, 140, + 154.11442, 140); + path.lineTo(45.885571, 140); + path.closeSubpath(); + return path; +} + + +QPainterPath Paths::heart() +{ + QPainterPath path; + path.moveTo(263.41570, 235.14588); + path.cubicTo(197.17570,235.14588, + 143.41575,288.90587, + 143.41575,355.14588); + path.cubicTo(143.41575, 489.90139, + 279.34890, 525.23318, + 371.97820, 658.45392); + path.cubicTo(459.55244,526.05056, + 600.54070,485.59932, + 600.54070,355.14588); + path.cubicTo(600.54070,288.90588, 546.78080,235.14587, 480.54070,235.14588); + path.cubicTo(432.49280,235.14588, 391.13910,263.51631, 371.97820,304.33338); + path.cubicTo(352.81740,263.51630, 311.46370,235.14587, 263.41570,235.14588); + path.closeSubpath(); + return path; +} + + +QPainterPath Paths::body() +{ + QPainterPath path; + path.moveTo(62.500000,15.531250); + path.cubicTo(48.633197,15.531250, 37.374999,26.789445, 37.375000,40.656250); + path.cubicTo(37.375000,54.523053, 48.633195,65.781252, 62.500000,65.781250); + path.cubicTo(76.366803,65.781250, 87.624998,54.523052, 87.625000,40.656250); + path.cubicTo(87.625000,26.789447, 76.366802,15.531250, 62.500000,15.531250); + path.closeSubpath(); + path.moveTo(54.437500,65.812500); + path.cubicTo(35.184750,65.812499, 19.687500,81.341002, 19.687500,100.59375); + path.lineTo(19.687500,155.68750); + path.cubicTo(19.687501,167.50351, 25.539122,177.88308, 34.500000,184.15625); + path.lineTo(34.500000,254.03125); + path.cubicTo(34.499999,257.03306, 46.990615,259.43748, 62.500000,259.43750); + path.cubicTo(78.009381,259.43751, 90.468750,257.03307, 90.468750,254.03125); + path.lineTo(90.468750,184.15625); + path.cubicTo(99.429633,177.88307, 105.28125,167.50352, 105.28125,155.68750); + path.lineTo(105.28125,100.59375); + path.cubicTo(105.28125,81.341000, 89.784000,65.812500, 70.531250,65.812500); + path.lineTo(54.437500,65.812500); + path.closeSubpath(); + + return path; +} + + +QPainterPath Paths::mailbox() +{ + QPainterPath path; + path.moveTo(355.22951,136.82424); + path.lineTo(332.03629,112.56585); + path.lineTo(325.71086,57.501867); + path.cubicTo(325.71086,57.501867, 410.12308,19.428758, 427.45202,29.094560); + path.cubicTo(444.78096,38.760366, 443.62570,54.289660, 443.62570,54.289660); + path.lineTo(443.62570,100.11509); + path.lineTo(355.22951,136.82424); + path.closeSubpath(); + + return path; +} + + +QPainterPath Paths::deer() +{ + QPainterPath path; + + path.moveTo(39.88,31.658); + path.cubicTo(35.632,31.658, 31.398,31.004, 27.871,32.82); + path.cubicTo(25.015,34.29, 19.608,34.158, 16.297,34.158); + path.cubicTo(14.722,34.158, 17.755,37.718, 17.709,38.922); + path.cubicTo(17.578,42.396, 24.612,43.15, 26.755,44.058); + path.cubicTo(30.062,45.46, 28.682,47.701, 28.963,50.574); + path.cubicTo(29.715,58.243, 26.887,63.745, 24.182,70.589); + path.cubicTo(23.365,72.657, 21.772,75.56, 21.972,77.866); + path.cubicTo(22.333,82.029, 15.803,77.207, 13.894,76.535); + path.cubicTo(10.977,75.508, 5.507,74.071, 2.424,75.331); + path.cubicTo(-1.532,76.947, 0.076,80.491, 2.169,82.806); + path.cubicTo(6.17,87.234, 2.703,90.713, 3.895,95.363); + path.cubicTo(4.321,97.026, 11.682,104.683, 12.858,103.668); + path.cubicTo(16.706,100.347, 11.464,98.692, 10.105,96.164); + path.cubicTo(9.487,95.015, 8.616,83.742, 8.866,83.759); + path.cubicTo(10.018,83.837, 12.591,85.867, 13.671,86.392); + path.cubicTo(16.889,87.954, 20.066,89.63, 22.963,91.741); + path.cubicTo(29.156,94.47, 35.543,96.965, 42.102,98.676); + path.cubicTo(51.085,101.02, 59.407,102.003, 68.009,106.005); + path.cubicTo(72.92,108.289, 72.05,113.282, 75.744,117.004); + path.cubicTo(79.422,120.709, 84.733,123.053, 88.978,126.053); + path.cubicTo(92.402,128.473, 95.422,132.308, 97.334,135.998); + path.cubicTo(99.551,140.279, 99.071,146.004, 99.838,150.674); + path.cubicTo(100.369,153.91, 104.378,156.321, 106.302,158.859); + path.cubicTo(110.471,164.355, 109.86,155.112, 108.163,154.412); + path.cubicTo(104.97,153.094, 103.991,146.625, 103.812,143.439); + path.cubicTo(103.525,138.336, 105.568,134.331, 101.918,130.346); + path.cubicTo(95.104,122.907, 89.488,114.182, 94.711,103.742); + path.cubicTo(96.889,99.388, 91.191,95.497, 96.94,94.368); + path.cubicTo(99.551,93.856, 102.49,94.367, 104.326,92.034); + path.cubicTo(106.639,89.095, 105.063,85.343, 102.943,82.798); + path.cubicTo(102.686,82.417, 102.359,82.121, 101.962,81.909); + path.cubicTo(102.331,81.909, 101.923,86.98, 100.981,87.628); + path.cubicTo(98.868,89.082, 95.569,91.586, 92.88,91.672); + path.cubicTo(90.569,91.745, 86.738,89.184, 85.212,87.658); + path.cubicTo(84.092,86.538, 80.176,86.157, 78.598,85.83); + path.cubicTo(74.737,85.031, 71.741,84.326, 68.012,82.806); + path.cubicTo(63.318,80.893, 58.687,78.672, 54.555,75.71); + path.cubicTo(44.573,68.555, 42.755,56.146, 44.022,44.495); + path.cubicTo(44.295,41.987, 43.169,38.057, 44.617,35.915); + path.cubicTo(44.961,35.406, 46.52,35.553, 47.119,35.024); + path.cubicTo(47.882,34.35, 49.574,31.822, 49.878,30.792); + path.cubicTo(51.126,26.569, 44.36,32.002, 45.336,31.938); + path.cubicTo(43.861,32.036, 47.011,22.934, 47.191,22.574); + path.cubicTo(47.555,21.846, 52.489,13.123, 49.511,13.222); + path.cubicTo(47.643,13.284, 48.563,18.667, 46.354,18.227); + path.cubicTo(43.964,17.751, 40.522,11.396, 41.566,9.011); + path.cubicTo(43.4,4.819, 39.743,3.905, 39.214,7.564); + path.cubicTo(39.112,8.269, 40.893,13.438, 38.159,12.665); + path.cubicTo(35.335,11.866, 35.748,-0.125, 34.38,-8.0352391e-15); + path.cubicTo(31.991,0.219, 34.074,10.836, 33.361,12.176); + path.cubicTo(33.144,12.584, 29.68,8.66, 29.459,7.718); + path.cubicTo(28.48,3.558, 28.031,5.106, 26.87,7.752); + path.cubicTo(25.333,11.254, 37.159,17.423, 39.292,18.663); + path.cubicTo(40.993,19.651, 42.39,20.504, 42.973,22.48); + path.cubicTo(43.482,24.205, 44.098,26.568, 42.926,28.191); + path.cubicTo(42.092,29.346, 39.88,29.982, 39.88,31.658); + return path; +} + + +QPainterPath Paths::fire() +{ + QPainterPath path; + + path.moveTo(362.83759,116.70426); + path.cubicTo(342.56574,131.59686, 300.71403,161.23127, 311.38454,218.12635); + path.cubicTo(322.05506,275.02144, 358.53432,301.66527, 328.90674,328.73285); + path.cubicTo(299.27916,355.80044, 251.48877,339.59410, 255.46042,288.61972); + path.cubicTo(258.22374,253.15368, 278.34141,205.10942, 278.34141,205.10942); + path.cubicTo(278.34141,205.10942, 234.02455,233.13427, 219.68939,254.01270); + path.cubicTo(205.35424,274.89113, 189.71452,330.07842, 208.58356,373.33974); + path.cubicTo(227.45261,416.60109, 316.46286,456.33444, 351.12048,514.32780); + path.cubicTo(374.10258,552.78425, 355.05815,613.59741, 310.80422,636.59310); + path.cubicTo(256.63287,664.74219, 299.16588,580.49238, 285.22551,523.86186); + path.cubicTo(273.46790,476.09839, 265.70022,445.12001, 188.03132,432.51681); + path.cubicTo(233.72591,465.34901, 242.16068,495.04075, 241.45928,524.11772); + path.cubicTo(240.78648,552.00862, 214.39595,634.57293, 177.39967,596.79021); + path.cubicTo(140.72642,559.33737, 214.27071,512.68654, 170.92945,471.62081); + path.cubicTo(174.73284,501.40284, 145.30515,514.98828, 131.55318,544.54392); + path.cubicTo(118.22673,573.18509, 123.55251,610.30651, 139.07596,645.41379); + path.cubicTo(181.14122,740.38745, 266.95518,726.23964, 208.75321,797.88229); + path.cubicTo(164.01134,852.95649, 162.90150,907.45084, 205.60384,970.81121); + path.cubicTo(240.06795,1021.9479, 371.11663,1060.7652, 432.20697,960.93460); + path.cubicTo(501.87852,820.00694, 357.14883,780.33174, 386.29974,732.84721); + path.cubicTo(405.70205,701.24238, 472.56601,668.86516, 501.09199,644.21233); + path.cubicTo(564.18184,587.55421, 561.84437,497.32621, 522.74229,471.25817); + path.cubicTo(530.19030,501.05022, 514.99952,542.79339, 483.67099,551.29691); + path.cubicTo(423.41173,567.65308, 458.18351,411.79373, 564.02075,393.61925); + path.cubicTo(530.91135,366.44998, 501.31413,367.33484, 454.91711,379.11707); + path.cubicTo(397.61736,393.57908, 407.64322,315.40944, 494.34643,262.67861); + path.cubicTo(549.19500,229.32101, 499.11573,147.63302, 491.66772,136.46100); + path.cubicTo(485.38713,213.93294, 435.43515,233.35601, 409.98053,235.72292); + path.cubicTo(375.27049,238.95043, 377.84554,214.33812, 396.75003,178.92950); + path.cubicTo(416.21172,142.47722, 448.15395,89.429942, 376.51366,44.060977); + path.cubicTo(388.13560,71.270572, 395.93673,94.012962, 362.83759,116.70426); + path.closeSubpath(); + return path; +} + + +QPainterPath Paths::lips() +{ + QPainterPath path; + + path.moveTo(177.02257,176.65905); + path.cubicTo(154.11895,176.65905, 136.56711,174.32266, 110.41800,155.61729); + path.cubicTo(83.894106,136.64382, 70.456540,123.78263, 44.264608,101.00195); + path.cubicTo(36.985036,94.670475, 11.607987,76.421189, 0.62503194,72.562763); + path.cubicTo(22.778258,60.937514, 46.738237,46.430325, 55.325084,40.325054); + path.cubicTo(79.128700,23.400628, 99.203004,0.53294656, 116.15033,0.61582047); + path.cubicTo(129.59137,0.68308215, 144.54744,18.524567, 177.02257,18.524567); + path.cubicTo(210.04060,18.524567, 224.45379,0.68308215, 237.89483,0.61582047); + path.cubicTo(254.84216,0.53294656, 274.91646,23.400628, 298.72008,40.325054); + path.cubicTo(307.30692,46.430325, 331.26690,60.937514, 353.42013,72.562763); + path.cubicTo(342.43717,76.421189, 317.06013,94.670475, 309.78055,101.00195); + path.cubicTo(283.58862,123.78263, 270.15105,136.64382, 243.62716,155.61729); + path.cubicTo(217.47805,174.32266, 199.38332,176.65905, 177.02257,176.65905); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::bezier1() +{ + QPainterPath path; + path.moveTo(50, 50); + path.cubicTo(100, 100, + 520, 90, + 400,400); + return path; +} + +QPainterPath Paths::bezier2() +{ + QPainterPath path; + path.moveTo(200,200); + path.cubicTo(200,125, 500,100, 500,500); + + return path; +} + +QPainterPath Paths::random1() +{ + QPainterPath path; + + path.moveTo(65.714286,91.428571); + path.lineTo(217.14286, 102.85714); + path.cubicTo(219.04762, 106.66666, + 220.95238, 110.47619, + 222.85714,114.28571); + path.cubicTo(231.2679, 131.10723, + 214.72525, 138.24185, + 211.42857,151.42857); + path.cubicTo(207.25902, 168.10676, + 213.24674, 175.8441, + 217.14286,191.42857); + path.cubicTo(221.088, 207.20915, + 201.21538,205.71429, + 188.57143,205.71429); + path.cubicTo(170.18303, 205.71429, + 161.42918, 197.50045, + 145.71429,185.71429); + path.cubicTo(113.93441, 161.87938, + 132.73699, 182.37652, + 137.14286, 200); + path.cubicTo(140.37884, 212.94392, + 128.50252, 217.16009, + 117.14286, 220); + path.cubicTo(98.323209, 224.70491, + 91.206108, 205.41767, + 82.857143, 194.28571); + path.cubicTo(77.307286, 186.8859, + 84.541768, 158.97578, + 85.714286, 154.28571); + path.cubicTo(87.843677, 145.76815, + 67.066253, 132.78054, + 60 , 125.71429); + path.cubicTo(54.074503, 119.78879, + 64.646395, 95.700137, + 65.714286, 91.428571); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::random2() +{ + QPainterPath path; + + path.moveTo(314.28571,160); + path.cubicTo(434.28571,125.71429, + 505.71429,200, + 505.71429,200); + path.lineTo(454.28571, 305.71429); + path.lineTo(337.14286, 302.85714); + path.cubicTo(337.14286, 302.85714, + 308.57143, 340, + 337.14286, 302.85714); + path.cubicTo(365.71429, 265.71429, + 200, 420, + 300, 291.42857); + path.cubicTo(400, 162.85714, + 254.28571, 240, + 254.28571, 240); + path.cubicTo(254.28571,240, + 240,71.428571, + 288.57143,134.28571); + path.cubicTo(337.14286,197.14286, + 314.28571,162.85714, + 314.28571,160); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::bezier3() +{ + QPainterPath path; + path.moveTo(295, 217); + path.cubicTo(364, 57, + 377, 34, + 456, 222); + return path; +} + +QPainterPath Paths::bezier4() +{ + QPainterPath path; + path.moveTo(200, 125); + path.cubicTo(200, 125, + 623, 126, + 623, 126); + return path; +} + +QPainterPath Paths::heart2() +{ + QPainterPath path; + path.moveTo(263.41570, 235.14588); + path.cubicTo(197.17570,235.14588, + 143.41575,288.90587, + 143.41575,355.14588); + path.cubicTo(143.41575, 489.90139, + 279.34890, 525.23318, + 371.97820, 658.45392); + return path; +} + +QPainterPath Paths::rect2() +{ + QPainterPath path; + + path.addRect(80, 80, 100, 100); + + return path; +} + + +QPainterPath Paths::rect3() +{ + QPainterPath path; + + path.addRect(100, 40, 100, 100); + + return path; +} + + +QPainterPath Paths::rect4() +{ + QPainterPath path; + + path.addRect(100, 0, 200, 200); + + path.addRect(120, 20, 80, 80); + + return path; +} + +QPainterPath Paths::simpleCurve() +{ + QPainterPath path; + path.moveTo(74, 160); + path.cubicTo( 74, 160, + 274, 406, + 425, 166); + path.cubicTo(577, -73, + 77, 160, + 74, 160); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::simpleCurve2() +{ + QPainterPath path; + path.moveTo(54, 140); + path.cubicTo( 54, 140, + 254, 386, + 405, 146); + path.cubicTo(557, -93, + 57, 140, + 54, 140); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::frame1() +{ + QPainterPath path; + path.moveTo(190.71429, 40.933613); + path.lineTo(683.57141, 40.933613); + path.cubicTo(697.42141, 40.933613, + 708.57141, 52.083613, + 708.57141, 65.933613); + path.lineTo(708.57141, 375.93361); + path.cubicTo(708.57141, 389.78361, + 697.42141, 400.93361, + 683.57141, 400.93361); + path.lineTo(190.71429, 400.93361); + path.cubicTo(176.86429, 400.93361, + 165.71429, 389.78361, + 165.71429,375.93361); + path.lineTo(165.71429, 65.933613); + path.cubicTo(165.71429,52.083613, + 176.86429,40.933613, + 190.71429,40.933613); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::frame2() +{ + QPainterPath path; + path.moveTo(55.114286, 103.79076); + path.lineTo(187.74288, 103.79076); + path.cubicTo(192.95048, 103.79076, + 197.14288, 107.88102, + 197.14288, 112.96176); + path.lineTo(197.14288, 131.76261); + path.cubicTo(197.14288, 136.84335, + 192.95048, 140.93361, + 187.74288, 140.93361); + path.lineTo(55.114286, 140.93361); + path.cubicTo(49.906687, 140.93361, + 45.714287, 136.84335, + 45.714287, 131.76261); + path.lineTo(45.714287, 112.96176); + path.cubicTo(45.714287, 107.88102, + 49.906687, 103.79076, + 55.114286, 103.79076); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::frame3() +{ + QPainterPath path; + path.moveTo(200,80.933609); + path.lineTo(682.85715,80.933609); + path.lineTo(682.85715,446.6479); + path.lineTo(200,446.6479); + path.lineTo(200,80.933609); + path.closeSubpath(); + return path; +} + +QPainterPath Paths::frame4() +{ + QPainterPath path; + + path.moveTo(88.571434,206.64789); + path.lineTo(231.42858,206.64789); + path.lineTo(231.42858,246.64789); + path.lineTo(88.571434,246.64789); + path.lineTo(88.571434,206.64789); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::simpleCurve3() +{ + QPainterPath path; + + path.moveTo(0, 0); + path.cubicTo(400,0, + 0,400, + 0,0); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::rect5() +{ + QPainterPath path; + + path.addRect(0, 0, 200, 200); + + return path; +} + +QPainterPath Paths::triangle1() +{ + QPainterPath path; + + path.moveTo(0, 0); + path.lineTo(60, 0); + path.lineTo(60, 60); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::triangle2() +{ + QPainterPath path; + + path.moveTo(0, 120); + path.lineTo(60, 120); + path.lineTo(60, 60); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::node() +{ + QRectF m_rect; + m_rect.setWidth(150); + m_rect.setHeight(100); + + QPainterPath shape; + shape.addRoundRect(m_rect, 25); + + const int conWidth = 10; + const int xOffset = 7; + + QRectF rect(xOffset, + conWidth + 20, + conWidth, conWidth); + shape.addEllipse(rect); + //shape.addRect(rect); + + rect = QRectF(m_rect.right() - conWidth - xOffset, + conWidth + 20, + conWidth, conWidth); + shape.addEllipse(rect); + //shape.addRect(rect); + return shape; +} + +QPainterPath Paths::interRect() +{ + QPainterPath path; + path.addRect(132, 42, 1, 1); + return path; +} + +QPainterPath Paths::bezierFlower() +{ + QPainterPath path; + path.moveTo(0, 0); + path.cubicTo(0, 50, -25, 75, -50, 100); + path.closeSubpath(); + path.moveTo(0, 0); + path.cubicTo(0, 50, 25, 75, 50, 100); + path.closeSubpath(); + + path.moveTo(0, 0); + path.cubicTo(0, -50, -25, -75, -50, -100); + path.closeSubpath(); + path.moveTo(0, 0); + path.cubicTo(0, -50, 25, -75, 50, -100); + path.closeSubpath(); + + path.moveTo(0, 0); + path.cubicTo(-50, 0, -75, -25, -100, -50); + path.closeSubpath(); + path.moveTo(0, 0); + path.cubicTo(-50, 0, -75, 25, -100, 50); + path.closeSubpath(); + + path.moveTo(0, 0); + path.cubicTo(50, 0, 75, -25, 100, -50); + path.closeSubpath(); + path.moveTo(0, 0); + path.cubicTo(50, 0, 75, 25, 100, 50); + path.closeSubpath(); + + return path; +} + +QPainterPath Paths::clover() +{ + QPainterPath path; + path.moveTo(50, 50); + path.lineTo(100, 25); + path.lineTo(100, 75); + path.lineTo(0, 25); + path.lineTo(0, 75); + path.lineTo(50, 50); + path.lineTo(75, 0); + path.lineTo(25, 0); + path.lineTo(75, 100); + path.lineTo(25, 100); + path.lineTo(50, 50); + return path; +} + +QPainterPath Paths::ellipses() +{ + QPainterPath path; + path.addEllipse(0, 0, 100, 100); + path.addEllipse(0, 20, 100, 60); + path.addEllipse(0, 40, 100, 20); + return path; +} + +QPainterPath Paths::windingFill() +{ + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(50, 25, 100, 50); + path.setFillRule(Qt::WindingFill); + return path; +} + +QPainterPath Paths::oddEvenFill() +{ + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.moveTo(50, 25); + path.lineTo(50, 75); + path.lineTo(150, 75); + path.lineTo(150, 25); + path.lineTo(50, 25); + path.setFillRule(Qt::OddEvenFill); + return path; +} + +QPainterPath Paths::squareWithHole() +{ + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(30, 30, 40, 40); + return path; +} + +QPainterPath Paths::circleWithHole() +{ + QPainterPath path; + path.addEllipse(0, 0, 100, 100); + path.addEllipse(30, 30, 40, 40); + return path; +} + +QPainterPath Paths::bezierQuadrant() +{ + QPainterPath path; + int d = 1; + for (int i = 25; i <= 85; i += 10) { + path.moveTo(50, 100); + path.cubicTo(50, i, 50 + i* d / 2, 0, 50 + 50 * d, 0); + path.lineTo(50 + 50 * d, 100); + path.closeSubpath(); + } + + QMatrix m(2, 0, + 0, 2, + 0, 0); + + return path; +} diff --git a/tests/auto/gui/painting/qpathclipper/paths.h b/tests/auto/gui/painting/qpathclipper/paths.h new file mode 100644 index 0000000000..89ef785857 --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/paths.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef PATHS_H +#define PATHS_H + +#include <QPainterPath> + +namespace Paths +{ + QPainterPath rect(); + QPainterPath heart(); + QPainterPath body(); + QPainterPath mailbox(); + QPainterPath deer(); + QPainterPath fire(); + QPainterPath lips(); + + QPainterPath bezier1(); + QPainterPath bezier2(); + QPainterPath bezier3(); + QPainterPath bezier4(); + + QPainterPath random1(); + QPainterPath random2(); + + QPainterPath heart2(); + QPainterPath rect2(); + QPainterPath rect3(); + QPainterPath rect4(); + QPainterPath rect5(); + QPainterPath rect6(); + + QPainterPath simpleCurve(); + QPainterPath simpleCurve2(); + QPainterPath simpleCurve3(); + + QPainterPath frame1(); + QPainterPath frame2(); + QPainterPath frame3(); + QPainterPath frame4(); + + QPainterPath triangle1(); + QPainterPath triangle2(); + + QPainterPath node(); + QPainterPath interRect(); + + QPainterPath bezierFlower(); + QPainterPath clover(); + QPainterPath ellipses(); + QPainterPath windingFill(); + QPainterPath oddEvenFill(); + QPainterPath squareWithHole(); + QPainterPath circleWithHole(); + QPainterPath bezierQuadrant(); +} +#endif diff --git a/tests/auto/gui/painting/qpathclipper/qpathclipper.pro b/tests/auto/gui/painting/qpathclipper/qpathclipper.pro new file mode 100644 index 0000000000..2becd7dd03 --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/qpathclipper.pro @@ -0,0 +1,11 @@ +load(qttest_p4) +INCLUDEPATH += . +HEADERS += paths.h +SOURCES += tst_qpathclipper.cpp paths.cpp +QT += gui-private + +requires(contains(QT_CONFIG,private_tests)) + +unix:!mac:!symbian:LIBS+=-lm + + diff --git a/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp b/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp new file mode 100644 index 0000000000..57a56b2d1a --- /dev/null +++ b/tests/auto/gui/painting/qpathclipper/tst_qpathclipper.cpp @@ -0,0 +1,1334 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "private/qpathclipper_p.h" +#include "paths.h" +#include "pathcompare.h" + +#include <QtTest/QtTest> + +#include <qpainterpath.h> +#include <qpolygon.h> +#include <qdebug.h> +#include <qpainter.h> + +#include <math.h> + +class tst_QPathClipper : public QObject +{ + Q_OBJECT + +public: + tst_QPathClipper(); + virtual ~tst_QPathClipper(); + +private: + void clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op); + + QList<QPainterPath> paths; + +public slots: + void initTestCase(); + +private slots: + void testWingedEdge(); + + void testComparePaths(); + + void clip_data(); + void clip(); + + void clip2(); + void clip3(); + + void testIntersections(); + void testIntersections2(); + void testIntersections3(); + void testIntersections4(); + void testIntersections5(); + void testIntersections6(); + void testIntersections7(); + void testIntersections8(); + void testIntersections9(); + + void zeroDerivativeCurves(); + + void task204301_data(); + void task204301(); + + void task209056(); + void task251909(); + + void qtbug3778(); +}; + +Q_DECLARE_METATYPE(QPainterPath) +Q_DECLARE_METATYPE(QPathClipper::Operation) + +tst_QPathClipper::tst_QPathClipper() +{ +} + +tst_QPathClipper::~tst_QPathClipper() +{ +} + +void tst_QPathClipper::initTestCase() +{ + paths << Paths::rect(); + paths << Paths::heart(); + paths << Paths::body(); + paths << Paths::mailbox(); + paths << Paths::deer(); + paths << Paths::fire(); + + paths << Paths::random1(); + paths << Paths::random2(); + + paths << Paths::heart2(); + paths << Paths::rect2(); + paths << Paths::rect3(); + paths << Paths::rect4(); + paths << Paths::rect5(); + paths << Paths::rect6(); + + paths << Paths::frame1(); + paths << Paths::frame2(); + paths << Paths::frame3(); + paths << Paths::frame4(); + + paths << Paths::triangle1(); + paths << Paths::triangle2(); + + paths << Paths::node(); + paths << Paths::interRect(); + + paths << Paths::simpleCurve(); + paths << Paths::simpleCurve2(); + paths << Paths::simpleCurve3(); + + paths << Paths::bezier1(); + paths << Paths::bezier2(); + paths << Paths::bezier3(); + paths << Paths::bezier4(); + + paths << Paths::bezierFlower(); + paths << Paths::lips(); + paths << Paths::clover(); + paths << Paths::ellipses(); + paths << Paths::windingFill(); + paths << Paths::oddEvenFill(); + paths << Paths::squareWithHole(); + paths << Paths::circleWithHole(); + paths << Paths::bezierQuadrant(); + + // make sure all the bounding rects are centered at the origin + for (int i = 0; i < paths.size(); ++i) { + QRectF bounds = paths[i].boundingRect(); + + QMatrix m(1, 0, + 0, 1, + -bounds.center().x(), -bounds.center().y()); + + paths[i] = m.map(paths[i]); + } +} + +static QPainterPath samplePath1() +{ + QPainterPath path; + path.moveTo(QPointF(200, 246.64789)); + path.lineTo(QPointF(200, 206.64789)); + path.lineTo(QPointF(231.42858, 206.64789)); + path.lineTo(QPointF(231.42858, 246.64789)); + path.lineTo(QPointF(200, 246.64789)); + return path; +} + +static QPainterPath samplePath2() +{ + QPainterPath path; + path.moveTo(QPointF(200, 146.64789)); + path.lineTo(QPointF(200, 106.64789)); + path.lineTo(QPointF(231.42858, 106.64789)); + path.lineTo(QPointF(231.42858, 146.64789)); + path.lineTo(QPointF(200, 146.64789)); + return path; +} + +static QPainterPath samplePath3() +{ + QPainterPath path; + path.moveTo(QPointF(231.42858, 80.933609)); + path.lineTo(QPointF(200, 80.933609)); + path.lineTo(QPointF(200, 96.64788999999999)); + path.lineTo(QPointF(231.42858, 96.64788999999999)); + path.lineTo(QPointF(231.42858, 80.933609)); + return path; +} + +static QPainterPath samplePath4() +{ + QPainterPath path; + path.moveTo(QPointF(288.571434, 80.933609)); + path.lineTo(QPointF(431.42858, 80.933609)); + path.lineTo(QPointF(431.42858, 96.64788999999999)); + path.lineTo(QPointF(288.571434, 96.64788999999999)); + path.lineTo(QPointF(288.571434, 80.933609)); + return path; +} + +static QPainterPath samplePath5() +{ + QPainterPath path; + path.moveTo(QPointF(588.571434, 80.933609)); + path.lineTo(QPointF(682.85715, 80.933609)); + path.lineTo(QPointF(682.85715, 96.64788999999999)); + path.lineTo(QPointF(588.571434, 96.64788999999999)); + path.lineTo(QPointF(588.571434, 80.933609)); + return path; +} + +static QPainterPath samplePath6() +{ + QPainterPath path; + path.moveTo(QPointF(588.571434, 80.933609)); + path.lineTo(QPointF(200, 80.933609)); + path.lineTo(QPointF(200, 446.6479)); + path.lineTo(QPointF(682.85715, 446.6479)); + path.lineTo(QPointF(682.85715, 96.64788999999999)); + path.lineTo(QPointF(731.42858, 96.64788999999999)); + path.lineTo(QPointF(731.42858, 56.64788999999999)); + path.lineTo(QPointF(588.571434, 56.64788999999999)); + path.lineTo(QPointF(588.571434, 80.933609)); + return path; +} + +static QPainterPath samplePath7() +{ + QPainterPath path; + path.moveTo(QPointF(682.85715, 206.64789)); + path.lineTo(QPointF(682.85715, 246.64789)); + path.lineTo(QPointF(588.571434, 246.64789)); + path.lineTo(QPointF(588.571434, 206.64789)); + path.lineTo(QPointF(682.85715, 206.64789)); + return path; +} + +static QPainterPath samplePath8() +{ + QPainterPath path; + path.moveTo(QPointF(682.85715, 406.64789)); + path.lineTo(QPointF(682.85715, 446.64789)); + path.lineTo(QPointF(588.571434, 446.64789)); + path.lineTo(QPointF(588.571434, 406.64789)); + path.lineTo(QPointF(682.85715, 406.64789)); + return path; +} + +static QPainterPath samplePath9() +{ + QPainterPath path; + path.moveTo(QPointF(682.85715, 426.64789)); + path.lineTo(QPointF(682.85715, 446.6479)); + path.lineTo(QPointF(568.571434, 446.6479)); + path.lineTo(QPointF(568.571434, 426.64789)); + path.lineTo(QPointF(682.85715, 426.64789)); + return path; +} + +static QPainterPath samplePath10() +{ + QPainterPath path; + path.moveTo(QPointF(511.42858, 446.6479)); + path.lineTo(QPointF(368.571434, 446.6479)); + path.lineTo(QPointF(368.571434, 426.64789)); + path.lineTo(QPointF(511.42858, 426.64789)); + path.lineTo(QPointF(511.42858, 446.6479)); + return path; +} + +static QPainterPath samplePath13() +{ + QPainterPath path; + path.moveTo(QPointF(160, 200)); + path.lineTo(QPointF(100, 200)); + path.lineTo(QPointF(100, 130)); + path.lineTo(QPointF(160, 130)); + path.lineTo(QPointF(160, 200)); + return path; +} + +static QPainterPath samplePath14() +{ + QPainterPath path; + + path.moveTo(160, 80); + path.lineTo(160, 180); + path.lineTo(100, 180); + path.lineTo(100, 80); + path.lineTo(160, 80); + path.moveTo(160, 80); + path.lineTo(160, 100); + path.lineTo(120, 100); + path.lineTo(120, 80); + + return path; +} + +void tst_QPathClipper::clip_data() +{ + //create the testtable instance and define the elements + QTest::addColumn<QPainterPath>("subject"); + QTest::addColumn<QPainterPath>("clip"); + QTest::addColumn<QPathClipper::Operation>("op"); + QTest::addColumn<QPainterPath>("result"); + + //next we fill it with data + QTest::newRow( "simple1" ) << Paths::frame3() + << Paths::frame4() + << QPathClipper::BoolAnd + << samplePath1(); + + QTest::newRow( "simple2" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(0, -100) + << QPathClipper::BoolAnd + << samplePath2(); + + QTest::newRow( "simple3" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(0, -150) + << QPathClipper::BoolAnd + << samplePath3(); + + QTest::newRow( "simple4" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(200, -150) + << QPathClipper::BoolAnd + << samplePath4(); + + QTest::newRow( "simple5" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(500, -150) + << QPathClipper::BoolAnd + << samplePath5(); + + QTest::newRow( "simple6" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(500, -150) + << QPathClipper::BoolOr + << samplePath6(); + + QTest::newRow( "simple7" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(500, 0) + << QPathClipper::BoolAnd + << samplePath7(); + + QTest::newRow( "simple8" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(500, 200) + << QPathClipper::BoolAnd + << samplePath8(); + + QTest::newRow( "simple9" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(480, 220) + << QPathClipper::BoolAnd + << samplePath9(); + + QTest::newRow( "simple10" ) << Paths::frame3() + << Paths::frame4() * QTransform().translate(280, 220) + << QPathClipper::BoolAnd + << samplePath10(); + + QTest::newRow( "simple_move_to1" ) << Paths::rect4() + << Paths::rect2() * QTransform().translate(-20, 50) + << QPathClipper::BoolAnd + << samplePath13(); + + QTest::newRow( "simple_move_to2" ) << Paths::rect4() + << Paths::rect2() * QTransform().translate(-20, 0) + << QPathClipper::BoolAnd + << samplePath14(); +} + +// sanity check to make sure comparePaths declared above works +void tst_QPathClipper::testComparePaths() +{ + QPainterPath a; + QPainterPath b; + + a.addRect(0, 0, 10, 10); + b.addRect(0, 0, 10.00001, 10.00001); + + QVERIFY(!QPathCompare::comparePaths(a, b)); + + b = QPainterPath(); + b.addRect(0, 0, 10.00000000001, 10.00000000001); + + QVERIFY(QPathCompare::comparePaths(a, b)); + + b = QPainterPath(); + b.moveTo(10, 0); + b.lineTo(0, 0); + b.lineTo(0, 10); + b.lineTo(10, 10); + + QVERIFY(QPathCompare::comparePaths(a, b)); + b.lineTo(10, 0); + QVERIFY(QPathCompare::comparePaths(a, b)); + + b = QPainterPath(); + b.moveTo(10, 0); + b.lineTo(0, 10); + b.lineTo(0, 0); + b.lineTo(10, 10); + + QVERIFY(!QPathCompare::comparePaths(a, b)); +} + +void tst_QPathClipper::clip() +{ + if (sizeof(double) != sizeof(qreal)) { + QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll); + } + QFETCH( QPainterPath, subject ); + QFETCH( QPainterPath, clip ); + QFETCH( QPathClipper::Operation, op ); + QFETCH( QPainterPath, result); + QPathClipper clipper(subject, clip); + QPainterPath x = clipper.clip(op); + + QVERIFY(QPathCompare::comparePaths(x, result)); +} + +static inline QPointF randomPointInRect(const QRectF &rect) +{ + qreal rx = qrand() / (RAND_MAX + 1.); + qreal ry = qrand() / (RAND_MAX + 1.); + + return QPointF(rect.left() + rx * rect.width(), + rect.top() + ry * rect.height()); +} + +void tst_QPathClipper::clipTest(int subjectIndex, int clipIndex, QPathClipper::Operation op) +{ + const QPainterPath &subject = paths[subjectIndex]; + const QPainterPath &clip = paths[clipIndex]; + const int count = 40; + + QRectF bounds = subject.boundingRect().united(clip.boundingRect()); + + const qreal adjustX = bounds.width() * 0.01; + const qreal adjustY = bounds.height() * 0.01; + + // make sure we test some points that are outside both paths as well + bounds = bounds.adjusted(-adjustX, -adjustY, adjustX, adjustY); + + const int dim = 256; + const qreal scale = qMin(dim / bounds.width(), dim / bounds.height()); + + QPathClipper clipper(subject, clip); + QPainterPath result = clipper.clip(op); + + // using the image here is a bit of a hacky way to make sure we don't test points that + // are too close to the path edges to avoid test fails that are due to numerical errors + QImage img(dim, dim, QImage::Format_ARGB32_Premultiplied); + img.fill(0x0); + QPainter p(&img); + p.setRenderHint(QPainter::Antialiasing); + p.scale(scale, scale); + p.translate(-bounds.topLeft()); + p.setPen(Qt::black); + p.drawPath(subject); + p.setPen(Qt::red); + p.drawPath(clip); + p.end(); + + for (int i = 0; i < count; ++i) { + QPointF point; + QRgb pixel; + do { + point = randomPointInRect(bounds); + const QPointF imagePoint = (point - bounds.topLeft()) * scale; + + pixel = img.pixel(int(imagePoint.x()), int(imagePoint.y())); + } while (qAlpha(pixel) > 0); + + const bool inSubject = subject.contains(point); + const bool inClip = clip.contains(point); + + const bool inResult = result.contains(point); + + bool expected = false; + switch (op) { + case QPathClipper::BoolAnd: + expected = inSubject && inClip; + break; + case QPathClipper::BoolOr: + expected = inSubject || inClip; + break; + case QPathClipper::BoolSub: + expected = inSubject && !inClip; + break; + default: + break; + } + + if (expected != inResult) { + char str[256]; + const char *opStr = + op == QPathClipper::BoolAnd ? "and" : + op == QPathClipper::BoolOr ? "or" : "sub"; + sprintf(str, "Expected: %d, actual: %d, subject: %d, clip: %d, op: %s\n", + int(expected), int(inResult), subjectIndex, clipIndex, opStr); + + // debugging +#if 0 + QRect rect = bounds.toAlignedRect(); + + QPainter p(&img); + p.scale(scale, scale); + p.translate(-bounds.topLeft()); + + p.setPen(Qt::NoPen); + p.setBrush(QColor(0x700ff00)); + p.drawPath(result); + + p.setPen(Qt::blue); + p.drawPoint(point); + p.end(); + + char str2[256]; + sprintf(str2, "fail-%d-%d-%s.png", subjectIndex, clipIndex, opStr); + img.save(str2); +#endif + QFAIL(str); + } + } +} + +void tst_QPathClipper::clip2() +{ + if (sizeof(double) != sizeof(qreal)) + QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll); + + int operation = 0; + + for (int i = 0; i < paths.size(); ++i) { + for (int j = 0; j <= i; ++j) { + QPathClipper::Operation op = QPathClipper::Operation((operation++) % 3); + clipTest(i, j, op); + } + } +} + +void tst_QPathClipper::clip3() +{ + int operation = 0; + + // this subset should work correctly for qreal = float + for (int i = 0; i < 20; ++i) { + for (int j = 0; j <= i; ++j) { + QPathClipper::Operation op = QPathClipper::Operation((operation++) % 3); + clipTest(i, j, op); + } + } +} + +void tst_QPathClipper::testIntersections() +{ + QPainterPath path1; + QPainterPath path2; + + path1.addRect(0, 0, 100, 100); + path2.addRect(20, 20, 20, 20); + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addEllipse(0, 0, 100, 100); + path2.addEllipse(200, 200, 100, 100); + QVERIFY(!path1.intersects(path2)); + QVERIFY(!path2.intersects(path1)); + QVERIFY(!path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addEllipse(0, 0, 100, 100); + path2.addEllipse(50, 50, 100, 100); + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(!path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(100, 100, 100, 100); + path2.addRect(50, 100, 100, 20); + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(!path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(100, 100, 100, 100); + path2.addRect(110, 201, 100, 20); + QVERIFY(!path1.intersects(path2)); + QVERIFY(!path2.intersects(path1)); + QVERIFY(!path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(0, 0, 100, 100); + path2.addRect(20, 20, 20, 20); + path2.addRect(25, 25, 5, 5); + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(path1.contains(path2)); + QVERIFY(!path2.contains(path1)); +} + +void tst_QPathClipper::testIntersections2() +{ + QPainterPath path1; + QPainterPath path2; + + path1 = QPainterPath(); + path2 = QPainterPath(); + + path1.moveTo(-8,-8); + path1.lineTo(107,-8); + path1.lineTo(107,107); + path1.lineTo(-8,107); + + path2.moveTo(0,0); + path2.lineTo(100,0); + path2.lineTo(100,100); + path2.lineTo(0,100); + path2.lineTo(0,0); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(path1.contains(path2)); + QVERIFY(!path2.contains(path1)); + + path1.closeSubpath(); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + QVERIFY(path1.contains(path2)); + QVERIFY(!path2.contains(path1)); +} + +void tst_QPathClipper::testIntersections3() +{ + QPainterPath path1 = Paths::node(); + QPainterPath path2 = Paths::interRect(); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + +void tst_QPathClipper::testIntersections4() +{ + QPainterPath path1; + QPainterPath path2; + + path1.moveTo(-5, 0); + path1.lineTo(5, 0); + + path2.moveTo(0, -5); + path2.lineTo(0, 5); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + +void tst_QPathClipper::testIntersections5() +{ + QPainterPath path1; + QPainterPath path2; + + path1.addRect(0, 0, 4, 4); + path1.addRect(2, 1, 1, 1); + path2.addRect(0.5, 2, 1, 1); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + +void tst_QPathClipper::testIntersections6() +{ + QPainterPath path1; + QPainterPath path2; + + path1.moveTo(QPointF(-115.567, -98.3254)); + path1.lineTo(QPointF(-45.9007, -98.3254)); + path1.lineTo(QPointF(-45.9007, -28.6588)); + path1.lineTo(QPointF(-115.567, -28.6588)); + + path2.moveTo(QPointF(-110, -110)); + path2.lineTo(QPointF(110, -110)); + path2.lineTo(QPointF(110, 110)); + path2.lineTo(QPointF(-110, 110)); + path2.lineTo(QPointF(-110, -110)); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + + +void tst_QPathClipper::testIntersections7() +{ + QPainterPath path1; + QPainterPath path2; + + path1.addRect(0, 0, 10, 10); + path2.addRect(5, 0, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(0, 0, 10, 10); + path2.addRect(0, 5, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(0, 0, 10, 10); + path2.addRect(0, 0, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + /// + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(5, 1, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(1, 5, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(1, 1, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(5, 5, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(9, 9, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(10, 10, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 9, 9); + path2.addRect(11, 11, 10, 10); + + QVERIFY(!path1.intersects(path2)); + QVERIFY(!path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(1, 1, 10, 10); + path2.addRect(12, 12, 10, 10); + + QVERIFY(!path1.intersects(path2)); + QVERIFY(!path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(11, 11, 10, 10); + path2.addRect(12, 12, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath(); + path2 = QPainterPath(); + path1.addRect(11, 11, 10, 10); + path2.addRect(10, 10, 10, 10); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + + +void tst_QPathClipper::testIntersections8() +{ + QPainterPath path1 = Paths::node() * QTransform().translate(100, 50); + QPainterPath path2 = Paths::node() * QTransform().translate(150, 50);; + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = Paths::node(); + path2 = Paths::node(); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = Paths::node(); + path2 = Paths::node() * QTransform().translate(0, 30); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = Paths::node(); + path2 = Paths::node() * QTransform().translate(30, 0); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = Paths::node(); + path2 = Paths::node() * QTransform().translate(30, 30); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = Paths::node(); + path2 = Paths::node() * QTransform().translate(1, 1); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + + +void tst_QPathClipper::testIntersections9() +{ + QPainterPath path1; + QPainterPath path2; + + path1.addRect(QRectF(-1,143, 146, 106)); + path2.addRect(QRectF(-9,145, 150, 100)); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath();; + path2 = QPainterPath(); + + path1.addRect(QRectF(-1,191, 136, 106)); + path2.addRect(QRectF(-19,194, 150, 100)); + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); + + path1 = QPainterPath();; + path2 = QPainterPath(); + + path1.moveTo(-1 , 143); + path1.lineTo(148 , 143); + path1.lineTo(148 , 250); + path1.lineTo(-1 , 250); + + path2.moveTo(-5 , 146); + path2.lineTo(145 , 146); + path2.lineTo(145 , 246); + path2.lineTo(-5 , 246); + path2.lineTo(-5 , 146); + + QVERIFY(path1.intersects(path2)); + QVERIFY(path2.intersects(path1)); +} + +QPainterPath pathFromRect(qreal x, qreal y, qreal w, qreal h) +{ + QPainterPath path; + path.addRect(QRectF(x, y, w, h)); + return path; +} + +QPainterPath pathFromLine(qreal x1, qreal y1, qreal x2, qreal y2) +{ + QPainterPath path; + path.moveTo(x1, y1); + path.lineTo(x2, y2); + return path; +} + +static int loopLength(const QWingedEdge &list, QWingedEdge::TraversalStatus status) +{ + int start = status.edge; + + int length = 0; + do { + ++length; + status = list.next(status); + } while (status.edge != start); + + return length; +} + +void tst_QPathClipper::testWingedEdge() +{ + { + QWingedEdge list; + int e1 = list.addEdge(QPointF(0, 0), QPointF(10, 0)); + int e2 = list.addEdge(QPointF(0, 0), QPointF(0, 10)); + int e3 = list.addEdge(QPointF(0, 0), QPointF(-10, 0)); + int e4 = list.addEdge(QPointF(0, 0), QPointF(0, -10)); + + QCOMPARE(list.edgeCount(), 4); + QCOMPARE(list.vertexCount(), 5); + + QWingedEdge::TraversalStatus status = { e1, QPathEdge::RightTraversal, QPathEdge::Forward }; + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e1); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e4); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e4); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e3); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e3); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e2); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e2); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e1); + } + { + QWingedEdge list; + int e1 = list.addEdge(QPointF(5, 0), QPointF(5, 10)); + int e2 = list.addEdge(QPointF(5, 0), QPointF(10, 5)); + int e3 = list.addEdge(QPointF(10, 5), QPointF(5, 10)); + int e4 = list.addEdge(QPointF(5, 0), QPointF(0, 5)); + int e5 = list.addEdge(QPointF(0, 5), QPointF(5, 10)); + + QCOMPARE(list.edgeCount(), 5); + QCOMPARE(list.vertexCount(), 4); + + QWingedEdge::TraversalStatus status = { e1, QPathEdge::RightTraversal, QPathEdge::Forward }; + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e5); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e4); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e1); + + QCOMPARE(loopLength(list, status), 3); + + status.flip(); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(loopLength(list, status), 3); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e2); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e3); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e1); + + status = list.next(status); + status.flip(); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e2); + QCOMPARE(loopLength(list, status), 4); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e4); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Forward); + QCOMPARE(status.traversal, QPathEdge::RightTraversal); + QCOMPARE(status.edge, e5); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e3); + + status = list.next(status); + QCOMPARE(status.direction, QPathEdge::Backward); + QCOMPARE(status.traversal, QPathEdge::LeftTraversal); + QCOMPARE(status.edge, e2); + } + { + QPainterPath path = pathFromRect(0, 0, 20, 20); + QWingedEdge list(path, QPainterPath()); + + QCOMPARE(list.edgeCount(), 4); + QCOMPARE(list.vertexCount(), 4); + + QWingedEdge::TraversalStatus status = { 0, QPathEdge::RightTraversal, QPathEdge::Forward }; + + QPathEdge *edge = list.edge(status.edge); + QCOMPARE(QPointF(*list.vertex(edge->first)), QPointF(0, 0)); + QCOMPARE(QPointF(*list.vertex(edge->second)), QPointF(20, 0)); + + status = list.next(status); + QCOMPARE(status.edge, 1); + + status = list.next(status); + QCOMPARE(status.edge, 2); + + status = list.next(status); + QCOMPARE(status.edge, 3); + + status = list.next(status); + QCOMPARE(status.edge, 0); + + status.flipDirection(); + status = list.next(status); + QCOMPARE(status.edge, 3); + + status = list.next(status); + QCOMPARE(status.edge, 2); + + status = list.next(status); + QCOMPARE(status.edge, 1); + + status = list.next(status); + QCOMPARE(status.edge, 0); + + QWingedEdge list2(path, pathFromRect(10, 5, 20, 10)); + + QCOMPARE(list2.edgeCount(), 12); + QCOMPARE(list2.vertexCount(), 10); + + status.flipDirection(); + QCOMPARE(loopLength(list2, status), 8); + + status = list2.next(status); + edge = list2.edge(status.edge); + QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(20, 0)); + QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 5)); + + status = list2.next(status); + status.flipTraversal(); + + edge = list2.edge(status.edge); + QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(10, 5)); + QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 5)); + + QCOMPARE(loopLength(list2, status), 4); + + status.flipDirection(); + status = list2.next(status); + status.flipTraversal(); + + edge = list2.edge(status.edge); + QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(20, 5)); + QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(20, 15)); + + QCOMPARE(loopLength(list2, status), 4); + status = list2.next(status); + status = list2.next(status); + + edge = list2.edge(status.edge); + QCOMPARE(QPointF(*list2.vertex(edge->first)), QPointF(30, 5)); + QCOMPARE(QPointF(*list2.vertex(edge->second)), QPointF(30, 15)); + } +} + +void tst_QPathClipper::zeroDerivativeCurves() +{ + // zero derivative at end + { + QPainterPath a; + a.cubicTo(100, 0, 100, 100, 100, 100); + a.lineTo(100, 200); + a.lineTo(0, 200); + + QPainterPath b; + b.moveTo(50, 100); + b.lineTo(150, 100); + b.lineTo(150, 150); + b.lineTo(50, 150); + + QPainterPath c = a.united(b); + QVERIFY(c.contains(QPointF(25, 125))); + QVERIFY(c.contains(QPointF(75, 125))); + QVERIFY(c.contains(QPointF(125, 125))); + } + + // zero derivative at start + { + QPainterPath a; + a.cubicTo(100, 0, 100, 100, 100, 100); + a.lineTo(100, 200); + a.lineTo(0, 200); + + QPainterPath b; + b.moveTo(50, 100); + b.lineTo(150, 100); + b.lineTo(150, 150); + b.lineTo(50, 150); + + QPainterPath c = a.united(b); + QVERIFY(c.contains(QPointF(25, 125))); + QVERIFY(c.contains(QPointF(75, 125))); + QVERIFY(c.contains(QPointF(125, 125))); + } +} + +static bool strictContains(const QPainterPath &a, const QPainterPath &b) +{ + return b.subtracted(a) == QPainterPath(); +} + +Q_DECLARE_METATYPE(QPolygonF) + +void tst_QPathClipper::task204301_data() +{ + QTest::addColumn<QPolygonF>("points"); + + { + QPointF a(51.09013255685567855835, 31.30814891308546066284); + QPointF b(98.39898971840739250183, 11.02079074829816818237); + QPointF c(91.23911846894770860672, 45.86981737054884433746); + QPointF d(66.58616356085985898972, 63.10526528395712375641); + QPointF e(82.08219456479714892794, 94.90238165489137145414); + QPointF f(16.09013040543221251255, 105.66263409332729850121); + QPointF g(10.62811442650854587555, 65.09154842235147953033); + QPointF h(5.16609844751656055450, 24.52046275138854980469); + QPolygonF v; + v << a << b << c << d << e << f << g << h; + QTest::newRow("failed_on_linux") << v; + } + + { + QPointF a(50.014648437500000, 24.392089843750000); + QPointF b(92.836303710937500, 5.548706054687500); + QPointF c(92.145690917968750, 54.390258789062500); + QPointF d(65.402221679687500, 74.345092773437500); + QPointF e(80.789794921787347, 124.298095703129690); + QPointF f(34.961242675812954, 87.621459960852135); + QPointF g(18.305969238281250, 57.426757812500000); + QPointF h(1.650695800781250, 27.232055664062500); + QPolygonF v; + v << a << b << c << d << e << f << g << h; + QTest::newRow("failed_on_windows") << v; + } +} + +void tst_QPathClipper::task204301() +{ + QFETCH(QPolygonF, points); + + QPointF a = points[0]; + QPointF b = points[1]; + QPointF c = points[2]; + QPointF d = points[3]; + QPointF e = points[4]; + QPointF f = points[5]; + QPointF g = points[6]; + QPointF h = points[7]; + + QPainterPath subA; + subA.addPolygon(QPolygonF() << a << b << c << d); + subA.closeSubpath(); + + QPainterPath subB; + subB.addPolygon(QPolygonF() << f << e << d << g); + subB.closeSubpath(); + + QPainterPath subC; + subC.addPolygon(QPolygonF() << h << a << d << g); + subC.closeSubpath(); + + QPainterPath path; + path.addPath(subA); + path.addPath(subB); + path.addPath(subC); + + QPainterPath simplified = path.simplified(); + + QVERIFY(strictContains(simplified, subA)); + QVERIFY(strictContains(simplified, subB)); + QVERIFY(strictContains(simplified, subC)); +} + +void tst_QPathClipper::task209056() +{ + QPainterPath p1; + p1.moveTo( QPointF(188.506, 287.793) ); + p1.lineTo( QPointF(288.506, 287.793) ); + p1.lineTo( QPointF(288.506, 387.793) ); + p1.lineTo( QPointF(188.506, 387.793) ); + p1.lineTo( QPointF(188.506, 287.793) ); + + QPainterPath p2; + p2.moveTo( QPointF(419.447, 164.383) ); + p2.cubicTo( QPointF(419.447, 69.5486), QPointF(419.447, 259.218),QPointF(419.447, 164.383) ); + + p2.cubicTo( QPointF(48.9378, 259.218), QPointF(131.879, 336.097),QPointF(234.192, 336.097) ); + p2.cubicTo( QPointF(336.506, 336.097), QPointF(419.447, 259.218),QPointF(419.447, 164.383) ); + + QPainterPath p3 = p1.intersected(p2); + + QVERIFY(p3 != QPainterPath()); +} + +void tst_QPathClipper::task251909() +{ + QPainterPath p1; + p1.moveTo(0, -10); + p1.lineTo(10, -10); + p1.lineTo(10, 0); + p1.lineTo(0, 0); + + QPainterPath p2; + p2.moveTo(0, 8e-14); + p2.lineTo(10, -8e-14); + p2.lineTo(10, 10); + p2.lineTo(0, 10); + + QPainterPath result = p1.united(p2); + + QVERIFY(result.elementCount() <= 5); +} + +void tst_QPathClipper::qtbug3778() +{ + if (sizeof(double) != sizeof(qreal)) { + QSKIP("This test only works for qreal=double, otherwise ends in rounding errors", SkipAll); + } + QPainterPath path1; + path1.moveTo(200, 3.22409e-5); + // e-5 and higher leads to a bug + // Using 3.22409e-4 starts to work correctly + path1.lineTo(0, 0); + path1.lineTo(1.07025e-13, 1450); + path1.lineTo(750, 950); + path1.lineTo(950, 750); + path1.lineTo(200, 3.22409e-13); + + QPainterPath path2; + path2.moveTo(0, 0); + path2.lineTo(200, 800); + path2.lineTo(600, 1500); + path2.lineTo(1500, 1400); + path2.lineTo(1900, 1200); + path2.lineTo(2000, 1000); + path2.lineTo(1400, 0); + path2.lineTo(0, 0); + + QPainterPath p12 = path1.intersected(path2); + + QVERIFY(p12.contains(QPointF(100, 100))); +} + +QTEST_APPLESS_MAIN(tst_QPathClipper) + + +#include "tst_qpathclipper.moc" diff --git a/tests/auto/gui/painting/qpen/.gitignore b/tests/auto/gui/painting/qpen/.gitignore new file mode 100644 index 0000000000..a9187367dc --- /dev/null +++ b/tests/auto/gui/painting/qpen/.gitignore @@ -0,0 +1 @@ +tst_qpen diff --git a/tests/auto/gui/painting/qpen/qpen.pro b/tests/auto/gui/painting/qpen/qpen.pro new file mode 100644 index 0000000000..53bd5e2b6e --- /dev/null +++ b/tests/auto/gui/painting/qpen/qpen.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_qpen.cpp + + + diff --git a/tests/auto/gui/painting/qpen/tst_qpen.cpp b/tests/auto/gui/painting/qpen/tst_qpen.cpp new file mode 100644 index 0000000000..64d725bc50 --- /dev/null +++ b/tests/auto/gui/painting/qpen/tst_qpen.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include "qpen.h" +#include "qbrush.h" + +#include <qdebug.h> + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPen : public QObject +{ + Q_OBJECT + +public: + tst_QPen(); + +private slots: + void getSetCheck(); + void swap(); + void operator_eq_eq(); + void operator_eq_eq_data(); + + void stream(); + void stream_data(); + + void constructor(); + void constructor_data(); +}; + +// Testing get/set functions +void tst_QPen::getSetCheck() +{ + QPen obj1; + // qreal QPen::miterLimit() + // void QPen::setMiterLimit(qreal) + obj1.setMiterLimit(0.0); + QCOMPARE(0.0, obj1.miterLimit()); + obj1.setMiterLimit(qreal(1.1)); + QCOMPARE(qreal(1.1), obj1.miterLimit()); + + // qreal QPen::widthF() + // void QPen::setWidthF(qreal) + obj1.setWidthF(0.0); + QCOMPARE(0.0, obj1.widthF()); + obj1.setWidthF(qreal(1.1)); + QCOMPARE(qreal(1.1), obj1.widthF()); + + // int QPen::width() + // void QPen::setWidth(int) + for (int i = 0; i < 100; ++i) { + obj1.setWidth(i); + QCOMPARE(i, obj1.width()); + } +} + +void tst_QPen::swap() +{ + QPen p1(Qt::black), p2(Qt::white); + p1.swap(p2); + QCOMPARE(p1.color(), QColor(Qt::white)); + QCOMPARE(p2.color(), QColor(Qt::black)); +} + +Q_DECLARE_METATYPE(QPen) +Q_DECLARE_METATYPE(QBrush) + +tst_QPen::tst_QPen() + +{ +} + +void tst_QPen::operator_eq_eq_data() +{ + QTest::addColumn<QPen>("pen1"); + QTest::addColumn<QPen>("pen2"); + QTest::addColumn<bool>("isEqual"); + + QTest::newRow("differentColor") << QPen(Qt::red) + << QPen(Qt::blue) + << bool(FALSE); + QTest::newRow("differentWidth") << QPen(Qt::red, 2) + << QPen(Qt::red, 3) + << bool(FALSE); + QTest::newRow("differentPenStyle") << QPen(Qt::red, 2, Qt::DashLine) + << QPen(Qt::red, 2, Qt::DotLine) + << bool(FALSE); + QTest::newRow("differentCapStyle") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin) + << QPen(Qt::red, 2, Qt::DashLine, Qt::SquareCap, Qt::BevelJoin) + << bool(FALSE); + QTest::newRow("differentJoinStyle") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin) + << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::MiterJoin) + << bool(FALSE); + QTest::newRow("same") << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin) + << QPen(Qt::red, 2, Qt::DashLine, Qt::RoundCap, Qt::BevelJoin) + << bool(TRUE); + +} + +void tst_QPen::operator_eq_eq() +{ + QFETCH(QPen, pen1); + QFETCH(QPen, pen2); + QFETCH(bool, isEqual); + QCOMPARE(pen1 == pen2, isEqual); +} + + +void tst_QPen::constructor_data() +{ + QTest::addColumn<QPen>("pen"); + QTest::addColumn<QBrush>("brush"); + QTest::addColumn<double>("width"); + QTest::addColumn<int>("style"); + QTest::addColumn<int>("capStyle"); + QTest::addColumn<int>("joinStyle"); + + QTest::newRow("solid_black") << QPen() << QBrush(Qt::black) << 0. << (int)Qt::SolidLine + << (int) Qt::SquareCap << (int)Qt::BevelJoin; + QTest::newRow("solid_red") << QPen(Qt::red) << QBrush(Qt::red) << 0. << (int)Qt::SolidLine + << (int)Qt::SquareCap << (int)Qt::BevelJoin; + QTest::newRow("full") << QPen(QBrush(QLinearGradient(0, 0, 100, 100)), 10, + Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin) + << QBrush(QLinearGradient(0, 0, 100, 100)) << 10. << (int)Qt::SolidLine + << (int)Qt::RoundCap << (int)Qt::MiterJoin; + +} + + +void tst_QPen::constructor() +{ + QFETCH(QPen, pen); + QFETCH(QBrush, brush); + QFETCH(double, width); + QFETCH(int, style); + QFETCH(int, capStyle); + QFETCH(int, joinStyle); + + QCOMPARE(pen.style(), Qt::PenStyle(style)); + QCOMPARE(pen.capStyle(), Qt::PenCapStyle(capStyle)); + QCOMPARE(pen.joinStyle(), Qt::PenJoinStyle(joinStyle)); + QCOMPARE(pen.widthF(), width); + QCOMPARE(pen.brush(), brush); +} + + +void tst_QPen::stream_data() +{ + QTest::addColumn<QPen>("pen"); + + QTest::newRow("solid_black") << QPen(); + QTest::newRow("solid_red") << QPen(Qt::red); + QTest::newRow("full") << QPen(QBrush(QLinearGradient(0, 0, 100, 100)), 10, Qt::SolidLine, Qt::RoundCap, Qt::MiterJoin); +} + + +void tst_QPen::stream() +{ + QFETCH(QPen, pen); + + QByteArray bytes; + + { + QDataStream stream(&bytes, QIODevice::WriteOnly); + stream << pen; + } + + QPen cmp; + { + QDataStream stream(&bytes, QIODevice::ReadOnly); + stream >> cmp; + } + + QCOMPARE(pen.widthF(), cmp.widthF()); + QCOMPARE(pen.style(), cmp.style()); + QCOMPARE(pen.capStyle(), cmp.capStyle()); + QCOMPARE(pen.joinStyle(), cmp.joinStyle()); + QCOMPARE(pen.brush(), cmp.brush()); + + QCOMPARE(pen, cmp); +} + +QTEST_APPLESS_MAIN(tst_QPen) +#include "tst_qpen.moc" diff --git a/tests/auto/gui/painting/qpolygon/.gitignore b/tests/auto/gui/painting/qpolygon/.gitignore new file mode 100644 index 0000000000..7c9d48c848 --- /dev/null +++ b/tests/auto/gui/painting/qpolygon/.gitignore @@ -0,0 +1 @@ +tst_qpointarray diff --git a/tests/auto/gui/painting/qpolygon/qpolygon.pro b/tests/auto/gui/painting/qpolygon/qpolygon.pro new file mode 100644 index 0000000000..186b704d17 --- /dev/null +++ b/tests/auto/gui/painting/qpolygon/qpolygon.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +QT += widgets +SOURCES += tst_qpolygon.cpp + +unix:!mac:!symbian:LIBS+=-lm + + diff --git a/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp new file mode 100644 index 0000000000..f47073a048 --- /dev/null +++ b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <qpolygon.h> +#include <qpainterpath.h> +#include <math.h> + +#include <qpainter.h> +#include <qdialog.h> + + + +//TESTED_CLASS= +//TESTED_FILES=gui/painting/qpolygon.h gui/painting/qpolygon.cpp + +class tst_QPolygon : public QObject +{ + Q_OBJECT + +public: + tst_QPolygon(); + +private slots: + void makeEllipse(); + void swap(); +}; + +tst_QPolygon::tst_QPolygon() +{ +} + +void tst_QPolygon::makeEllipse() +{ + // create an ellipse with R1 = R2 = R, i.e. a circle + QPolygon pa; + const int R = 50; // radius + QPainterPath path; + path.addEllipse(0, 0, 2*R, 2*R); + pa = path.toSubpathPolygons().at(0).toPolygon(); + + int i; + // make sure that all points are R+-1 away from the center + bool err = FALSE; + for (i = 1; i < pa.size(); i++) { + QPoint p = pa.at( i ); + double r = sqrt( pow( double(p.x() - R), 2.0 ) + pow( double(p.y() - R), 2.0 ) ); + // ### too strict ? at least from visual inspection it looks + // quite odd around the main axes. 2.0 passes easily. + err |= ( qAbs( r - double(R) ) > 2.0 ); + } + QVERIFY( !err ); +} + +void tst_QPolygon::swap() +{ + QPolygon p1(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10)); + QPolygon p2(QVector<QPoint>() << QPoint(0,0) << QPoint( 0,10) << QPoint( 10,10) << QPoint(10,0)); + p1.swap(p2); + QCOMPARE(p1.count(),4); + QCOMPARE(p2.count(),3); +} + +QTEST_APPLESS_MAIN(tst_QPolygon) +#include "tst_qpolygon.moc" diff --git a/tests/auto/gui/painting/qprinter/.gitignore b/tests/auto/gui/painting/qprinter/.gitignore new file mode 100644 index 0000000000..85de0e9675 --- /dev/null +++ b/tests/auto/gui/painting/qprinter/.gitignore @@ -0,0 +1,4 @@ +tqpluginloader/st_qprinter +silly +test.pdf + diff --git a/tests/auto/gui/painting/qprinter/qprinter.pro b/tests/auto/gui/painting/qprinter/qprinter.pro new file mode 100644 index 0000000000..cbe4ad7986 --- /dev/null +++ b/tests/auto/gui/painting/qprinter/qprinter.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +QT += printsupport widgets +SOURCES += tst_qprinter.cpp + +mac*:CONFIG+=insignificant_test diff --git a/tests/auto/gui/painting/qprinter/tst_qprinter.cpp b/tests/auto/gui/painting/qprinter/tst_qprinter.cpp new file mode 100644 index 0000000000..a6b6895981 --- /dev/null +++ b/tests/auto/gui/painting/qprinter/tst_qprinter.cpp @@ -0,0 +1,1044 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> + +#include <qprinter.h> +#include <qpagesetupdialog.h> +#include <qpainter.h> +#include <qprintdialog.h> +#include <qprinterinfo.h> +#include <qvariant.h> +#include <qpainter.h> +#include <qprintengine.h> + +#include <math.h> + +#ifdef Q_WS_WIN +#include <windows.h> +#endif + +Q_DECLARE_METATYPE(QRect) + +QT_FORWARD_DECLARE_CLASS(QPrinter) + +//TESTED_CLASS= +//TESTED_FILES= + +#ifndef QT_NO_PRINTER + +class tst_QPrinter : public QObject +{ + Q_OBJECT + +public: + tst_QPrinter(); + virtual ~tst_QPrinter(); + + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void getSetCheck(); +// Add your testfunctions and testdata create functions here + void testPageSize(); + void testPageRectAndPaperRect(); + void testPageRectAndPaperRect_data(); + void testSetOptions(); + void testMargins_data(); + void testMargins(); + void testNonExistentPrinter(); + void testPageSetupDialog(); + void testMulitpleSets_data(); + void testMulitpleSets(); + void testPageMargins_data(); + void testPageMargins(); + void changingOutputFormat(); + void outputFormatFromSuffix(); + void setGetPaperSize(); + void valuePreservation(); + void errorReporting(); + void testCustomPageSizes(); + void printDialogCompleter(); + + void testCopyCount(); + void testCurrentPage(); + + void taskQTBUG4497_reusePrinterOnDifferentFiles(); + void testPdfTitle(); + +private: +}; + +// Testing get/set functions +void tst_QPrinter::getSetCheck() +{ + QPrinter obj1; + // OutputFormat QPrinter::outputFormat() + // void QPrinter::setOutputFormat(OutputFormat) + obj1.setOutputFormat(QPrinter::OutputFormat(QPrinter::PdfFormat)); + QCOMPARE(QPrinter::OutputFormat(QPrinter::PdfFormat), obj1.outputFormat()); + + // bool QPrinter::collateCopies() + // void QPrinter::setCollateCopies(bool) + obj1.setCollateCopies(false); + QCOMPARE(false, obj1.collateCopies()); + obj1.setCollateCopies(true); + QCOMPARE(true, obj1.collateCopies()); + + obj1.setColorMode(QPrinter::GrayScale); + QCOMPARE(obj1.colorMode(), QPrinter::GrayScale); + obj1.setColorMode(QPrinter::Color); + QCOMPARE(obj1.colorMode(), QPrinter::Color); + + obj1.setCreator(QString::fromLatin1("RandomQtUser")); + QCOMPARE(obj1.creator(), QString::fromLatin1("RandomQtUser")); + + obj1.setDocName(QString::fromLatin1("RandomQtDocument")); + QCOMPARE(obj1.docName(), QString::fromLatin1("RandomQtDocument")); + + obj1.setDoubleSidedPrinting(true); + QCOMPARE(obj1.doubleSidedPrinting(), true); + obj1.setDoubleSidedPrinting(false); + QCOMPARE(obj1.doubleSidedPrinting(), false); + + obj1.setFromTo(1, 4); + QCOMPARE(obj1.fromPage(), 1); + QCOMPARE(obj1.toPage(), 4); + + obj1.setFullPage(true); + QCOMPARE(obj1.fullPage(), true); + obj1.setFullPage(false); + QCOMPARE(obj1.fullPage(), false); + + obj1.setOrientation(QPrinter::Landscape); + QCOMPARE(obj1.orientation(), QPrinter::Landscape); + obj1.setOrientation(QPrinter::Portrait); + QCOMPARE(obj1.orientation(), QPrinter::Portrait); + + obj1.setOutputFileName(QString::fromLatin1("RandomQtName")); + QCOMPARE(obj1.outputFileName(), QString::fromLatin1("RandomQtName")); + + obj1.setPageOrder(QPrinter::FirstPageFirst); + QCOMPARE(obj1.pageOrder(), QPrinter::FirstPageFirst); + obj1.setPageOrder(QPrinter::LastPageFirst); + QCOMPARE(obj1.pageOrder(), QPrinter::LastPageFirst); + + obj1.setPaperSource(QPrinter::Cassette); + QCOMPARE(obj1.paperSource(), QPrinter::Cassette); + obj1.setPaperSource(QPrinter::Middle); + QCOMPARE(obj1.paperSource(), QPrinter::Middle); + +#ifdef Q_OS_UNIX + obj1.setPrintProgram(QString::fromLatin1("/bin/true")); + QCOMPARE(obj1.printProgram(), QString::fromLatin1("/bin/true")); + + obj1.setPrinterSelectionOption(QString::fromLatin1("--option")); + QCOMPARE(obj1.printerSelectionOption(), QString::fromLatin1("--option")); +#endif + + obj1.setPrinterName(QString::fromLatin1("myPrinter")); + QCOMPARE(obj1.printerName(), QString::fromLatin1("myPrinter")); + + // bool QPrinter::fontEmbeddingEnabled() + // void QPrinter::setFontEmbeddingEnabled(bool) + obj1.setFontEmbeddingEnabled(false); + QCOMPARE(false, obj1.fontEmbeddingEnabled()); + obj1.setFontEmbeddingEnabled(true); + QCOMPARE(true, obj1.fontEmbeddingEnabled()); + + // PageSize QPrinter::pageSize() + // void QPrinter::setPageSize(PageSize) + obj1.setPageSize(QPrinter::PageSize(QPrinter::A4)); + QCOMPARE(QPrinter::PageSize(QPrinter::A4), obj1.pageSize()); + obj1.setPageSize(QPrinter::PageSize(QPrinter::Letter)); + QCOMPARE(QPrinter::PageSize(QPrinter::Letter), obj1.pageSize()); + obj1.setPageSize(QPrinter::PageSize(QPrinter::Legal)); + QCOMPARE(QPrinter::PageSize(QPrinter::Legal), obj1.pageSize()); + + // PrintRange QPrinter::printRange() + // void QPrinter::setPrintRange(PrintRange) + obj1.setPrintRange(QPrinter::PrintRange(QPrinter::AllPages)); + QCOMPARE(QPrinter::PrintRange(QPrinter::AllPages), obj1.printRange()); + obj1.setPrintRange(QPrinter::PrintRange(QPrinter::Selection)); + QCOMPARE(QPrinter::PrintRange(QPrinter::Selection), obj1.printRange()); + obj1.setPrintRange(QPrinter::PrintRange(QPrinter::PageRange)); + QCOMPARE(QPrinter::PrintRange(QPrinter::PageRange), obj1.printRange()); +} + +tst_QPrinter::tst_QPrinter() +{ +} + +tst_QPrinter::~tst_QPrinter() +{ +} + +// initTestCase will be executed once before the first testfunction is executed. +void tst_QPrinter::initTestCase() +{ +// TODO: Add testcase generic initialization code here. +// suggestion: +// testWidget = new QPrinter(0,"testWidget"); +// testWidget->setFixedSize(200, 200); +// qApp->setMainWidget(testWidget); +// testWidget->show(); +} + +// cleanupTestCase will be executed once after the last testfunction is executed. +void tst_QPrinter::cleanupTestCase() +{ +// TODO: Add testcase generic cleanup code here. +// suggestion: +// testWidget->hide(); +// qApp->setMainWidget(0); +// delete testWidget; +} + +// init() will be executed immediately before each testfunction is run. +void tst_QPrinter::init() +{ +// TODO: Add testfunction specific initialization code here. +} + +// cleanup() will be executed immediately after each testfunction is run. +void tst_QPrinter::cleanup() +{ +// TODO: Add testfunction specific cleanup code here. +} + +#define MYCOMPARE(a, b) QCOMPARE(QVariant((int)a), QVariant((int)b)) + +void tst_QPrinter::testPageSetupDialog() +{ + // Make sure this doesn't crash at least + { + QPrinter printer; + QPageSetupDialog dialog(&printer); + } +} + +void tst_QPrinter::testPageSize() +{ +#if defined (Q_WS_WIN) + QPrinter prn; + + prn.setPageSize(QPrinter::Letter); + MYCOMPARE(prn.pageSize(), QPrinter::Letter); + MYCOMPARE(prn.winPageSize(), DMPAPER_LETTER); + + prn.setPageSize(QPrinter::A4); + MYCOMPARE(prn.pageSize(), QPrinter::A4); + MYCOMPARE(prn.winPageSize(), DMPAPER_A4); + + prn.setWinPageSize(DMPAPER_LETTER); + MYCOMPARE(prn.winPageSize(), DMPAPER_LETTER); + MYCOMPARE(prn.pageSize(), QPrinter::Letter); + + prn.setWinPageSize(DMPAPER_A4); + MYCOMPARE(prn.winPageSize(), DMPAPER_A4); + MYCOMPARE(prn.pageSize(), QPrinter::A4); +#else + QSKIP("QPrinter::winPageSize() does not exist for nonwindows platforms", SkipAll); +#endif +} + +void tst_QPrinter::testPageRectAndPaperRect_data() +{ + QTest::addColumn<int>("orientation"); + QTest::addColumn<bool>("withPainter"); + QTest::addColumn<int>("resolution"); + QTest::addColumn<bool>("doPaperRect"); + + // paperrect + QTest::newRow("paperRect0") << int(QPrinter::Portrait) << true << 300 << true; + QTest::newRow("paperRect1") << int(QPrinter::Portrait) << false << 300 << true; + QTest::newRow("paperRect2") << int(QPrinter::Landscape) << true << 300 << true; + QTest::newRow("paperRect3") << int(QPrinter::Landscape) << false << 300 << true; + QTest::newRow("paperRect4") << int(QPrinter::Portrait) << true << 600 << true; + QTest::newRow("paperRect5") << int(QPrinter::Portrait) << false << 600 << true; + QTest::newRow("paperRect6") << int(QPrinter::Landscape) << true << 600 << true; + QTest::newRow("paperRect7") << int(QPrinter::Landscape) << false << 600 << true; + QTest::newRow("paperRect8") << int(QPrinter::Portrait) << true << 1200 << true; + QTest::newRow("paperRect9") << int(QPrinter::Portrait) << false << 1200 << true; + QTest::newRow("paperRect10") << int(QPrinter::Landscape) << true << 1200 << true; + QTest::newRow("paperRect11") << int(QPrinter::Landscape) << false << 1200 << true; + + // page rect + QTest::newRow("pageRect0") << int(QPrinter::Portrait) << true << 300 << false; + QTest::newRow("pageRect1") << int(QPrinter::Portrait) << false << 300 << false; + QTest::newRow("pageRect2") << int(QPrinter::Landscape) << true << 300 << false; + QTest::newRow("pageRect3") << int(QPrinter::Landscape) << false << 300 << false; + QTest::newRow("pageRect4") << int(QPrinter::Portrait) << true << 600 << false; + QTest::newRow("pageRect5") << int(QPrinter::Portrait) << false << 600 << false; + QTest::newRow("pageRect6") << int(QPrinter::Landscape) << true << 600 << false; + QTest::newRow("pageRect7") << int(QPrinter::Landscape) << false << 600 << false; + QTest::newRow("pageRect8") << int(QPrinter::Portrait) << true << 1200 << false; + QTest::newRow("pageRect9") << int(QPrinter::Portrait) << false << 1200 << false; + QTest::newRow("pageRect10") << int(QPrinter::Landscape) << true << 1200 << false; + QTest::newRow("pageRect11") << int(QPrinter::Landscape) << false << 1200 << false; +} + +void tst_QPrinter::testPageRectAndPaperRect() +{ + QFETCH(bool, withPainter); + QFETCH(int, orientation); + QFETCH(int, resolution); + QFETCH(bool, doPaperRect); + + QPainter *painter = 0; + QPrinter printer(QPrinter::HighResolution); + printer.setOrientation(QPrinter::Orientation(orientation)); + printer.setOutputFileName("silly"); + + QRect pageRect = doPaperRect ? printer.paperRect() : printer.pageRect(); + float inchesX = float(pageRect.width()) / float(printer.resolution()); + float inchesY = float(pageRect.height()) / float(printer.resolution()); + printer.setResolution(resolution); + if (withPainter) + painter = new QPainter(&printer); + + QRect otherRect = doPaperRect ? printer.paperRect() : printer.pageRect(); + float otherInchesX = float(otherRect.width()) / float(printer.resolution()); + float otherInchesY = float(otherRect.height()) / float(printer.resolution()); + if (painter != 0) + delete painter; + + QVERIFY(qAbs(otherInchesX - inchesX) < 0.01); + QVERIFY(qAbs(otherInchesY - inchesY) < 0.01); + + QVERIFY(printer.orientation() == QPrinter::Portrait || pageRect.width() > pageRect.height()); + QVERIFY(printer.orientation() != QPrinter::Portrait || pageRect.width() < pageRect.height()); +} + +void tst_QPrinter::testSetOptions() +{ + QPrinter prn; + QPrintDialog dlg(&prn); + + // Verify default values + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), TRUE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), FALSE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE); + + dlg.setEnabledOptions(QAbstractPrintDialog::PrintPageRange); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), FALSE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE); + + dlg.setEnabledOptions((QAbstractPrintDialog::PrintDialogOptions(QAbstractPrintDialog::PrintSelection + | QAbstractPrintDialog::PrintPageRange))); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), TRUE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), TRUE); + + dlg.setEnabledOptions(QAbstractPrintDialog::PrintSelection); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintToFile), FALSE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintSelection), TRUE); + MYCOMPARE(dlg.isOptionEnabled(QAbstractPrintDialog::PrintPageRange), FALSE); +} + +void tst_QPrinter::testMargins_data() +{ + QTest::addColumn<int>("orientation"); + QTest::addColumn<bool>("fullpage"); + QTest::addColumn<int>("pagesize"); + QTest::addColumn<int>("width"); + QTest::addColumn<int>("height"); + QTest::addColumn<bool>("withPainter"); + + QTest::newRow("data0") << int(QPrinter::Portrait) << true << int(QPrinter::A4) << 210 << 297 << false; + QTest::newRow("data1") << int(QPrinter::Landscape) << true << int(QPrinter::A4) << 297 << 210 << false; + QTest::newRow("data2") << int(QPrinter::Landscape) << false << int(QPrinter::A4) << 297 << 210 << false; + QTest::newRow("data3") << int(QPrinter::Portrait) << false << int(QPrinter::A4) << 210 << 297 << false; + QTest::newRow("data4") << int(QPrinter::Portrait) << true << int(QPrinter::A4) << 210 << 297 << true; + QTest::newRow("data5") << int(QPrinter::Landscape) << true << int(QPrinter::A4) << 297 << 210 << true; + QTest::newRow("data6") << int(QPrinter::Landscape) << false << int(QPrinter::A4) << 297 << 210 << true; + QTest::newRow("data7") << int(QPrinter::Portrait) << false << int(QPrinter::A4) << 210 << 297 << true; +} + +void tst_QPrinter::testMargins() +{ + QFETCH(bool, withPainter); + QFETCH(int, orientation); + QFETCH(int, pagesize); + QFETCH(int, width); + QFETCH(int, height); + QFETCH(bool, fullpage); + Q_UNUSED(width); + Q_UNUSED(height); + QPrinter printer; + QPainter *painter = 0; + printer.setOutputFileName("silly"); + printer.setOrientation((QPrinter::Orientation)orientation); + printer.setFullPage(fullpage); + printer.setPageSize((QPrinter::PageSize)pagesize); + if (withPainter) + painter = new QPainter(&printer); + + if (painter) + delete painter; +} + +void tst_QPrinter::testNonExistentPrinter() +{ +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_MAC) + QSKIP("QPrinter::testNonExistentPrinter() is not relevant for this platform", SkipAll); +#else + QPrinter printer; + QPainter painter; + + // Make sure it doesn't crash on setting or getting properties + printer.setPrinterName("some non existing printer"); + printer.setPageSize(QPrinter::A4); + printer.setOrientation(QPrinter::Portrait); + printer.setFullPage(true); + printer.pageSize(); + printer.orientation(); + printer.fullPage(); + printer.setCopyCount(1); + printer.printerName(); + + // nor metrics + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmWidth), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmHeight), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmWidthMM), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmHeightMM), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmNumColors), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDepth), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDpiX), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmDpiY), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmPhysicalDpiX), 0); + QCOMPARE(printer.printEngine()->metric(QPaintDevice::PdmPhysicalDpiY), 0); + + QVERIFY(!painter.begin(&printer)); +#endif +} + + +void tst_QPrinter::testMulitpleSets_data() +{ + QTest::addColumn<int>("resolution"); + QTest::addColumn<int>("pageSize"); + QTest::addColumn<int>("widthMMAfter"); + QTest::addColumn<int>("heightMMAfter"); + + + QTest::newRow("lowRes") << int(QPrinter::ScreenResolution) << int(QPrinter::A4) << 210 << 297; + QTest::newRow("lowResLetter") << int(QPrinter::ScreenResolution) << int(QPrinter::Letter) << 216 << 279; + QTest::newRow("lowResA5") << int(QPrinter::ScreenResolution) << int(QPrinter::A5) << 148 << 210; + QTest::newRow("midRes") << int(QPrinter::PrinterResolution) << int(QPrinter::A4) << 210 << 297; + QTest::newRow("midResLetter") << int(QPrinter::PrinterResolution) << int(QPrinter::Letter) << 216 << 279; + QTest::newRow("midResA5") << int(QPrinter::PrinterResolution) << int(QPrinter::A5) << 148 << 210; + QTest::newRow("highRes") << int(QPrinter::HighResolution) << int(QPrinter::A4) << 210 << 297; + QTest::newRow("highResLetter") << int(QPrinter::HighResolution) << int(QPrinter::Letter) << 216 << 279; + QTest::newRow("highResA5") << int(QPrinter::HighResolution) << int(QPrinter::A5) << 148 << 210; +} + +static void computePageValue(const QPrinter &printer, int &retWidth, int &retHeight) +{ + const double Inch2MM = 25.4; + + double width = double(printer.paperRect().width()) / printer.logicalDpiX() * Inch2MM; + double height = double(printer.paperRect().height()) / printer.logicalDpiY() * Inch2MM; + retWidth = qRound(width); + retHeight = qRound(height); +} + +void tst_QPrinter::testMulitpleSets() +{ + // A very simple test, but Mac needs to have its format "validated" if the format is changed + // This takes care of that. + QFETCH(int, resolution); + QFETCH(int, pageSize); + QFETCH(int, widthMMAfter); + QFETCH(int, heightMMAfter); + + + QPrinter::PrinterMode mode = QPrinter::PrinterMode(resolution); + QPrinter::PageSize printerPageSize = QPrinter::PageSize(pageSize); + QPrinter printer(mode); + printer.setFullPage(true); + + int paperWidth, paperHeight; + //const int Tolerance = 2; + + computePageValue(printer, paperWidth, paperHeight); + printer.setPageSize(printerPageSize); + + if (printer.pageSize() != printerPageSize) { + QSKIP("Current page size is not supported on this printer", SkipSingle); + return; + } + + QCOMPARE(printer.widthMM(), widthMMAfter); + QCOMPARE(printer.heightMM(), heightMMAfter); + + computePageValue(printer, paperWidth, paperHeight); + + QVERIFY(qAbs(paperWidth - widthMMAfter) <= 2); + QVERIFY(qAbs(paperHeight - heightMMAfter) <= 2); + + // Set it again and see if it still works. + printer.setPageSize(printerPageSize); + QCOMPARE(printer.widthMM(), widthMMAfter); + QCOMPARE(printer.heightMM(), heightMMAfter); + + printer.setOrientation(QPrinter::Landscape); + computePageValue(printer, paperWidth, paperHeight); + QVERIFY(qAbs(paperWidth - heightMMAfter) <= 2); + QVERIFY(qAbs(paperHeight - widthMMAfter) <= 2); +} + +void tst_QPrinter::changingOutputFormat() +{ +#if QT_VERSION < 0x050000 + QPrinter p; + p.setOutputFormat(QPrinter::PostScriptFormat); + p.setPageSize(QPrinter::A8); + p.setOutputFormat(QPrinter::PdfFormat); + QCOMPARE(p.pageSize(), QPrinter::A8); +#endif +} + +void tst_QPrinter::outputFormatFromSuffix() +{ + if (QPrinterInfo::availablePrinters().size() == 0) + QSKIP("No printers available.", SkipAll); + QPrinter p; + QVERIFY(p.outputFormat() == QPrinter::NativeFormat); + p.setOutputFileName("test.pdf"); + QVERIFY(p.outputFormat() == QPrinter::PdfFormat); + p.setOutputFileName(QString()); + QVERIFY(p.outputFormat() == QPrinter::NativeFormat); +} + +void tst_QPrinter::setGetPaperSize() +{ + QPrinter p; + p.setOutputFormat(QPrinter::PdfFormat); + QSizeF size(500, 10); + p.setPaperSize(size, QPrinter::Millimeter); + QCOMPARE(p.paperSize(QPrinter::Millimeter), size); + QSizeF ptSize = p.paperSize(QPrinter::Point); + //qDebug() << ptSize; + QVERIFY(qAbs(ptSize.width() - size.width() * (72/25.4)) < 1E-4); + QVERIFY(qAbs(ptSize.height() - size.height() * (72/25.4)) < 1E-4); +} + +void tst_QPrinter::testPageMargins_data() +{ + QTest::addColumn<qreal>("left"); + QTest::addColumn<qreal>("top"); + QTest::addColumn<qreal>("right"); + QTest::addColumn<qreal>("bottom"); + QTest::addColumn<int>("unit"); + + QTest::newRow("data0") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Millimeter); + QTest::newRow("data1") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Point); + QTest::newRow("data2") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Inch); + QTest::newRow("data3") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Pica); + QTest::newRow("data4") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Didot); + QTest::newRow("data5") << qreal(5.5) << qreal(6.5) << qreal(7.5) << qreal(8.5) << static_cast<int>(QPrinter::Cicero); +} + +void tst_QPrinter::testPageMargins() +{ + QPrinter obj1; + + qreal toMillimeters[6]; + toMillimeters[QPrinter::Millimeter] = 1; + toMillimeters[QPrinter::Point] = 0.352777778; + toMillimeters[QPrinter::Inch] = 25.4; + toMillimeters[QPrinter::Pica] = 4.23333333; + toMillimeters[QPrinter::Didot] = 0.376; + toMillimeters[QPrinter::Cicero] = 4.51166667; + + QFETCH(qreal, left); + QFETCH(qreal, top); + QFETCH(qreal, right); + QFETCH(qreal, bottom); + QFETCH(int, unit); + + qreal nLeft, nTop, nRight, nBottom; + + obj1.setPageMargins(left, top, right, bottom, static_cast<QPrinter::Unit>(unit)); + + qreal tolerance = 0.05; + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Millimeter); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Millimeter]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Millimeter]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Millimeter]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Millimeter]) < tolerance); + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Point); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Point]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Point]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Point]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Point]) < tolerance); + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Inch); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Inch]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Inch]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Inch]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Inch]) < tolerance); + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Pica); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Pica]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Pica]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Pica]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Pica]) < tolerance); + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Didot); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Didot]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Didot]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Didot]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Didot]) < tolerance); + + obj1.getPageMargins(&nLeft, &nTop, &nRight, &nBottom, QPrinter::Cicero); + QVERIFY(fabs(left*toMillimeters[unit] - nLeft*toMillimeters[QPrinter::Cicero]) < tolerance); + QVERIFY(fabs(top*toMillimeters[unit] - nTop*toMillimeters[QPrinter::Cicero]) < tolerance); + QVERIFY(fabs(right*toMillimeters[unit] - nRight*toMillimeters[QPrinter::Cicero]) < tolerance); + QVERIFY(fabs(bottom*toMillimeters[unit] - nBottom*toMillimeters[QPrinter::Cicero]) < tolerance); +} + +void tst_QPrinter::valuePreservation() +{ + QPrinter::OutputFormat oldFormat = QPrinter::PdfFormat; + QPrinter::OutputFormat newFormat = QPrinter::NativeFormat; // TODO: Correct? + + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + bool status = printer.collateCopies(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.collateCopies(), status); + + printer.setCollateCopies(!status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.collateCopies(), !status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.collateCopies(), !status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::ColorMode status = printer.colorMode(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.colorMode(), status); + + printer.setColorMode(QPrinter::ColorMode(!status)); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.colorMode(), QPrinter::ColorMode(!status)); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.colorMode(), QPrinter::ColorMode(!status)); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.creator(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.creator(), status); + + status = QString::fromLatin1("Mr. Test"); + printer.setCreator(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.creator(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.creator(), status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.docName(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.docName(), status); + + status = QString::fromLatin1("Test document"); + printer.setDocName(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.docName(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.docName(), status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + bool status = printer.doubleSidedPrinting(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.doubleSidedPrinting(), status); + + printer.setDoubleSidedPrinting(!status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.doubleSidedPrinting(), !status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.doubleSidedPrinting(), !status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + bool status = printer.fontEmbeddingEnabled(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.fontEmbeddingEnabled(), status); + + printer.setFontEmbeddingEnabled(!status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.fontEmbeddingEnabled(), !status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.fontEmbeddingEnabled(), !status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + bool status = printer.fullPage(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.fullPage(), status); + + printer.setFullPage(!status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.fullPage(), !status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.fullPage(), !status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::Orientation status = printer.orientation(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.orientation(), status); + + printer.setOrientation(QPrinter::Orientation(!status)); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.orientation(), QPrinter::Orientation(!status)); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.orientation(), QPrinter::Orientation(!status)); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.outputFileName(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.outputFileName(), status); + + status = QString::fromLatin1("Test file"); + printer.setOutputFileName(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.outputFileName(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.outputFileName(), status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::PageOrder status = printer.pageOrder(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.pageOrder(), status); + + printer.setPageOrder(QPrinter::PageOrder(!status)); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.pageOrder(), QPrinter::PageOrder(!status)); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.pageOrder(), QPrinter::PageOrder(!status)); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::PageSize status = printer.pageSize(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.pageSize(), status); + + printer.setPageSize(QPrinter::B5); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.pageSize(), QPrinter::B5); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.pageSize(), QPrinter::B5); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::PaperSource status = printer.paperSource(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.paperSource(), status); + + printer.setPaperSource(QPrinter::Manual); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.paperSource(), QPrinter::Manual); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.paperSource(), QPrinter::Manual); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.printProgram(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printProgram(), status); + + status = QString::fromLatin1("/usr/local/bin/lpr"); + printer.setPrintProgram(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.printProgram(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printProgram(), status); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QPrinter::PrintRange status = printer.printRange(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printRange(), status); + + printer.setPrintRange(QPrinter::PrintRange(!status)); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.printRange(), QPrinter::PrintRange(!status)); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printRange(), QPrinter::PrintRange(!status)); + } + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.printerName(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printerName(), status); + + status = QString::fromLatin1("SuperDuperPrinter"); + printer.setPrinterName(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.printerName(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printerName(), status); + } +#ifndef Q_OS_WIN + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + QString status = printer.printerSelectionOption(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printerSelectionOption(), status); + + status = QString::fromLatin1("Optional option"); + printer.setPrinterSelectionOption(status); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.printerSelectionOption(), status); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.printerSelectionOption(), status); + } +#endif + { + QPrinter printer; + printer.setOutputFormat(oldFormat); + int status = printer.resolution(); + printer.setOutputFormat(newFormat); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.resolution(), status); + + printer.setResolution(status-150); + printer.setOutputFormat(newFormat); + QCOMPARE(printer.resolution(), status-150); + printer.setOutputFormat(oldFormat); + QCOMPARE(printer.resolution(), status-150); + } +} + +void tst_QPrinter::errorReporting() +{ + QPrinter p; + p.setOutputFormat(QPrinter::PdfFormat); + QCOMPARE(p.isValid(), true); + QPainter painter; +#ifndef Q_WS_WIN + // not sure how to choose a never-writable file on windows. But its QFile behavior anyway, so lets rely on it failing elsewhere + p.setOutputFileName("/foobar/nonwritable.pdf"); + QCOMPARE(painter.begin(&p), false); // it should check the output file is writable +#endif + p.setOutputFileName("test.pdf"); + QCOMPARE(painter.begin(&p), true); // it should check the output + QCOMPARE(p.isValid(), true); + painter.end(); +} + +void tst_QPrinter::testCustomPageSizes() +{ + QPrinter p; + + QSizeF customSize(8.5, 11.0); + p.setPaperSize(customSize, QPrinter::Inch); + + QSizeF paperSize = p.paperSize(QPrinter::Inch); + QCOMPARE(paperSize, customSize); + + QPrinter p2(QPrinter::HighResolution); + p2.setPaperSize(customSize, QPrinter::Inch); + paperSize = p.paperSize(QPrinter::Inch); + QCOMPARE(paperSize, customSize); +} + +void tst_QPrinter::printDialogCompleter() +{ +#if defined(QT_NO_COMPLETER) || defined(QT_NO_FILEDIALOG) + QSKIP("QT_NO_COMPLETER || QT_NO_FILEDIALOG: Auto-complete turned off in QPrinterDialog.", QTest::SkipAll); +#else + QPrintDialog dialog; + dialog.printer()->setOutputFileName("file.pdf"); + dialog.setEnabledOptions(QAbstractPrintDialog::PrintToFile); + dialog.show(); + + QTest::qWait(100); + + QTest::keyClick(&dialog, Qt::Key_Tab); + QTest::keyClick(&dialog, 'P'); + // The test passes if it doesn't crash. +#endif +} + +void tst_QPrinter::testCopyCount() +{ + QPrinter p; + p.setCopyCount(15); + QCOMPARE(p.copyCount(), 15); +} + +static void printPage(QPainter *painter) +{ + painter->setPen(QPen(Qt::black, 4)); + painter->drawRect(50, 60, 70, 80); +} + +void tst_QPrinter::taskQTBUG4497_reusePrinterOnDifferentFiles() +{ + QPrinter printer; + { + + printer.setOutputFileName("out1.ps"); + QPainter painter(&printer); + printPage(&painter); + + } + { + + printer.setOutputFileName("out2.ps"); + QPainter painter(&printer); + printPage(&painter); + + } + QFile file1("out1.ps"); + QVERIFY(file1.open(QIODevice::ReadOnly)); + + QFile file2("out2.ps"); + QVERIFY(file2.open(QIODevice::ReadOnly)); + + QCOMPARE(file1.readAll(), file2.readAll()); +} + +void tst_QPrinter::testCurrentPage() +{ + QPrinter printer; + printer.setFromTo(1, 10); + + // Test set print range + printer.setPrintRange(QPrinter::CurrentPage); + QCOMPARE(printer.printRange(), QPrinter::CurrentPage); + QCOMPARE(printer.fromPage(), 1); + QCOMPARE(printer.toPage(), 10); + + QPrintDialog dialog(&printer); + + // Test default Current Page option to off + QCOMPARE(dialog.isOptionEnabled(QPrintDialog::PrintCurrentPage), false); + + // Test enable Current Page option + dialog.setOption(QPrintDialog::PrintCurrentPage); + QCOMPARE(dialog.isOptionEnabled(QPrintDialog::PrintCurrentPage), true); + +} + +void tst_QPrinter::testPdfTitle() +{ + // Check the document name is represented correctly in produced pdf + { + QPainter painter; + QPrinter printer; + // This string is just the UTF-8 encoding of the string: \()f ø hiragana o + const char title[]={0x5c, 0x28, 0x29, 0x66, 0xc3, 0xb8, 0xe3, 0x81, 0x8a, 0x00}; + printer.setOutputFileName("file.pdf"); + printer.setDocName(QString::fromUtf8(title)); + painter.begin(&printer); + painter.end(); + } + QFile file("file.pdf"); + QVERIFY(file.open(QIODevice::ReadOnly)); + // The we expect the title to appear in the PDF as: + // ASCII('\title (') UTF16(\\\(\)f ø hiragana o) ASCII(')'). + // which has the following binary representation + const char expected[] = { + 0x2f, 0x54, 0x69, 0x74, 0x6c, 0x65, 0x20, 0x28, 0xfe, + 0xff, 0x00, 0x5c, 0x5c, 0x00, 0x5c, 0x28, 0x00, 0x5c, + 0x29, 0x00, 0x66, 0x00, 0xf8, 0x30, 0x4a, 0x29}; + QVERIFY(file.readAll().contains(QByteArray(expected, 26))); +} + +QTEST_MAIN(tst_QPrinter) +#include "tst_qprinter.moc" + +#else //QT_NO_PRINTER + +QTEST_NOOP_MAIN + +#endif //QT_NO_PRINTER diff --git a/tests/auto/gui/painting/qprinterinfo/.gitignore b/tests/auto/gui/painting/qprinterinfo/.gitignore new file mode 100644 index 0000000000..fcef7c1997 --- /dev/null +++ b/tests/auto/gui/painting/qprinterinfo/.gitignore @@ -0,0 +1 @@ +tst_qprinterinfo diff --git a/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro b/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro new file mode 100644 index 0000000000..1bf799d6ce --- /dev/null +++ b/tests/auto/gui/painting/qprinterinfo/qprinterinfo.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +SOURCES += tst_qprinterinfo.cpp + +QT += printsupport network + +DEFINES += QT_USE_USING_NAMESPACE + diff --git a/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp new file mode 100644 index 0000000000..7e5da4a6f8 --- /dev/null +++ b/tests/auto/gui/painting/qprinterinfo/tst_qprinterinfo.cpp @@ -0,0 +1,401 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <QtGlobal> +#include <QtAlgorithms> +#include <QtNetwork/QHostInfo> + +#ifndef QT_NO_PRINTER +#include <qprinterinfo.h> + +#ifdef Q_OS_UNIX +# include <unistd.h> +# include <sys/types.h> +# include <sys/wait.h> +#endif + +Q_DECLARE_METATYPE(QRect) + + +#if defined(Q_OS_WIN32) +# define ACCEPTABLE_WINDOWS +#endif + + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QPrinterInfo : public QObject +{ + Q_OBJECT + +public: + //tst_QPrinterInfo(); + //virtual ~tst_QPrinterInfo(); + + +public slots: + //void initTestCase(); + //void cleanupTestCase(); + //void init(); + //void cleanup(); +private slots: + void testForDefaultPrinter(); + void testForPrinters(); + void testForPaperSizes(); + void testConstructors(); + void testAssignment(); + +private: + void macFixNameFormat(QString *printerName); + QString getDefaultPrinterFromSystem(); + QStringList getPrintersFromSystem(); + + QString getOutputFromCommand(const QStringList& command); +}; + +void tst_QPrinterInfo::macFixNameFormat(QString *printerName) +{ +// Modify the format of the printer name to match Qt, lpstat returns +// foo___domain_no, Qt returns foo @ domain.no +#ifdef Q_WS_MAC + printerName->replace(QLatin1String("___"), QLatin1String(" @ ")); + printerName->replace(QLatin1String("_"), QLatin1String(".")); +#else + Q_UNUSED(printerName); +#endif +} + +QString tst_QPrinterInfo::getDefaultPrinterFromSystem() +{ + QStringList command; + command << "lpstat" << "-d"; + QString output = getOutputFromCommand(command); + + QRegExp noDefaultReg("[^:]*no .*default"); + int pos = noDefaultReg.indexIn(output); + if (pos >= 0) { + return QString(); + } + + QRegExp defaultReg("default.*: *([a-zA-Z0-9_]+)"); + defaultReg.indexIn(output); + QString printer = defaultReg.cap(1); + macFixNameFormat(&printer); + return printer; +} + +QStringList tst_QPrinterInfo::getPrintersFromSystem() +{ + QStringList ans; + + QStringList command; + command << "lpstat" << "-p"; + QString output = getOutputFromCommand(command); + QStringList list = output.split(QChar::fromLatin1('\n')); + + QRegExp reg("^[Pp]rinter ([.a-zA-Z0-9-_@]+)"); + for (int c = 0; c < list.size(); ++c) { + if (reg.indexIn(list[c]) >= 0) { + QString printer = reg.cap(1); + macFixNameFormat(&printer); + ans << printer; + } + } + + return ans; +} + +// This function does roughly the same as the `command substitution` in +// the shell. +QString tst_QPrinterInfo::getOutputFromCommand(const QStringList& command) +{ +// The command execution does nothing on non-unix systems. +#ifdef Q_OS_UNIX + int pid; + int status = 0; + int pipePtr[2]; + + // Create a pipe that is shared between parent and child process. + if (pipe(pipePtr) < 0) { + return QString(); + } + pid = fork(); + if (pid < 0) { + close(pipePtr[0]); + close(pipePtr[1]); + return QString(); + } else if (pid == 0) { + // In child. + // Close the reading end. + close(pipePtr[0]); + // Redirect stdout to the pipe. + if (dup2(pipePtr[1], 1) < 0) { + exit(1); + } + + char** argv = new char*[command.size()+1]; + for (int c = 0; c < command.size(); ++c) { + argv[c] = new char[command[c].size()+1]; + strcpy(argv[c], command[c].toLatin1().data()); + } + argv[command.size()] = NULL; + execvp(argv[0], argv); + // Shouldn't get here, but it's possible if command is not found. + close(pipePtr[1]); + close(1); + for (int c = 0; c < command.size(); ++c) { + delete [] argv[c]; + } + delete [] argv; + exit(1); + } else { + // In parent. + // Close the writing end. + close(pipePtr[1]); + + QFile pipeRead; + if (!pipeRead.open(pipePtr[0], QIODevice::ReadOnly)) { + close(pipePtr[0]); + return QString(); + } + QByteArray array; + array = pipeRead.readAll(); + pipeRead.close(); + close(pipePtr[0]); + wait(&status); + return QString(array); + } +#else + return QString(); +#endif // Q_OS_UNIX +} + +void tst_QPrinterInfo::testForDefaultPrinter() +{ +#if defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS) +# ifdef ACCEPTABLE_WINDOWS + if (QHostInfo::localHostName() == "fantomet" || QHostInfo::localHostName() == "bobo") { + QWARN("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows and may fail"); + } else { + QSKIP("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows", SkipAll); + } + QString defSysPrinter; + if (QHostInfo::localHostName() == "fantomet") { + defSysPrinter = "Yacc (Lexmark Optra T610 PS3)"; + } else if (QHostInfo::localHostName() == "bobo") { + defSysPrinter = "press"; + } +# else + QString defSysPrinter = getDefaultPrinterFromSystem(); +# endif + if (defSysPrinter == "") return; + + QList<QPrinterInfo> list = QPrinterInfo::availablePrinters(); + bool found = false; + for (int c = 0; c < list.size(); ++c) { + if (list[c].isDefault()) { + QVERIFY(list.at(c).printerName() == defSysPrinter); + QVERIFY(!list.at(c).isNull()); + found = true; + } else { + QVERIFY(list.at(c).printerName() != defSysPrinter); + QVERIFY(!list.at(c).isNull()); + } + } + + if (!found && defSysPrinter != "") QFAIL("No default printer reported by Qt, although there is one"); +#else + QSKIP("Test doesn't work on non-Unix", SkipAll); +#endif // defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS) +} + +void tst_QPrinterInfo::testForPrinters() +{ +#if defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS) +# ifdef ACCEPTABLE_WINDOWS + if (QHostInfo::localHostName() == "fantomet" || QHostInfo::localHostName() == "bobo") { + QWARN("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows and may fail"); + } else { + QSKIP("Test is hardcoded to \"fantomet\" and \"bobo\" on Windows", SkipAll); + } + QStringList sysPrinters; + if (QHostInfo::localHostName() == "fantomet") { + sysPrinters + << "Press" + << "Canon PS-IPU Color Laser Copier v52.3" + << "EPSON EPL-N4000 PS3" + << "Kroksleiven" + << "Lexmark Optra Color 1200 PS" + << "Yacc (Lexmark Optra T610 PCL)" + << "Yacc (Lexmark Optra T610 PS3)" + ; + } else if (QHostInfo::localHostName() == "bobo") { + sysPrinters + << "press" + << "finnmarka" + << "nordmarka" + ; + } +# else + QStringList sysPrinters = getPrintersFromSystem(); +# endif + QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters(); + + QCOMPARE(printers.size(), sysPrinters.size()); + + QHash<QString, bool> qtPrinters; + + for (int j = 0; j < printers.size(); ++j) { + qtPrinters.insert(printers.at(j).printerName(), !printers.at(j).isNull()); + } + + for (int i = 0; i < sysPrinters.size(); ++i) { + if (!qtPrinters.value(sysPrinters.at(i))) { + qDebug() << "Available printers: " << qtPrinters; + QFAIL(qPrintable(QString("Printer '%1' reported by system, but not reported by Qt").arg(sysPrinters.at(i)))); + } + } +#else + QSKIP("Test doesn't work on non-Unix", SkipAll); +#endif // defined(Q_OS_UNIX) || defined(ACCEPTABLE_WINDOWS) +} + +void tst_QPrinterInfo::testForPaperSizes() +{ +QSKIP("PaperSize feature doesn't work on Windows, fails on Mac, and is unstable on Linux", SkipAll); + // This test is based on common printers found at the Oslo + // office. It is likely to be skipped or fail for other locations. + QStringList hardPrinters; + hardPrinters << "Finnmarka" << "Huldra"; + + QList<QList<QPrinter::PaperSize> > hardSizes; + hardSizes + << QList<QPrinter::PaperSize>() + << QList<QPrinter::PaperSize>() + ; + hardSizes[0] // Finnmarka + << QPrinter::Letter + << QPrinter::A4 + << QPrinter::A3 + << QPrinter::A5 + << QPrinter::B4 + << QPrinter::B5 + << QPrinter::Custom // COM10 + << QPrinter::Custom // C5 + << QPrinter::Custom // DL + << QPrinter::Custom // Monarch + << QPrinter::Executive + << QPrinter::Custom // Foolscap + << QPrinter::Custom // ISO B5 + << QPrinter::Ledger + << QPrinter::Legal + << QPrinter::Custom // Japanese Post Card + << QPrinter::Custom // Invoice + ; + hardSizes[1] // Huldra + << QPrinter::Custom // Not listed at http://localhost:631/, name "Custom" + << QPrinter::Letter + << QPrinter::A4 + << QPrinter::A5 + << QPrinter::A6 + << QPrinter::B5 + << QPrinter::Custom // #5 1/2 Envelope + << QPrinter::Custom // 6x9 Envelope + << QPrinter::Custom // #10 Envelope + << QPrinter::Custom // A7 Envelope + << QPrinter::Custom // C5 Envelope + << QPrinter::Custom // DL Envelope + << QPrinter::Custom // Monarch Envelope + << QPrinter::Custom // #6 3/4 Envelope + << QPrinter::Executive + << QPrinter::Custom // US Folio + << QPrinter::Custom // Index Card + << QPrinter::Custom // ISO B5 + << QPrinter::Legal + << QPrinter::Custom // Statement + ; + + QList<QPrinterInfo> printers = QPrinterInfo::availablePrinters(); + for (int i = 0; i < printers.size(); ++i) { + for (int j = 0; j < hardPrinters.size(); ++j) { + if (printers[i].printerName() == hardPrinters[j]) { + QList<QPrinter::PaperSize> sizes = printers[i].supportedPaperSizes(); + qSort(sizes); + qSort(hardSizes[j]); + QCOMPARE(sizes, hardSizes[j]); + } + } + } +} + +void tst_QPrinterInfo::testConstructors() +{ + QList<QPrinterInfo> prns(QPrinterInfo::availablePrinters()); + + for (int c = 0; c < prns.size(); ++c) { + QList<QPrinter::PaperSize> list1, list2; + list1 = prns[c].supportedPaperSizes(); + QPrinter pr(prns[c]); + list2 = QPrinterInfo(pr).supportedPaperSizes(); + QCOMPARE(list2, list1); + } +} + +void tst_QPrinterInfo::testAssignment() +{ + QList<QPrinterInfo> prns(QPrinterInfo::availablePrinters()); + + for (int c = 0; c < prns.size(); ++c) { + QPrinterInfo pi = QPrinterInfo::defaultPrinter(); + pi = prns[c]; + QCOMPARE(pi.printerName(), prns[c].printerName()); + QCOMPARE(pi.supportedPaperSizes(), prns[c].supportedPaperSizes()); + } +} + +QTEST_MAIN(tst_QPrinterInfo) +#include "tst_qprinterinfo.moc" +#else +QTEST_NOOP_MAIN +#endif diff --git a/tests/auto/gui/painting/qregion/.gitignore b/tests/auto/gui/painting/qregion/.gitignore new file mode 100644 index 0000000000..8be21c3736 --- /dev/null +++ b/tests/auto/gui/painting/qregion/.gitignore @@ -0,0 +1 @@ +tst_qregion diff --git a/tests/auto/gui/painting/qregion/qregion.pro b/tests/auto/gui/painting/qregion/qregion.pro new file mode 100644 index 0000000000..8dbb4844a0 --- /dev/null +++ b/tests/auto/gui/painting/qregion/qregion.pro @@ -0,0 +1,8 @@ +load(qttest_p4) + +QT += gui-private + +SOURCES += tst_qregion.cpp + + + diff --git a/tests/auto/gui/painting/qregion/tst_qregion.cpp b/tests/auto/gui/painting/qregion/tst_qregion.cpp new file mode 100644 index 0000000000..58d2034e41 --- /dev/null +++ b/tests/auto/gui/painting/qregion/tst_qregion.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <qregion.h> + +#include <qbitmap.h> +#include <qpainter.h> +#include <qpolygon.h> +#ifdef Q_WS_X11 +#include <private/qt_x11_p.h> +#endif + + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QRegion : public QObject +{ + Q_OBJECT + +public: + tst_QRegion(); + +private slots: + void boundingRect(); + void rects(); + void swap(); + void setRects(); + void ellipseRegion(); + void polygonRegion(); + void bitmapRegion(); + void intersected_data(); + void intersected(); + void emptyPolygonRegion_data(); + void emptyPolygonRegion(); + + void intersects_region_data(); + void intersects_region(); + void intersects_rect_data(); + void intersects_rect(); + void contains_point(); + + void operator_plus_data(); + void operator_plus(); + void operator_minus_data(); + void operator_minus(); + void operator_intersect_data(); + void operator_intersect(); + void operator_xor_data(); + void operator_xor(); + + void rectCount_data(); + void rectCount(); + + void isEmpty_data(); + void isEmpty(); +#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL) + void clipRectangles(); +#endif + + void regionFromPath(); + + void regionToPath_data(); + void regionToPath(); +}; + +Q_DECLARE_METATYPE(QPolygon) +Q_DECLARE_METATYPE(QVector<QRect>) +Q_DECLARE_METATYPE(QRegion) + +tst_QRegion::tst_QRegion() +{ +} + +void tst_QRegion::boundingRect() +{ + { + QRect rect; + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + { + QRect rect( 10, -20, 30, 40 ); + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + { + QRect rect(15,25,10,10); + QRegion region( rect ); + QCOMPARE( region.boundingRect(), rect ); + } + +} + +void tst_QRegion::rects() +{ + { + QRect rect; + QRegion region( rect ); + QVERIFY( region.isEmpty() ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRect rect( 10, -20, 30, 40 ); + QRegion region( rect ); + QCOMPARE( region.rects().count(), 1 ); + QCOMPARE( region.rects()[0], rect ); + } + { + QRect r( QPoint(10, 10), QPoint(40, 40) ); + QRegion region( r ); + QVERIFY( region.contains( QPoint(10,10) ) ); + QVERIFY( region.contains( QPoint(20,40) ) ); + QVERIFY( region.contains( QPoint(40,20) ) ); + QVERIFY( !region.contains( QPoint(20,41) ) ); + QVERIFY( !region.contains( QPoint(41,20) ) ); + } + { + QRect r( 10, 10, 30, 30 ); + QRegion region( r ); + QVERIFY( region.contains( QPoint(10,10) ) ); + QVERIFY( region.contains( QPoint(20,39) ) ); + QVERIFY( region.contains( QPoint(39,20) ) ); + QVERIFY( !region.contains( QPoint(20,40) ) ); + QVERIFY( !region.contains( QPoint(40,20) ) ); + } +} + +void tst_QRegion::swap() +{ + QRegion r1(QRect( 0, 0,10,10)); + QRegion r2(QRect(10,10,10,10)); + r1.swap(r2); + QCOMPARE(r1.rects().front(), QRect(10,10,10,10)); + QCOMPARE(r2.rects().front(), QRect( 0, 0,10,10)); +} + +void tst_QRegion::setRects() +{ + { + QRegion region; + region.setRects( 0, 0 ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRegion region; + QRect rect; + region.setRects( &rect, 0 ); + QVERIFY(region.isEmpty()); + QVERIFY(region == QRegion()); + QVERIFY(!region.boundingRect().isValid()); + QVERIFY(region.rects().isEmpty()); + } + { + QRegion region; + QRect rect; + region.setRects( &rect, 1 ); + QVERIFY( !region.boundingRect().isValid() ); + QVERIFY( region.rects().isEmpty() ); + } + { + QRegion region; + QRect rect( 10, -20, 30, 40 ); + region.setRects( &rect, 1 ); + QCOMPARE( region.rects().count(), 1 ); + QCOMPARE( region.rects()[0], rect ); + } +} + +void tst_QRegion::ellipseRegion() +{ + QRegion region(0, 0, 100, 100, QRegion::Ellipse); + + // These should not be inside the circe + QVERIFY(!region.contains(QPoint(13, 13))); + QVERIFY(!region.contains(QPoint(13, 86))); + QVERIFY(!region.contains(QPoint(86, 13))); + QVERIFY(!region.contains(QPoint(86, 86))); + + // These should be inside + QVERIFY(region.contains(QPoint(16, 16))); + QVERIFY(region.contains(QPoint(16, 83))); + QVERIFY(region.contains(QPoint(83, 16))); + QVERIFY(region.contains(QPoint(83, 83))); + + // ..a.. + // .. .. + // . . + // . . + // b c + // . . + // . . + // .. .. + // ..d.. + QVERIFY(region.contains(QPoint(50, 0))); // Mid-top (a) + QVERIFY(region.contains(QPoint(0, 50))); // Mid-left (b) + QVERIFY(region.contains(QPoint(99, 50))); // Mid-right (c) + QVERIFY(region.contains(QPoint(50, 99))); // Mid-bottom (d) + + QRect bounds = region.boundingRect(); + QCOMPARE(bounds.x(), 0); + QCOMPARE(bounds.y(), 0); + QCOMPARE(bounds.width(), 100); + QCOMPARE(bounds.height(), 100); +} + +void tst_QRegion::polygonRegion() +{ + QPolygon pa; + { + QRegion region ( pa ); + QVERIFY( region.isEmpty() ); + } + { + pa.setPoints( 8, 10, 10, // a____________b + 40, 10, // | | + 40, 20, // |___ ___| + 30, 20, // | | + 30, 40, // | | + 20, 40, // | | + 20, 20, // |____c + 10, 20 ); + + QRegion region ( pa ); + QVERIFY( !region.isEmpty() ); + + // These should not be inside the circle + QVERIFY( !region.contains( QPoint( 9, 9 ) ) ); + QVERIFY( !region.contains( QPoint( 30, 41 ) ) ); + QVERIFY( !region.contains( QPoint( 41, 10 ) ) ); + QVERIFY( !region.contains( QPoint( 31, 21 ) ) ); + + // These should be inside + QVERIFY( region.contains( QPoint( 10, 10 ) ) ); // Upper-left (a) + + } +} + +void tst_QRegion::emptyPolygonRegion_data() +{ + QTest::addColumn<QPolygon>("pa"); + QTest::addColumn<bool>("isEmpty"); + QTest::addColumn<int>("numRects"); + QTest::addColumn<QVector<QRect> >("rects"); + + QPolygon pa; + + + QTest::newRow("no points") << pa << true << 0 << QVector<QRect>(); + pa = QPolygon() << QPoint(10,10); + QTest::newRow("one point") << pa << true << 0 << QVector<QRect>(); + pa = QPolygon() << QPoint(10,10) << QPoint(10,20); + QTest::newRow("two points, horizontal") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,10); + QTest::newRow("two points, vertical") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(20,20); + QTest::newRow("two points, diagonal") << pa << true << 0 << QVector<QRect>(); + + pa = QPolygon() << QPoint(10,10) << QPoint(15,15) << QPoint(10,15) << QPoint(10, 10) ; + QVector<QRect> v; + v << QRect(10,11,1, 1) << QRect(10,12,2,1) << QRect(10,13,3,1) << QRect(10,14,4,1); + QTest::newRow("triangle") << pa << false << 4 << v; + + v.clear(); + v << QRect(10,10,10,10); + + QTest::newRow("rectangle") << QPolygon(QRect(10,10,10,10)) << false << 1 << v; + +} + +void tst_QRegion::emptyPolygonRegion() +{ + QFETCH(QPolygon, pa); + + QRegion r(pa); + QTEST(r.isEmpty(), "isEmpty"); + QTEST(r.rects().count(), "numRects"); + QTEST(r.rects(), "rects"); +} + + +static const char *circle_xpm[] = { + "20 20 2 1", + " c #FFFFFF", + ". c #000000", + " ...... ", + " .......... ", + " .............. ", + " ................ ", + " ................ ", + " .................. ", + " .................. ", + "....................", + "....................", + "....................", + "....................", + "....................", + "....................", + " .................. ", + " .................. ", + " ................ ", + " ................ ", + " .............. ", + " .......... ", + " ...... " +}; + +void tst_QRegion::bitmapRegion() +{ + QBitmap circle; + { + QRegion region( circle ); + QVERIFY( region.isEmpty() ); + } + { + circle = QPixmap( circle_xpm ); + QRegion region( circle ); + + //// These should not be inside the circe + QVERIFY( !region.contains( QPoint( 2, 2 ) ) ); + QVERIFY( !region.contains( QPoint( 2, 17 ) ) ); + QVERIFY( !region.contains( QPoint( 17, 2 ) ) ); + QVERIFY( !region.contains( QPoint( 17, 17 ) ) ); + + //// These should be inside + QVERIFY( region.contains( QPoint( 3, 3 ) ) ); + QVERIFY( region.contains( QPoint( 3, 16 ) ) ); + QVERIFY( region.contains( QPoint( 16, 3 ) ) ); + QVERIFY( region.contains( QPoint( 16, 16 ) ) ); + + QVERIFY( region.contains( QPoint( 0, 10 ) ) ); // Mid-left + QVERIFY( region.contains( QPoint( 10, 0 ) ) ); // Mid-top + QVERIFY( region.contains( QPoint( 19, 10 ) ) ); // Mid-right + QVERIFY( region.contains( QPoint( 10, 19 ) ) ); // Mid-bottom + } +} + +void tst_QRegion::intersected_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<bool>("intersects"); + // QTest::addColumn<QRegion>("intersected"); + + QPolygon ps1(8); + QPolygon ps2(8); + ps1.putPoints(0,8, 20,20, 50,20, 50,100, 70,100, 70,20, 120,20, 120,200, 20, 200); + ps2.putPoints(0,8, 100,150, 140,150, 140,160, 160,160, 160,150, 200,150, 200,180, 100,180); + QTest::newRow("task30716") << QRegion(ps1) << QRegion(ps2) << true; +} + +void tst_QRegion::intersected() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(bool, intersects); + + QRegion interReg = r1.intersected(r2); + QVERIFY(interReg.isEmpty() != intersects); + // Need a way to test the intersected QRegion is right +} + +void tst_QRegion::intersects_region_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<bool>("intersects"); + + QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200) + << QRegion(200, 200, 200, 200) + << true; + + QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200) + << QRegion(400, 400, 200, 200) + << false; + + QTest::newRow("ellipse overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRegion(200, 200, 200, 200, QRegion::Ellipse) + << true; + + QTest::newRow("ellipse not overlap ellipse") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRegion(400, 400, 200, 200, QRegion::Ellipse) + << false; +} + +void tst_QRegion::intersects_region() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(bool, intersects); + QCOMPARE(r1.intersects(r2), intersects); +} + + +void tst_QRegion::intersects_rect_data() +{ + QTest::addColumn<QRegion>("region"); + QTest::addColumn<QRect>("rect"); + QTest::addColumn<bool>("intersects"); + + QTest::newRow("rect overlap rect") << QRegion(100, 100, 200, 200) + << QRect(200, 200, 200, 200) + << true; + + QTest::newRow("rect not overlap rect") << QRegion(100, 100, 200, 200) + << QRect(400, 400, 200, 200) + << false; + + QTest::newRow("ellipse overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRect(200, 200, 200, 200) + << true; + + QTest::newRow("ellipse not overlap rect") << QRegion(100, 100, 200, 200, QRegion::Ellipse) + << QRect(400, 400, 200, 200) + << false; +} + +void tst_QRegion::intersects_rect() +{ + QFETCH(QRegion, region); + QFETCH(QRect, rect); + QFETCH(bool, intersects); + QCOMPARE(region.intersects(rect), intersects); +} + +void tst_QRegion::contains_point() +{ + QCOMPARE(QRegion().contains(QPoint(1,1)),false); + QCOMPARE(QRegion(0,0,2,2).contains(QPoint(1,1)),true); +} + +void tst_QRegion::operator_plus_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(QRect(10, 10, 10, 10)); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion expected; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("non overlapping") << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10) + << expected; + + rects.clear(); + rects << QRect(50, 0, 50, 2); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("adjacent y-rects") << QRegion(50, 0, 50, 1) + << QRegion(50, 1, 50, 1) + << expected; + + rects.clear(); + rects << QRect(50, 0, 2, 1); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("adjacent x-rects") << QRegion(50, 0, 1, 1) + << QRegion(51, 0, 1, 1) + << expected; + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10); + QRegion r1; + r1.setRects(rects.constData(), rects.size()); + QTest::newRow("double merge") << r1 << QRegion(15, 20, 5, 10) + << QRegion(10, 10, 10, 20); + rects.clear(); + rects << QRect(15, 10, 5, 10) << QRect(10, 20, 10, 10); + r1.setRects(rects.constData(), rects.size()); + QTest::newRow("double merge 2") << r1 << QRegion(10, 10, 5, 10) + << QRegion(10, 10, 10, 20); + QTest::newRow("overlapping x") << QRegion(10, 10, 10, 10) + << QRegion(15, 10, 10, 10) + << QRegion(10, 10, 15, 10); + QTest::newRow("overlapping y") << QRegion(10, 10, 10, 10) + << QRegion(10, 15, 10, 10) + << QRegion(10, 10, 10, 15); + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 5, 10); + r1.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(15, 20, 5, 10) << QRect(10, 30, 10, 10); + QRegion r2; + r2.setRects(rects.constData(), rects.size()); + QTest::newRow("triple merge") << r1 << r2 + << QRegion(10, 10, 10, 30); + + rects.clear(); + rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10); + r1.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(15, 20, 10, 10); + r2.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(10, 10, 4, 10) << QRect(15, 10, 10, 10) + << QRect(15, 20, 10, 10); + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("don't merge y") << r1 << r2 << expected; + + QTest::newRow("equal 1") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("equal 2") << expected << expected << expected; +} + +void tst_QRegion::operator_plus() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(QRegion, expected); + + if (r1 + r2 != expected) { + qDebug() << "r1 + r2" << (r1 + r2); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 + r2, expected); + if (r2.rectCount() == 1) { + if (r1 + r2.boundingRect() != expected) { + qDebug() << "r1 + QRect(r2)" << (r1 + r2.boundingRect()); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 + r2.boundingRect(), expected); + } + + if (r2 + r1 != expected) { + qDebug() << "r2 + r1" << (r2 + r1); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 + r1, expected); + if (r1.rectCount() == 1) { + if (r1 + r2.boundingRect() != expected) { + qDebug() << "r2 + QRect(r1)" << (r2 + r1.boundingRect()); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 + r1.boundingRect(), expected); + } + + QRegion result1 = r1; + result1 += r2; + if (result1 != expected) { + qDebug() << "r1 += r2" << result1; + qDebug() << "expected" << expected; + } + QCOMPARE(result1, expected); + if (r2.rectCount() == 1) { + result1 = r1; + result1 += r2.boundingRect(); + if (result1 != expected) { + qDebug() << "r1 += QRect(r2)" << result1; + qDebug() << "expected" << expected; + } + QCOMPARE(result1, expected); + } + + QRegion result2 = r2; + result2 += r1; + if (result2 != expected) { + qDebug() << "r2 += r1" << result2; + qDebug() << "expected" << expected; + } + QCOMPARE(result2, expected); + if (r1.rectCount() == 1) { + result2 = r2; + result2 += r1.boundingRect(); + if (result2 != expected) { + qDebug() << "r2 += QRect(r1)" << result2; + qDebug() << "expected" << expected; + } + QCOMPARE(result2, expected); + } +} + +void tst_QRegion::operator_minus_data() +{ + QTest::addColumn<QRegion>("dest"); + QTest::addColumn<QRegion>("subtract"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10); + + rects.clear(); + rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10); + dest.setRects(rects.constData(), rects.size()); + + QRegion minus; + rects.clear(); + rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12); + minus.setRects(rects.constData(), rects.size()); + QTest::newRow("empty 3") << dest << minus << QRegion(); +} + +void tst_QRegion::operator_minus() +{ + QFETCH(QRegion, dest); + QFETCH(QRegion, subtract); + QFETCH(QRegion, expected); + + if (dest - subtract != expected) { + qDebug() << "dest - subtract" << (dest - subtract); + qDebug() << "expected" << expected; + }; + QCOMPARE(dest - subtract, expected); + + dest -= subtract; + + if (dest != expected) { + qDebug() << "dest" << dest; + qDebug() << "expected" << expected; + }; + QCOMPARE(dest, expected); +} + +void tst_QRegion::operator_intersect_data() +{ + QTest::addColumn<QRegion>("r1"); + QTest::addColumn<QRegion>("r2"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(22, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 10); + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 15, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("merge 1") << dest + << QRegion(10, 10, 10, 20) + << QRegion(10, 10, 10, 20); + + rects.clear(); + rects << QRect(11, 11, 218, 117) << QRect(11, 128, 218, 27) + << QRect(264, 128, 122, 27) << QRect(11, 155, 218, 43) + << QRect(11, 198, 218, 27) << QRect(264, 198, 122, 27) + << QRect(11, 225, 218, 221); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("merge 2") << dest << QRegion(11, 11, 218, 458) + << QRegion(11, 11, 218, 435); + + rects.clear(); + rects << QRect(0, 0, 10, 10) << QRect(20, 0, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("empty 3") << dest << QRegion(11, 0, 5, 5) << QRegion(); + + QTest::newRow("extents check") << dest << QRegion(0, 0, 15, 15) + << QRegion(0, 0, 10, 10); + + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10) + << QRect(30, 20, 10, 10) << QRect(10, 30, 10, 10); + dest.setRects(rects.constData(), rects.size()); + rects.clear(); + rects << QRect(10, 10, 10, 10) << QRect(10, 20, 10, 10) + << QRect(30, 20, 10, 10); + QRegion expected; + expected.setRects(rects.constData(), rects.size()); + QTest::newRow("dont merge") << dest << QRegion(0, 0, 100, 30) + << expected; +} + +void tst_QRegion::operator_intersect() +{ + QFETCH(QRegion, r1); + QFETCH(QRegion, r2); + QFETCH(QRegion, expected); + + if ((r1 & r2) != expected) { + qDebug() << "r1 & r2" << (r1 & r2); + qDebug() << "expected" << expected; + } + QCOMPARE(r1 & r2, expected); + + if ((r2 & r1) != expected) { + qDebug() << "r2 & r1" << (r2 & r1); + qDebug() << "expected" << expected; + } + QCOMPARE(r2 & r1, expected); + + r1 &= r2; + QCOMPARE(r1, expected); +} + +void tst_QRegion::operator_xor_data() +{ + QTest::addColumn<QRegion>("dest"); + QTest::addColumn<QRegion>("arg"); + QTest::addColumn<QRegion>("expected"); + + QTest::newRow("empty 0") << QRegion() << QRegion() << QRegion(); + QTest::newRow("empty 1") << QRegion() << QRegion(QRect(10, 10, 10, 10)) + << QRegion(QRect(10, 10, 10, 10)); + QTest::newRow("empty 2") << QRegion(QRect(10, 10, 10, 10)) << QRegion() + << QRegion(QRect(10, 10, 10, 10)); + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + QTest::newRow("simple 1") << dest + << QRegion(22, 10, 10, 10) + << QRegion(10, 10, 10, 10); + QTest::newRow("simple 2") << dest + << QRegion(10, 10, 10, 10) + << QRegion(22, 10, 10, 10); + QTest::newRow("simple 3") << dest << dest << QRegion(); + QTest::newRow("simple 4") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 5, 10) + << QRegion(15, 10, 5, 10); + QTest::newRow("simple 5") << QRegion(10, 10, 10, 10) + << QRegion(10, 10, 10, 5) + << QRegion(10, 15, 10, 5); + + const QRegion rgnA(0, 0, 100, 100); + const QRegion rgnB(0, 0, 10, 10); + + QTest::newRow("simple 6") << rgnA + << rgnA - rgnB + << rgnB; + + QTest::newRow("simple 7") << rgnB + << rgnA + << rgnA - rgnB; +} + +void tst_QRegion::operator_xor() +{ + QFETCH(QRegion, dest); + QFETCH(QRegion, arg); + QFETCH(QRegion, expected); + + QCOMPARE(dest ^ arg, expected); + QCOMPARE(dest.xored(arg), expected); + + dest ^= arg; + QCOMPARE(dest, expected); +} + +void tst_QRegion::rectCount_data() +{ + QTest::addColumn<QRegion>("region"); + QTest::addColumn<int>("expected"); + + QTest::newRow("empty") << QRegion() << 0; + QTest::newRow("rect") << QRegion(10, 10, 10, 10) << 1; + + QRegion dest; + QVector<QRect> rects; + rects << QRect(10, 10, 10, 10) << QRect(22, 10, 10, 10); + dest.setRects(rects.constData(), rects.size()); + + QTest::newRow("2 rects") << dest << rects.size(); +} + +void tst_QRegion::rectCount() +{ + QFETCH(QRegion, region); + QFETCH(int, expected); + + QCOMPARE(region.rectCount(), expected); +} + +void tst_QRegion::isEmpty_data() +{ + QTest::addColumn<QRegion>("region"); + + QTest::newRow("QRegion") << QRegion(); + + QVector<QRect> rects; + rects << QRect(0, 0, 10, 10) << QRect(15, 0, 10, 10); + QRegion r1; + r1.setRects(rects.constData(), rects.size()); + + QRegion r2; + rects.clear(); + rects << QRect(0, 0, 12, 12) << QRect(15, 0, 12, 12); + r2.setRects(rects.constData(), rects.size()); + QTest::newRow("minus") << (r1 - r2); +} + +void tst_QRegion::isEmpty() +{ + QFETCH(QRegion, region); + + QVERIFY(region.isEmpty()); + QCOMPARE(region, QRegion()); + QCOMPARE(region.rectCount(), 0); + QCOMPARE(region.boundingRect(), QRect()); + QVERIFY(region.rects().isEmpty()); +} + +#if defined(Q_WS_X11) && defined(QT_BUILD_INTERNAL) +void tst_QRegion::clipRectangles() +{ + QRegion region(30, 30, 30, 30); + int num = 0; + qt_getClipRects(region, num); + QCOMPARE(num, 1); + + region += QRegion(10, 10, 10, 10); + XRectangle *rects2 = static_cast<XRectangle *>(qt_getClipRects(region, num)); + QCOMPARE(num, 2); + + // Here's the important part (Y-sorted): + QCOMPARE(int(rects2[0].y), 10); + QCOMPARE(int(rects2[1].y), 30); +} +#endif + +void tst_QRegion::regionFromPath() +{ + { + QPainterPath path; + path.addRect(0, 0, 10, 10); + path.addRect(0, 100, 100, 1000); + + QRegion rgn(path.toFillPolygon().toPolygon()); + QCOMPARE(rgn.rects().size(), 2); + QCOMPARE(rgn.rects().at(0), QRect(0, 0, 10, 10)); + QCOMPARE(rgn.rects().at(1), QRect(0, 100, 100, 1000)); + + QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 1100)); + } + + { + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(10, 10, 80, 80); + + QRegion rgn(path.toFillPolygon().toPolygon()); + QCOMPARE(rgn.rects().size(), 4); + + QCOMPARE(rgn.rects().at(0), QRect(0, 0, 100, 10)); + QCOMPARE(rgn.rects().at(1), QRect(0, 10, 10, 80)); + QCOMPARE(rgn.rects().at(2), QRect(90, 10, 10, 80)); + QCOMPARE(rgn.rects().at(3), QRect(0, 90, 100, 10)); + + QCOMPARE(rgn.boundingRect(), QRect(0, 0, 100, 100)); + } +} + +Q_DECLARE_METATYPE(QPainterPath) + +void tst_QRegion::regionToPath_data() +{ + QTest::addColumn<QPainterPath>("path"); + { + QPainterPath path; + path.addRect(QRect(0, 0, 10, 10)); + + QTest::newRow("Rectangle") << path; + } + + { + QPainterPath path; + path.addRect(QRect(0, 0, 10, 10)); + path.addRect(QRect(20, 0, 10, 10)); + + QTest::newRow("Two rects") << path; + } + + { + QPainterPath path; + path.addEllipse(QRect(0, 0, 10, 10)); + + QTest::newRow("Ellipse") << path; + } + + { + QPainterPath path; + path.addRect(QRect(0, 0, 3, 8)); + path.addRect(QRect(6, 0, 3, 8)); + path.addRect(QRect(3, 3, 3, 2)); + path.addRect(QRect(12, 3, 3, 2)); + + QTest::newRow("H-dot") << path; + } + + { + QPainterPath path; + for (int y = 0; y <= 10; ++y) { + for (int x = 0; x <= 10; ++x) { + if (!(y & 1) || ((x ^ y) & 1)) + path.addRect(QRect(x, y, 1, 1)); + } + } + + QTest::newRow("Grid") << path; + } +} + +#ifdef QT_BUILD_INTERNAL +QT_BEGIN_NAMESPACE +extern QPainterPath qt_regionToPath(const QRegion ®ion); +QT_END_NAMESPACE +#endif + +void tst_QRegion::regionToPath() +{ +#ifdef QT_BUILD_INTERNAL + + QFETCH(QPainterPath, path); + + for (int i = 0; i < 360; i += 10) { + + QTransform transform; + transform.scale(5, 5); + transform.rotate(i); + + QPainterPath mapped = transform.map(path); + QRegion region(mapped.toFillPolygon().toPolygon()); + + QPainterPath a; + a.addRegion(region); + + QPainterPath b = qt_regionToPath(region); + + QRect r = a.boundingRect().toAlignedRect(); + QImage ia(r.size(), QImage::Format_RGB32); + ia.fill(0xffffffff); + QImage ib = ia; + + QPainter p(&ia); + p.translate(-r.x(), -r.y()); + p.fillPath(a, Qt::red); + p.end(); + p.begin(&ib); + p.translate(-r.x(), -r.y()); + p.fillPath(b, Qt::red); + p.end(); + + QCOMPARE(ia, ib); + QCOMPARE(a.boundingRect(), b.boundingRect()); + } +#endif +} + +QTEST_MAIN(tst_QRegion) +#include "tst_qregion.moc" diff --git a/tests/auto/gui/painting/qtransform/.gitignore b/tests/auto/gui/painting/qtransform/.gitignore new file mode 100644 index 0000000000..f1da0161e7 --- /dev/null +++ b/tests/auto/gui/painting/qtransform/.gitignore @@ -0,0 +1 @@ +tst_qtransform diff --git a/tests/auto/gui/painting/qtransform/qtransform.pro b/tests/auto/gui/painting/qtransform/qtransform.pro new file mode 100644 index 0000000000..92bef8ce38 --- /dev/null +++ b/tests/auto/gui/painting/qtransform/qtransform.pro @@ -0,0 +1,7 @@ +load(qttest_p4) +HEADERS += +SOURCES += tst_qtransform.cpp + +unix:!mac:!symbian:LIBS+=-lm + + diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp new file mode 100644 index 0000000000..f8319c9e13 --- /dev/null +++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp @@ -0,0 +1,807 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include "qtransform.h" +#include <math.h> +#include <qpolygon.h> +#include <qdebug.h> + +Q_DECLARE_METATYPE(QRect) + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QTransform : public QObject +{ + Q_OBJECT + +public: + tst_QTransform(); + virtual ~tst_QTransform(); + + +public slots: + void init(); + void cleanup(); +private slots: + void mapRect_data(); + void operator_star_qrect_data(); + void mapToPolygon_data(); + void mapRect(); + void operator_star_qrect(); + void assignments(); + void mapToPolygon(); + void translate(); + void scale(); + void matrix(); + void testOffset(); + void types(); + void scalarOps(); + void transform(); + void mapEmptyPath(); + void boundingRect(); + void controlPointRect(); + void inverted_data(); + void inverted(); + void projectivePathMapping(); + void mapInt(); + void mapPathWithPoint(); + +private: + void mapping_data(); +}; + +Q_DECLARE_METATYPE(QTransform) +Q_DECLARE_METATYPE(QPolygon) + +tst_QTransform::tst_QTransform() +{ +} + +tst_QTransform::~tst_QTransform() +{ +} + +void tst_QTransform::init() +{ + // No initialisation is required +} + +void tst_QTransform::cleanup() +{ + // No cleanup is required. +} + +#if defined(Q_OS_WIN) && !defined(M_PI) +#define M_PI 3.14159265897932384626433832795f +#endif + +void tst_QTransform::mapRect_data() +{ + mapping_data(); + + // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here. + qreal deg = -45; + QTest::newRow( "rot 45 a" ) + << QTransform().rotate(deg) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( 0, -7, 14, 14 ) ); + QTest::newRow( "rot 45 b" ) + << QTransform().rotate(deg) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 21, -14, 50, 49 ) ); + QTest::newRow( "rot 45 c" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( 0, -71, 141, 142 ) ); + QTest::newRow( "rot 45 d" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 212, -141, 495, 495 ) ); + + deg = 45; + QTest::newRow( "rot -45 a" ) + << QTransform().rotate(deg) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( -7, 0, 14, 14 ) ); + QTest::newRow( "rot -45 b" ) + << QTransform().rotate(deg) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -35, 21, 49, 50 ) ); + QTest::newRow( "rot -45 c" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( -71, 0, 142, 141 ) ); + QTest::newRow( "rot -45 d" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -354, 212, 495, 495 ) ); +} + +void tst_QTransform::operator_star_qrect_data() +{ + mapping_data(); +} + +void tst_QTransform::mapToPolygon_data() +{ + mapping_data(); +} + +void tst_QTransform::mapping_data() +{ + //create the testtable instance and define the elements + QTest::addColumn<QTransform>("matrix"); + QTest::addColumn<QRect>("src"); + QTest::addColumn<QPolygon>("res"); + + //next we fill it with data + + // identity + QTest::newRow( "identity" ) + << QTransform() + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 10, 20, 30, 40 ) ); + // scaling + QTest::newRow( "scale 0" ) + << QTransform().scale(2, 2) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 20, 40, 60, 80 ) ); + QTest::newRow( "scale 1" ) + << QTransform().scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 100, 200, 300, 400 ) ); + // mirroring + QTest::newRow( "mirror 0" ) + << QTransform().scale(-1, 1) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -40, 20, 30, 40 ) ); + QTest::newRow( "mirror 1" ) + << QTransform().scale(1, -1) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 10, -60, 30, 40 ) ); + QTest::newRow( "mirror 2" ) + << QTransform().scale(-1, -1) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -40, -60, 30, 40 ) ); + QTest::newRow( "mirror 3" ) + << QTransform().scale(-2, -2) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -80, -120, 60, 80 ) ); + QTest::newRow( "mirror 4" ) + << QTransform().scale(-10, -10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -400, -600, 300, 400 ) ); + QTest::newRow( "mirror 5" ) + << QTransform().scale(-1, 1) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -30, 0, 30, 40 ) ); + QTest::newRow( "mirror 6" ) + << QTransform().scale(1, -1) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -40, 30, 40 ) ); + QTest::newRow( "mirror 7" ) + << QTransform().scale(-1, -1) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -30, -40, 30, 40 ) ); + QTest::newRow( "mirror 8" ) + << QTransform().scale(-2, -2) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -60, -80, 60, 80 ) ); + QTest::newRow( "mirror 9" ) + << QTransform().scale(-10, -10) << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -300, -400, 300, 400 ) ); + + // rotations + float deg = 0.; + QTest::newRow( "rot 0 a" ) + << QTransform().rotate(deg) + << QRect( 0, 0, 30, 40 ) + << QPolygon ( QRect( 0, 0, 30, 40 ) ); + deg = 0.00001f; + QTest::newRow( "rot 0 b" ) + << QTransform().rotate(deg) + << QRect( 0, 0, 30, 40 ) + << QPolygon ( QRect( 0, 0, 30, 40 ) ); + deg = 0.; + QTest::newRow( "rot 0 c" ) + << QTransform().rotate(deg) + << QRect( 10, 20, 30, 40 ) + << QPolygon ( QRect( 10, 20, 30, 40 ) ); + deg = 0.00001f; + QTest::newRow( "rot 0 d" ) + << QTransform().rotate(deg) + << QRect( 10, 20, 30, 40 ) + << QPolygon ( QRect( 10, 20, 30, 40 ) ); + + // rotations + deg = -90.f; + QTest::newRow( "rotscale 90 a" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -300, 400, 300 ) ); + deg = -90.00001f; + QTest::newRow( "rotscale 90 b" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -300, 400, 300 ) ); + deg = -90.f; + QTest::newRow( "rotscale 90 c" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 200, -400, 400, 300 ) ); + deg = -90.00001f; + QTest::newRow( "rotscale 90 d" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 200, -400, 400, 300 ) ); + + deg = 180.f; + QTest::newRow( "rotscale 180 a" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -300, -400, 300, 400 ) ); + deg = 180.000001f; + QTest::newRow( "rotscale 180 b" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -300, -400, 300, 400 ) ); + deg = 180.f; + QTest::newRow( "rotscale 180 c" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -400, -600, 300, 400 ) ); + deg = 180.000001f; + QTest::newRow( "rotscale 180 d" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -400, -600, 300, 400 ) ); + + deg = -270.f; + QTest::newRow( "rotscale 270 a" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -400, 0, 400, 300 ) ); + deg = -270.0000001f; + QTest::newRow( "rotscale 270 b" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -400, 0, 400, 300 ) ); + deg = -270.f; + QTest::newRow( "rotscale 270 c" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -600, 100, 400, 300 ) ); + deg = -270.000001f; + QTest::newRow( "rotscale 270 d" ) + << QTransform().rotate(deg).scale(10, 10) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -600, 100, 400, 300 ) ); +} + +void tst_QTransform::mapRect() +{ + QFETCH( QTransform, matrix ); + QFETCH( QRect, src ); + QFETCH( QPolygon, res ); + QRect mapped = matrix.mapRect(src); + QCOMPARE( mapped, res.boundingRect().adjusted(0, 0, -1, -1) ); + + QRectF r = matrix.mapRect(QRectF(src)); + QRect ir(r.topLeft().toPoint(), r.bottomRight().toPoint() - QPoint(1, 1)); + QCOMPARE( mapped, ir ); +} + +void tst_QTransform::operator_star_qrect() +{ +#if 0 + QFETCH( QTransform, matrix ); + QFETCH( QRect, src ); + QFETCH( QPolygon, res ); + + QCOMPARE( (matrix * src), QRegion(res) ); +#endif +} + +void tst_QTransform::assignments() +{ + QTransform m; + m.scale(2, 3); + m.rotate(45); + m.shear(4, 5); + + QTransform c1(m); + + QCOMPARE(m.m11(), c1.m11()); + QCOMPARE(m.m12(), c1.m12()); + QCOMPARE(m.m21(), c1.m21()); + QCOMPARE(m.m22(), c1.m22()); + QCOMPARE(m.dx(), c1.dx()); + QCOMPARE(m.dy(), c1.dy()); + + QTransform c2 = m; + QCOMPARE(m.m11(), c2.m11()); + QCOMPARE(m.m12(), c2.m12()); + QCOMPARE(m.m21(), c2.m21()); + QCOMPARE(m.m22(), c2.m22()); + QCOMPARE(m.dx(), c2.dx()); + QCOMPARE(m.dy(), c2.dy()); +} + + +void tst_QTransform::mapToPolygon() +{ + QFETCH( QTransform, matrix ); + QFETCH( QRect, src ); + QFETCH( QPolygon, res ); + + QPolygon poly = matrix.mapToPolygon(src); + + // don't care about starting point + bool equal = false; + for (int i = 0; i < poly.size(); ++i) { + QPolygon rot; + for (int j = i; j < poly.size(); ++j) + rot << poly[j]; + for (int j = 0; j < i; ++j) + rot << poly[j]; + if (rot == res) + equal = true; + } + + QVERIFY(equal); +} + + +void tst_QTransform::translate() +{ + QTransform m( 1, 2, 3, 4, 5, 6 ); + QTransform res2( m ); + QTransform res( 1, 2, 3, 4, 75, 106 ); + m.translate( 10, 20 ); + QVERIFY( m == res ); + m.translate( -10, -20 ); + QVERIFY( m == res2 ); + QVERIFY( QTransform::fromTranslate( 0, 0 ).type() == QTransform::TxNone ); + QVERIFY( QTransform::fromTranslate( 10, 0 ).type() == QTransform::TxTranslate ); + QVERIFY( QTransform::fromTranslate( -1, 5 ) == QTransform().translate( -1, 5 )); + QVERIFY( QTransform::fromTranslate( 0, 0 ) == QTransform()); +} + +void tst_QTransform::scale() +{ + QTransform m( 1, 2, 3, 4, 5, 6 ); + QTransform res2( m ); + QTransform res( 10, 20, 60, 80, 5, 6 ); + m.scale( 10, 20 ); + QVERIFY( m == res ); + m.scale( 1./10., 1./20. ); + QVERIFY( m == res2 ); + QVERIFY( QTransform::fromScale( 1, 1 ).type() == QTransform::TxNone ); + QVERIFY( QTransform::fromScale( 2, 4 ).type() == QTransform::TxScale ); + QVERIFY( QTransform::fromScale( 2, 4 ) == QTransform().scale( 2, 4 )); + QVERIFY( QTransform::fromScale( 1, 1 ) == QTransform()); +} + +void tst_QTransform::matrix() +{ + QMatrix mat1; + mat1.scale(0.3, 0.7); + mat1.translate(53.3, 94.4); + mat1.rotate(45); + + QMatrix mat2; + mat2.rotate(33); + mat2.scale(0.6, 0.6); + mat2.translate(13.333, 7.777); + + QTransform tran1(mat1); + QTransform tran2(mat2); + QTransform dummy; + dummy.setMatrix(mat1.m11(), mat1.m12(), 0, + mat1.m21(), mat1.m22(), 0, + mat1.dx(), mat1.dy(), 1); + + QVERIFY(tran1 == dummy); + QVERIFY(tran1.inverted() == dummy.inverted()); + QVERIFY(tran1.inverted() == QTransform(mat1.inverted())); + QVERIFY(tran2.inverted() == QTransform(mat2.inverted())); + + QMatrix mat3 = mat1 * mat2; + QTransform tran3 = tran1 * tran2; + QVERIFY(QTransform(mat3) == tran3); + + /* QMatrix::operator==() doesn't use qFuzzyCompare(), which + * on win32-g++ results in a failure. So we work around it by + * calling QTranform::operator==(), which performs a fuzzy compare. */ + QCOMPARE(QTransform(mat3), QTransform(tran3.toAffine())); + + QTransform tranInv = tran1.inverted(); + QMatrix matInv = mat1.inverted(); + + QRect rect(43, 70, 200, 200); + QPoint pt(43, 66); + QVERIFY(tranInv.map(pt) == matInv.map(pt)); + QVERIFY(tranInv.map(pt) == matInv.map(pt)); + + QPainterPath path; + path.moveTo(55, 60); + path.lineTo(110, 110); + path.quadTo(220, 50, 10, 20); + path.closeSubpath(); + QVERIFY(tranInv.map(path) == matInv.map(path)); +} + +void tst_QTransform::testOffset() +{ + QTransform trans; + const QMatrix &aff = trans.toAffine(); + QCOMPARE((void*)(&aff), (void*)(&trans)); +} + +void tst_QTransform::types() +{ + QTransform m1; + QCOMPARE(m1.type(), QTransform::TxNone); + + m1.translate(1.0f, 0.0f); + QCOMPARE(m1.type(), QTransform::TxTranslate); + QCOMPARE(m1.inverted().type(), QTransform::TxTranslate); + + m1.scale(1.0f, 2.0f); + QCOMPARE(m1.type(), QTransform::TxScale); + QCOMPARE(m1.inverted().type(), QTransform::TxScale); + + m1.rotate(45.0f); + QCOMPARE(m1.type(), QTransform::TxRotate); + QCOMPARE(m1.inverted().type(), QTransform::TxRotate); + + m1.shear(0.5f, 0.25f); + QCOMPARE(m1.type(), QTransform::TxShear); + QCOMPARE(m1.inverted().type(), QTransform::TxShear); + + m1.rotate(45.0f, Qt::XAxis); + QCOMPARE(m1.type(), QTransform::TxProject); + m1.shear(0.5f, 0.25f); + QCOMPARE(m1.type(), QTransform::TxProject); + m1.rotate(45.0f); + QCOMPARE(m1.type(), QTransform::TxProject); + m1.scale(1.0f, 2.0f); + QCOMPARE(m1.type(), QTransform::TxProject); + m1.translate(1.0f, 0.0f); + QCOMPARE(m1.type(), QTransform::TxProject); + + QTransform m2(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f); + + QCOMPARE(m2.type(), QTransform::TxTranslate); + QCOMPARE((m1 * m2).type(), QTransform::TxProject); + + m1 *= QTransform(); + QCOMPARE(m1.type(), QTransform::TxProject); + + m1 *= QTransform(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 1.0f); + QCOMPARE(m1.type(), QTransform::TxProject); + + m2.reset(); + QCOMPARE(m2.type(), QTransform::TxNone); + + m2.setMatrix(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxNone); + + m2 *= QTransform(); + QCOMPARE(m2.type(), QTransform::TxNone); + + m2.setMatrix(2.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxScale); + m2 *= QTransform(); + QCOMPARE(m2.type(), QTransform::TxScale); + + m2.setMatrix(0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxRotate); + m2 *= QTransform(); + QCOMPARE(m2.type(), QTransform::TxRotate); + + m2.setMatrix(1.0f, 0.0f, 0.5f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxProject); + m2 *= QTransform(); + QCOMPARE(m2.type(), QTransform::TxProject); + + m2.setMatrix(1.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxShear); + + m2 *= m2.inverted(); + QCOMPARE(m2.type(), QTransform::TxNone); + + m2.translate(5.0f, 5.0f); + m2.rotate(45.0f); + m2.rotate(-45.0f); + QCOMPARE(m2.type(), QTransform::TxTranslate); + + m2.scale(2.0f, 3.0f); + m2.shear(1.0f, 0.0f); + m2.shear(-1.0f, 0.0f); + QCOMPARE(m2.type(), QTransform::TxScale); + + m2 *= QTransform(1.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxShear); + + m2 *= QTransform(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 1.0f, 0.0f, 1.0f); + QCOMPARE(m2.type(), QTransform::TxShear); + + QTransform m3(1.8f, 0.0f, 0.0f, + 0.0f, 1.8f, 0.0f, + 0.0f, 0.0f, 1.0f); + + QCOMPARE(m3.type(), QTransform::TxScale); + m3.translate(5.0f, 5.0f); + QCOMPARE(m3.type(), QTransform::TxScale); + QCOMPARE(m3.inverted().type(), QTransform::TxScale); + + m3.setMatrix(1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 2.0f); + QCOMPARE(m3.type(), QTransform::TxProject); + + m3.setMatrix(0.0f, 2.0f, 0.0f, + 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 2.0f); + QCOMPARE(m3.type(), QTransform::TxProject); + + QTransform m4; + m4.scale(5, 5); + m4.translate(4, 2); + m4.rotate(45); + + QCOMPARE(m4.type(), QTransform::TxRotate); + + QTransform m5; + m5.scale(5, 5); + m5 = m5.adjoint() / m5.determinant(); + QCOMPARE(m5.type(), QTransform::TxScale); +} + + +void tst_QTransform::scalarOps() +{ + QTransform t; + QCOMPARE(t.m11(), 1.); + QCOMPARE(t.m33(), 1.); + QCOMPARE(t.m21(), 0.); + + t = QTransform() + 3; + QCOMPARE(t.m11(), 4.); + QCOMPARE(t.m33(), 4.); + QCOMPARE(t.m21(), 3.); + + t = t - 3; + QCOMPARE(t.m11(), 1.); + QCOMPARE(t.m33(), 1.); + QCOMPARE(t.m21(), 0.); + QCOMPARE(t.isIdentity(), true); + + t += 3; + t = t * 2; + QCOMPARE(t.m11(), 8.); + QCOMPARE(t.m33(), 8.); + QCOMPARE(t.m21(), 6.); +} + +void tst_QTransform::transform() +{ + QTransform t; + t.rotate(30, Qt::YAxis); + t.translate(15, 10); + t.scale(2, 2); + t.rotate(30); + t.shear(0.5, 0.5); + + QTransform a, b, c, d, e; + a.rotate(30, Qt::YAxis); + b.translate(15, 10); + c.scale(2, 2); + d.rotate(30); + e.shear(0.5, 0.5); + + QVERIFY(qFuzzyCompare(t, e * d * c * b * a)); +} + +void tst_QTransform::mapEmptyPath() +{ + QPainterPath path; + path.moveTo(10, 10); + path.lineTo(10, 10); + QCOMPARE(QTransform().map(path), path); +} + +void tst_QTransform::boundingRect() +{ + QPainterPath path; + path.moveTo(10, 10); + path.lineTo(10, 10); + QCOMPARE(path.boundingRect(), QRectF(10, 10, 0, 0)); +} + +void tst_QTransform::controlPointRect() +{ + QPainterPath path; + path.moveTo(10, 10); + path.lineTo(10, 10); + QCOMPARE(path.controlPointRect(), QRectF(10, 10, 0, 0)); +} + +void tst_QTransform::inverted_data() +{ + QTest::addColumn<QTransform>("matrix"); + + QTest::newRow("identity") + << QTransform(); + + QTest::newRow("TxTranslate") + << QTransform().translate(200, 10); + + QTest::newRow("TxScale") + << QTransform().scale(5, 2); + + QTest::newRow("TxTranslate TxScale") + << QTransform().translate(100, -10).scale(40, 2); + + QTest::newRow("TxScale TxTranslate") + << QTransform().scale(40, 2).translate(100, -10); + + QTest::newRow("TxRotate") + << QTransform().rotate(40, Qt::ZAxis); + + QTest::newRow("TxRotate TxScale") + << QTransform().rotate(60, Qt::ZAxis).scale(2, 0.25); + + QTest::newRow("TxScale TxRotate") + << QTransform().scale(2, 0.25).rotate(30, Qt::ZAxis); + + QTest::newRow("TxRotate TxScale TxTranslate") + << QTransform().rotate(60, Qt::ZAxis).scale(2, 0.25).translate(200, -3000); + + QTest::newRow("TxRotate TxTranslate TxScale") + << QTransform().rotate(60, Qt::ZAxis).translate(200, -3000).scale(19, 77); + + QTest::newRow("TxShear") + << QTransform().shear(10, 10); + + QTest::newRow("TxShear TxRotate") + << QTransform().shear(10, 10).rotate(45, Qt::ZAxis); + + QTest::newRow("TxShear TxRotate TxScale") + << QTransform().shear(10, 10).rotate(45, Qt::ZAxis).scale(19, 81); + + QTest::newRow("TxTranslate TxShear TxRotate TxScale") + << QTransform().translate(150, -1).shear(10, 10).rotate(45, Qt::ZAxis).scale(19, 81); + + const qreal s = 500000; + + QTransform big; + big.scale(s, s); + + QTest::newRow("big") << big; + + QTransform smallTransform; + smallTransform.scale(1/s, 1/s); + + QTest::newRow("small") << smallTransform; +} + +void tst_QTransform::inverted() +{ + if (sizeof(qreal) != sizeof(double)) + QSKIP("precision error if qreal is not double", SkipAll); + + QFETCH(QTransform, matrix); + + const QTransform inverted = matrix.inverted(); + + QVERIFY(matrix.isIdentity() == inverted.isIdentity()); + QVERIFY(matrix.type() == inverted.type()); + + QVERIFY((matrix * inverted).isIdentity()); + QVERIFY((inverted * matrix).isIdentity()); +} + +void tst_QTransform::projectivePathMapping() +{ + QPainterPath path; + path.addRect(-50, -50, 100, 100); + + const QRectF view(0, 0, 1024, 1024); + + QVERIFY(view.intersects(path.boundingRect())); + + for (int i = 0; i < 85; i += 5) { + QTransform transform; + transform.translate(512, 512); + transform.rotate(i, Qt::YAxis); + + const QPainterPath mapped = transform.map(path); + + QVERIFY(view.intersects(mapped.boundingRect())); + QVERIFY(transform.inverted().mapRect(view).intersects(path.boundingRect())); + } +} + +void tst_QTransform::mapInt() +{ + int x = 0; + int y = 0; + + QTransform::fromTranslate(10, 10).map(x, y, &x, &y); + + QCOMPARE(x, 10); + QCOMPARE(y, 10); +} + +void tst_QTransform::mapPathWithPoint() +{ + QPainterPath p(QPointF(10, 10)); + p = QTransform::fromTranslate(10, 10).map(p); + QCOMPARE(p.currentPosition(), QPointF(20, 20)); +} + +QTEST_APPLESS_MAIN(tst_QTransform) + + +#include "tst_qtransform.moc" diff --git a/tests/auto/gui/painting/qwmatrix/.gitignore b/tests/auto/gui/painting/qwmatrix/.gitignore new file mode 100644 index 0000000000..c983191769 --- /dev/null +++ b/tests/auto/gui/painting/qwmatrix/.gitignore @@ -0,0 +1 @@ +tst_qwmatrix diff --git a/tests/auto/gui/painting/qwmatrix/qwmatrix.pro b/tests/auto/gui/painting/qwmatrix/qwmatrix.pro new file mode 100644 index 0000000000..bab298bc93 --- /dev/null +++ b/tests/auto/gui/painting/qwmatrix/qwmatrix.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_qwmatrix.cpp + +unix:!mac:!symbian:LIBS+=-lm + + diff --git a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp new file mode 100644 index 0000000000..0e7372d9d8 --- /dev/null +++ b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp @@ -0,0 +1,436 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> +#include <qmatrix.h> +#include <math.h> +#include <qpolygon.h> + +Q_DECLARE_METATYPE(QRect) + +//TESTED_CLASS= +//TESTED_FILES=gui/painting/qmatrix.h gui/painting/qmatrix.cpp + +class tst_QWMatrix : public QObject +{ + Q_OBJECT + +public: + tst_QWMatrix(); + virtual ~tst_QWMatrix(); + + +public slots: + void init(); + void cleanup(); +private slots: + void mapRect_data(); + void operator_star_qrect_data(); + void mapToPolygon_data(); + void mapRect(); + void operator_star_qrect(); + void operator_star_qwmatrix(); + void assignments(); + void mapToPolygon(); + void translate(); + void scale(); + void mapPolygon(); + +private: + void mapping_data(); +}; + +Q_DECLARE_METATYPE(QMatrix) +Q_DECLARE_METATYPE(QPolygon) + +tst_QWMatrix::tst_QWMatrix() +{ +} + +tst_QWMatrix::~tst_QWMatrix() +{ +} + +void tst_QWMatrix::init() +{ + // No initialisation is required +} + +void tst_QWMatrix::cleanup() +{ + // No cleanup is required. +} + +void tst_QWMatrix::mapRect_data() +{ + mapping_data(); +} + +void tst_QWMatrix::operator_star_qrect_data() +{ + mapping_data(); +} + +void tst_QWMatrix::mapToPolygon_data() +{ + mapping_data(); +} + +void tst_QWMatrix::mapping_data() +{ + //create the testtable instance and define the elements + QTest::addColumn<QMatrix>("matrix"); + QTest::addColumn<QRect>("src"); + QTest::addColumn<QPolygon>("res"); + + //next we fill it with data + + // identity + QTest::newRow( "identity" ) << QMatrix( 1, 0, 0, 1, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 10, 20, 30, 40 ) ); + // scaling + QTest::newRow( "scale 0" ) << QMatrix( 2, 0, 0, 2, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 20, 40, 60, 80 ) ); + QTest::newRow( "scale 1" ) << QMatrix( 10, 0, 0, 10, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 100, 200, 300, 400 ) ); + // mirroring + QTest::newRow( "mirror 0" ) << QMatrix( -1, 0, 0, 1, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -40, 20, 30, 40 ) ); + QTest::newRow( "mirror 1" ) << QMatrix( 1, 0, 0, -1, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 10, -60, 30, 40 ) ); + QTest::newRow( "mirror 2" ) << QMatrix( -1, 0, 0, -1, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -40, -60, 30, 40 ) ); + QTest::newRow( "mirror 3" ) << QMatrix( -2, 0, 0, -2, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -80, -120, 60, 80 ) ); + QTest::newRow( "mirror 4" ) << QMatrix( -10, 0, 0, -10, 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -400, -600, 300, 400 ) ); + QTest::newRow( "mirror 5" ) << QMatrix( -1, 0, 0, 1, 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -30, 0, 30, 40 ) ); + QTest::newRow( "mirror 6" ) << QMatrix( 1, 0, 0, -1, 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -40, 30, 40 ) ); + QTest::newRow( "mirror 7" ) << QMatrix( -1, 0, 0, -1, 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -30, -40, 30, 40 ) ); + QTest::newRow( "mirror 8" ) << QMatrix( -2, 0, 0, -2, 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -60, -80, 60, 80 ) ); + QTest::newRow( "mirror 9" ) << QMatrix( -10, 0, 0, -10, 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -300, -400, 300, 400 ) ); + +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +#define M_PI 3.14159265897932384626433832795f +#endif + + // rotations + float deg = 0.; + QTest::newRow( "rot 0 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon ( QRect( 0, 0, 30, 40 ) ); + deg = 0.00001f; + QTest::newRow( "rot 0 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon ( QRect( 0, 0, 30, 40 ) ); + deg = 0.; + QTest::newRow( "rot 0 c" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon ( QRect( 10, 20, 30, 40 ) ); + deg = 0.00001f; + QTest::newRow( "rot 0 d" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon ( QRect( 10, 20, 30, 40 ) ); + +#if 0 + // rotations + deg = 90.; + QTest::newRow( "rotscale 90 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -299, 400, 300 ) ); + deg = 90.00001; + QTest::newRow( "rotscale 90 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( 0, -299, 400, 300 ) ); + deg = 90.; + QTest::newRow( "rotscale 90 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 200, -399, 400, 300 ) ); + deg = 90.00001; + QTest::newRow( "rotscale 90 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 200, -399, 400, 300 ) ); + + deg = 180.; + QTest::newRow( "rotscale 180 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -299, -399, 300, 400 ) ); + deg = 180.000001; + QTest::newRow( "rotscale 180 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -299, -399, 300, 400 ) ); + deg = 180.; + QTest::newRow( "rotscale 180 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -399, -599, 300, 400 ) ); + deg = 180.000001; + QTest::newRow( "rotscale 180 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -399, -599, 300, 400 ) ); + + deg = 270.; + QTest::newRow( "rotscale 270 a" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -399, 00, 400, 300 ) ); + deg = 270.0000001; + QTest::newRow( "rotscale 270 b" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 30, 40 ) + << QPolygon( QRect( -399, 00, 400, 300 ) ); + deg = 270.; + QTest::newRow( "rotscale 270 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -599, 100, 400, 300 ) ); + deg = 270.000001; + QTest::newRow( "rotscale 270 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -599, 100, 400, 300 ) ); + + // rotations that are not multiples of 90 degrees. mapRect returns the bounding rect here. + deg = 45; + QTest::newRow( "rot 45 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( 0, -7, 14, 14 ) ); + QTest::newRow( "rot 45 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 21, -14, 49, 49 ) ); + QTest::newRow( "rot 45 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( 0, -70, 141, 141 ) ); + QTest::newRow( "rot 45 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( 212, -141, 495, 495 ) ); + + deg = -45; + QTest::newRow( "rot -45 a" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( -7, 0, 14, 14 ) ); + QTest::newRow( "rot -45 b" ) << QMatrix( cos( M_PI*deg/180. ), -sin( M_PI*deg/180. ), + sin( M_PI*deg/180. ), cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -35, 21, 49, 49 ) ); + QTest::newRow( "rot -45 c" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 0, 0, 10, 10 ) + << QPolygon( QRect( -70, 0, 141, 141 ) ); + QTest::newRow( "rot -45 d" ) << QMatrix( 10*cos( M_PI*deg/180. ), -10*sin( M_PI*deg/180. ), + 10*sin( M_PI*deg/180. ), 10*cos( M_PI*deg/180. ), 0, 0 ) + << QRect( 10, 20, 30, 40 ) + << QPolygon( QRect( -353, 212, 495, 495 ) ); +#endif +} + +void tst_QWMatrix::mapRect() +{ + QFETCH( QMatrix, matrix ); + QFETCH( QRect, src ); +// qDebug( "got src: %d/%d (%d/%d), matrix=[ %f %f %f %f %f %f ]", +// src.x(), src.y(), src.width(), src.height(), +// matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), matrix.dx(), matrix.dy() ); + QTEST( QPolygon( matrix.mapRect(src) ), "res" ); +} + +void tst_QWMatrix::operator_star_qrect() +{ +#if 0 // QT_VERSION >= 0x030100 + QFETCH( QMatrix, matrix ); + QFETCH( QRect, src ); + QFETCH( QPolygon, res ); + + QCOMPARE( (matrix * src), QRegion(res) ); +#else + QSKIP( "Not tested with Qt versions < 3.1", SkipAll); +#endif +} + + +void tst_QWMatrix::operator_star_qwmatrix() +{ +#if 0 + // Left out until the matrix multiply operator behaves properly.. + QMatrix m1( 2, 3, 4, 5, 6, 7 ); + QMatrix m2( 3, 4, 5, 6, 7, 8 ); + + QMatrix result1x2( 21, 26, 37, 46, 44, 75 ); + QMatrix result2x1( 22, 29, 34, 45, 53, 80); + + QMatrix product12 = m1*m2; + QMatrix product21 = m2*m1; + + QVERIFY( product12==result1x2 ); + QVERIFY( product21==result2x1 ); +#else + QSKIP( "Not tested with Qt versions since the operator is broken..", + SkipAll ); +#endif +} + + +void tst_QWMatrix::assignments() +{ + QMatrix m; + m.scale(2, 3); + m.rotate(45); + m.shear(4, 5); + + QMatrix c1(m); + + QCOMPARE(m.m11(), c1.m11()); + QCOMPARE(m.m12(), c1.m12()); + QCOMPARE(m.m21(), c1.m21()); + QCOMPARE(m.m22(), c1.m22()); + QCOMPARE(m.dx(), c1.dx()); + QCOMPARE(m.dy(), c1.dy()); + + QMatrix c2 = m; + QCOMPARE(m.m11(), c2.m11()); + QCOMPARE(m.m12(), c2.m12()); + QCOMPARE(m.m21(), c2.m21()); + QCOMPARE(m.m22(), c2.m22()); + QCOMPARE(m.dx(), c2.dx()); + QCOMPARE(m.dy(), c2.dy()); +} + + +void tst_QWMatrix::mapToPolygon() +{ + QFETCH( QMatrix, matrix ); + QFETCH( QRect, src ); + QFETCH( QPolygon, res ); + + QCOMPARE( matrix.mapToPolygon( src ), res ); +} + + +void tst_QWMatrix::translate() +{ + QMatrix m( 1, 2, 3, 4, 5, 6 ); + QMatrix res2( m ); + QMatrix res( 1, 2, 3, 4, 75, 106 ); + m.translate( 10, 20 ); + QVERIFY( m == res ); + m.translate( -10, -20 ); + QVERIFY( m == res2 ); +} + +void tst_QWMatrix::scale() +{ + QMatrix m( 1, 2, 3, 4, 5, 6 ); + QMatrix res2( m ); + QMatrix res( 10, 20, 60, 80, 5, 6 ); + m.scale( 10, 20 ); + QVERIFY( m == res ); + m.scale( 1./10., 1./20. ); + QVERIFY( m == res2 ); +} + +void tst_QWMatrix::mapPolygon() +{ + QPolygon poly; + poly << QPoint(0, 0) << QPoint(1, 1) << QPoint(100, 1) << QPoint(1, 100) << QPoint(-1, -1) << QPoint(-1000, 1000); + + { + QMatrix m; + m.rotate(90); + + // rotating 90 degrees four times should result in original poly + QPolygon mapped = m.map(m.map(m.map(m.map(poly)))); + QCOMPARE(mapped, poly); + + QMatrix m2; + m2.scale(10, 10); + QMatrix m3; + m3.scale(0.1, 0.1); + + mapped = m3.map(m2.map(poly)); + QCOMPARE(mapped, poly); + } + + { + QMatrix m(1, 2, 3, 4, 5, 6); + + QPolygon mapped = m.map(poly); + for (int i = 0; i < mapped.size(); ++i) + QCOMPARE(mapped.at(i), m.map(poly.at(i))); + } +} + +QTEST_APPLESS_MAIN(tst_QWMatrix) +#include "tst_qwmatrix.moc" |