From bfb3c424abc7c839dc44de0e36024ede99ece736 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 14 Oct 2011 10:51:42 +0200 Subject: Rename Qt Quick-specific classes to QQuick* The QSG (SceneGraph) prefix is too generic for Qt Quick(2)-specific classes. All the classes and files in the declarative/items directory have been renamed. In particular, for classes that are currently public, the renaming is as follows: QSGView --> QQuickView QSGCanvas --> QQuickCanvas QSGItem --> QQuickItem QSGPaintedItem --> QQuickPaintedItem The header files have been renamed accordingly (e.g. qsgview.h --> qquickview.h). Change-Id: Iac937fff81db20bb639486a793c3aeb5230b038c Reviewed-by: Kent Hansen --- .../declarative/qquickimage/data/aspectratio.qml | 6 + tests/auto/declarative/qquickimage/data/big.jpeg | Bin 0 -> 1700081 bytes tests/auto/declarative/qquickimage/data/big256.png | Bin 0 -> 3566 bytes tests/auto/declarative/qquickimage/data/colors.png | Bin 0 -> 1655 bytes .../auto/declarative/qquickimage/data/colors1.png | Bin 0 -> 1655 bytes tests/auto/declarative/qquickimage/data/green.png | Bin 0 -> 314 bytes .../declarative/qquickimage/data/heart-win32.png | Bin 0 -> 12621 bytes tests/auto/declarative/qquickimage/data/heart.png | Bin 0 -> 12577 bytes tests/auto/declarative/qquickimage/data/heart.svg | 55 ++ .../qquickimage/data/heart200-win32.png | Bin 0 -> 8062 bytes .../auto/declarative/qquickimage/data/heart200.png | Bin 0 -> 8063 bytes .../auto/declarative/qquickimage/data/htiling.qml | 11 + tests/auto/declarative/qquickimage/data/mirror.qml | 11 + .../declarative/qquickimage/data/nullpixmap.qml | 6 + .../auto/declarative/qquickimage/data/pattern.png | Bin 0 -> 1371 bytes .../declarative/qquickimage/data/qtbug_16389.qml | 30 + tests/auto/declarative/qquickimage/data/rect.png | Bin 0 -> 171 bytes .../auto/declarative/qquickimage/data/vtiling.qml | 11 + tests/auto/declarative/qquickimage/qquickimage.pro | 13 + .../declarative/qquickimage/tst_qquickimage.cpp | 689 +++++++++++++++++++++ 20 files changed, 832 insertions(+) create mode 100644 tests/auto/declarative/qquickimage/data/aspectratio.qml create mode 100644 tests/auto/declarative/qquickimage/data/big.jpeg create mode 100644 tests/auto/declarative/qquickimage/data/big256.png create mode 100644 tests/auto/declarative/qquickimage/data/colors.png create mode 100644 tests/auto/declarative/qquickimage/data/colors1.png create mode 100644 tests/auto/declarative/qquickimage/data/green.png create mode 100644 tests/auto/declarative/qquickimage/data/heart-win32.png create mode 100644 tests/auto/declarative/qquickimage/data/heart.png create mode 100644 tests/auto/declarative/qquickimage/data/heart.svg create mode 100644 tests/auto/declarative/qquickimage/data/heart200-win32.png create mode 100644 tests/auto/declarative/qquickimage/data/heart200.png create mode 100644 tests/auto/declarative/qquickimage/data/htiling.qml create mode 100644 tests/auto/declarative/qquickimage/data/mirror.qml create mode 100644 tests/auto/declarative/qquickimage/data/nullpixmap.qml create mode 100644 tests/auto/declarative/qquickimage/data/pattern.png create mode 100644 tests/auto/declarative/qquickimage/data/qtbug_16389.qml create mode 100644 tests/auto/declarative/qquickimage/data/rect.png create mode 100644 tests/auto/declarative/qquickimage/data/vtiling.qml create mode 100644 tests/auto/declarative/qquickimage/qquickimage.pro create mode 100644 tests/auto/declarative/qquickimage/tst_qquickimage.cpp (limited to 'tests/auto/declarative/qquickimage') diff --git a/tests/auto/declarative/qquickimage/data/aspectratio.qml b/tests/auto/declarative/qquickimage/data/aspectratio.qml new file mode 100644 index 0000000000..b26f0e1f04 --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/aspectratio.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Image { + source: "heart.png" + fillMode: Image.PreserveAspectFit; +} diff --git a/tests/auto/declarative/qquickimage/data/big.jpeg b/tests/auto/declarative/qquickimage/data/big.jpeg new file mode 100644 index 0000000000..bed7bd65c3 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/big.jpeg differ diff --git a/tests/auto/declarative/qquickimage/data/big256.png b/tests/auto/declarative/qquickimage/data/big256.png new file mode 100644 index 0000000000..1dc1596d03 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/big256.png differ diff --git a/tests/auto/declarative/qquickimage/data/colors.png b/tests/auto/declarative/qquickimage/data/colors.png new file mode 100644 index 0000000000..dfb62f3d64 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/colors.png differ diff --git a/tests/auto/declarative/qquickimage/data/colors1.png b/tests/auto/declarative/qquickimage/data/colors1.png new file mode 100644 index 0000000000..dfb62f3d64 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/colors1.png differ diff --git a/tests/auto/declarative/qquickimage/data/green.png b/tests/auto/declarative/qquickimage/data/green.png new file mode 100644 index 0000000000..0a2e153ba1 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/green.png differ diff --git a/tests/auto/declarative/qquickimage/data/heart-win32.png b/tests/auto/declarative/qquickimage/data/heart-win32.png new file mode 100644 index 0000000000..351da13772 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/heart-win32.png differ diff --git a/tests/auto/declarative/qquickimage/data/heart.png b/tests/auto/declarative/qquickimage/data/heart.png new file mode 100644 index 0000000000..abe97fee4b Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/heart.png differ diff --git a/tests/auto/declarative/qquickimage/data/heart.svg b/tests/auto/declarative/qquickimage/data/heart.svg new file mode 100644 index 0000000000..8c982cd93c --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/heart.svg @@ -0,0 +1,55 @@ + + + + + +Heart Left-Highlight +This is a normal valentines day heart. + + +holiday +valentines + +valentine +hash(0x8a091c0) +hash(0x8a0916c) +signs_and_symbols +hash(0x8a091f0) +day + + + + +Jon Phillips + + + + +Jon Phillips + + + + +Jon Phillips + + + +image/svg+xml + + +en + + + + + + + + + + + + + + + diff --git a/tests/auto/declarative/qquickimage/data/heart200-win32.png b/tests/auto/declarative/qquickimage/data/heart200-win32.png new file mode 100644 index 0000000000..4976ff98ba Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/heart200-win32.png differ diff --git a/tests/auto/declarative/qquickimage/data/heart200.png b/tests/auto/declarative/qquickimage/data/heart200.png new file mode 100644 index 0000000000..7fbb13c5bb Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/heart200.png differ diff --git a/tests/auto/declarative/qquickimage/data/htiling.qml b/tests/auto/declarative/qquickimage/data/htiling.qml new file mode 100644 index 0000000000..f192f931c9 --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/htiling.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Rectangle { + width: 200; height: 550 + + Image { + objectName: "tiling"; anchors.fill: parent + source: "green.png"; fillMode: Image.TileHorizontally + } +} + diff --git a/tests/auto/declarative/qquickimage/data/mirror.qml b/tests/auto/declarative/qquickimage/data/mirror.qml new file mode 100644 index 0000000000..98fddf083e --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/mirror.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Rectangle { + width: 300 + height: 250 + Image { + objectName: "image" + anchors.fill: parent + source: "pattern.png" + } +} diff --git a/tests/auto/declarative/qquickimage/data/nullpixmap.qml b/tests/auto/declarative/qquickimage/data/nullpixmap.qml new file mode 100644 index 0000000000..d52f41f164 --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/nullpixmap.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Image { + width: 10; height:10; fillMode: Image.PreserveAspectFit + source: "" +} diff --git a/tests/auto/declarative/qquickimage/data/pattern.png b/tests/auto/declarative/qquickimage/data/pattern.png new file mode 100644 index 0000000000..d3d5e1e007 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/pattern.png differ diff --git a/tests/auto/declarative/qquickimage/data/qtbug_16389.qml b/tests/auto/declarative/qquickimage/data/qtbug_16389.qml new file mode 100644 index 0000000000..7b8adecb11 --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/qtbug_16389.qml @@ -0,0 +1,30 @@ +import QtQuick 2.0 +Rectangle { + width: 400 + height: 400 + + Item { + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: blueHandle.top + anchors.right: blueHandle.left + + Image { + id: iconImage + objectName: "iconImage" + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "heart200.png" + fillMode: Image.PreserveAspectFit + smooth: true + } + } + + Rectangle { + id: blueHandle + objectName: "blueHandle" + color: "blue" + width: 25 + height: 25 + } +} diff --git a/tests/auto/declarative/qquickimage/data/rect.png b/tests/auto/declarative/qquickimage/data/rect.png new file mode 100644 index 0000000000..d564a2d5a5 Binary files /dev/null and b/tests/auto/declarative/qquickimage/data/rect.png differ diff --git a/tests/auto/declarative/qquickimage/data/vtiling.qml b/tests/auto/declarative/qquickimage/data/vtiling.qml new file mode 100644 index 0000000000..f730f6e050 --- /dev/null +++ b/tests/auto/declarative/qquickimage/data/vtiling.qml @@ -0,0 +1,11 @@ +import QtQuick 2.0 + +Rectangle { + width: 550; height: 200 + + Image { + objectName: "tiling"; anchors.fill: parent + source: "green.png"; fillMode: Image.TileVertically + } +} + diff --git a/tests/auto/declarative/qquickimage/qquickimage.pro b/tests/auto/declarative/qquickimage/qquickimage.pro new file mode 100644 index 0000000000..46cbdb49aa --- /dev/null +++ b/tests/auto/declarative/qquickimage/qquickimage.pro @@ -0,0 +1,13 @@ +CONFIG += testcase +TARGET = tst_qquickimage +macx:CONFIG -= app_bundle + +HEADERS += ../shared/testhttpserver.h +SOURCES += tst_qquickimage.cpp ../shared/testhttpserver.cpp + +testDataFiles.files = data +testDataFiles.path = . +DEPLOYMENT += testDataFiles + +CONFIG += parallel_test +QT += core-private gui-private declarative-private network testlib diff --git a/tests/auto/declarative/qquickimage/tst_qquickimage.cpp b/tests/auto/declarative/qquickimage/tst_qquickimage.cpp new file mode 100644 index 0000000000..3d7ee07d56 --- /dev/null +++ b/tests/auto/declarative/qquickimage/tst_qquickimage.cpp @@ -0,0 +1,689 @@ +/**************************************************************************** +** +** 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../shared/util.h" +#include "../shared/testhttpserver.h" + +#define SERVER_PORT 14451 +#define SERVER_ADDR "http://127.0.0.1:14451" + +class tst_qquickimage : public QObject +{ + Q_OBJECT +public: + tst_qquickimage(); + +private slots: + void noSource(); + void imageSource(); + void imageSource_data(); + void clearSource(); + void resized(); + void preserveAspectRatio(); + void smooth(); + void mirror(); + void svg(); + void geometry(); + void geometry_data(); + void big(); + void tiling_QTBUG_6716(); + void tiling_QTBUG_6716_data(); + void noLoading(); + void paintedWidthHeight(); + void sourceSize_QTBUG_14303(); + void sourceSize_QTBUG_16389(); + void nullPixmapPaint(); + +private: + template + T *findItem(QQuickItem *parent, const QString &id, int index=-1); + + QDeclarativeEngine engine; +}; + +tst_qquickimage::tst_qquickimage() +{ +} + +void tst_qquickimage::noSource() +{ + QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->source(), QUrl()); + QVERIFY(obj->status() == QQuickImage::Null); + QCOMPARE(obj->width(), 0.); + QCOMPARE(obj->height(), 0.); + QCOMPARE(obj->fillMode(), QQuickImage::Stretch); + QCOMPARE(obj->progress(), 0.0); + + delete obj; +} + +void tst_qquickimage::imageSource_data() +{ + QTest::addColumn("source"); + QTest::addColumn("width"); + QTest::addColumn("height"); + QTest::addColumn("remote"); + QTest::addColumn("async"); + QTest::addColumn("cache"); + QTest::addColumn("error"); + + QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << true << ""; + QTest::newRow("local no cache") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << false << ""; + QTest::newRow("local async") << QUrl::fromLocalFile(TESTDATA("colors1.png")).toString() << 120.0 << 120.0 << false << true << true << ""; + QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << 0.0 << 0.0 << false + << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString(); + QTest::newRow("local async not found") << QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString() << 0.0 << 0.0 << false + << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString(); + QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << ""; + QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << ""; + if (QImageReader::supportedImageFormats().contains("svg")) + QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << ""; + + QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true + << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found"; + +} + +void tst_qquickimage::imageSource() +{ + QFETCH(QString, source); + QFETCH(double, width); + QFETCH(double, height); + QFETCH(bool, remote); + QFETCH(bool, async); + QFETCH(bool, cache); + QFETCH(QString, error); + + TestHTTPServer server(SERVER_PORT); + if (remote) { + QVERIFY(server.isValid()); + server.serveDirectory(TESTDATA("")); + server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png"); + } + + if (!error.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, error.toUtf8()); + + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: " + + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: " + + (cache ? QLatin1String("true") : QLatin1String("false")) + " }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + + if (async) + QVERIFY(obj->asynchronous() == true); + else + QVERIFY(obj->asynchronous() == false); + + if (cache) + QVERIFY(obj->cache() == true); + else + QVERIFY(obj->cache() == false); + + if (remote || async) + QTRY_VERIFY(obj->status() == QQuickImage::Loading); + + QCOMPARE(obj->source(), remote ? source : QUrl(source)); + + if (error.isEmpty()) { + QTRY_VERIFY(obj->status() == QQuickImage::Ready); + QCOMPARE(obj->width(), qreal(width)); + QCOMPARE(obj->height(), qreal(height)); + QCOMPARE(obj->fillMode(), QQuickImage::Stretch); + QCOMPARE(obj->progress(), 1.0); + } else { + QTRY_VERIFY(obj->status() == QQuickImage::Error); + } + + delete obj; +} + +void tst_qquickimage::clearSource() +{ + QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png"))); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QVERIFY(obj->status() == QQuickImage::Ready); + QCOMPARE(obj->width(), 120.); + QCOMPARE(obj->height(), 120.); + QCOMPARE(obj->progress(), 1.0); + + ctxt->setContextProperty("srcImage", ""); + QVERIFY(obj->source().isEmpty()); + QVERIFY(obj->status() == QQuickImage::Null); + QCOMPARE(obj->width(), 0.); + QCOMPARE(obj->height(), 0.); + QCOMPARE(obj->progress(), 0.0); + + delete obj; +} + +void tst_qquickimage::resized() +{ + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 300 }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 300.); + QCOMPARE(obj->height(), 300.); + QCOMPARE(obj->fillMode(), QQuickImage::Stretch); + delete obj; +} + + +void tst_qquickimage::preserveAspectRatio() +{ + QQuickView *canvas = new QQuickView(0); + canvas->show(); + + canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml"))); + QQuickImage *image = qobject_cast(canvas->rootObject()); + QVERIFY(image != 0); + image->setWidth(80.0); + QCOMPARE(image->width(), 80.); + QCOMPARE(image->height(), 80.); + + canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml"))); + image = qobject_cast(canvas->rootObject()); + image->setHeight(60.0); + QVERIFY(image != 0); + QCOMPARE(image->height(), 60.); + QCOMPARE(image->width(), 60.); + delete canvas; +} + +void tst_qquickimage::smooth() +{ + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 300.); + QCOMPARE(obj->height(), 300.); + QCOMPARE(obj->smooth(), true); + QCOMPARE(obj->fillMode(), QQuickImage::Stretch); + + delete obj; +} + +void tst_qquickimage::mirror() +{ + QMap screenshots; + QList fillModes; + fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop + << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally; + + qreal width = 300; + qreal height = 250; + + foreach (QQuickImage::FillMode fillMode, fillModes) { + QQuickView *canvas = new QQuickView; + canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml"))); + + QQuickImage *obj = canvas->rootObject()->findChild("image"); + QVERIFY(obj != 0); + + obj->setFillMode(fillMode); + obj->setProperty("mirror", true); + canvas->show(); + + QImage screenshot = canvas->grabFrameBuffer(); + screenshots[fillMode] = screenshot; + delete canvas; + } + + foreach (QQuickImage::FillMode fillMode, fillModes) { + QPixmap srcPixmap; + QVERIFY(srcPixmap.load(TESTDATA("pattern.png"))); + + QPixmap expected(width, height); + expected.fill(); + QPainter p_e(&expected); + QTransform transform; + transform.translate(width, 0).scale(-1, 1.0); + p_e.setTransform(transform); + + switch (fillMode) { + case QQuickImage::Stretch: + p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QQuickImage::PreserveAspectFit: + p_e.drawPixmap(QRect(25, 0, height, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + case QQuickImage::PreserveAspectCrop: + { + qreal ratio = width/srcPixmap.width(); // width is the longer side + QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio); + rect.moveCenter(QRect(0, 0, width, height).center()); + p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height())); + break; + } + case QQuickImage::Tile: + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QQuickImage::TileVertically: + transform.scale(width / srcPixmap.width(), 1.0); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + case QQuickImage::TileHorizontally: + transform.scale(1.0, height / srcPixmap.height()); + p_e.setTransform(transform); + p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap); + break; + } + + QImage img = expected.toImage(); +#ifdef Q_WS_QPA + QEXPECT_FAIL("", "QTBUG-21005 fails", Continue); +#endif + QCOMPARE(screenshots[fillMode], img); + } +} + +void tst_qquickimage::svg() +{ + if (!QImageReader::supportedImageFormats().contains("svg")) + QSKIP("svg support not available"); + + QString src = QUrl::fromLocalFile(TESTDATA("heart.svg")).toString(); + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 300.0); + QCOMPARE(obj->height(), 300.0); + obj->setSourceSize(QSize(200,200)); + + QCOMPARE(obj->width(), 200.0); + QCOMPARE(obj->height(), 200.0); + delete obj; +} + +void tst_qquickimage::geometry_data() +{ + QTest::addColumn("fillMode"); + QTest::addColumn("explicitWidth"); + QTest::addColumn("explicitHeight"); + QTest::addColumn("itemWidth"); + QTest::addColumn("paintedWidth"); + QTest::addColumn("boundingWidth"); + QTest::addColumn("itemHeight"); + QTest::addColumn("paintedHeight"); + QTest::addColumn("boundingHeight"); + + // tested image has width 200, height 100 + + // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match + QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0; + QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0; + + // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match + QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0; + QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0; + QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0; + + // bounding rect, painted rect and item rect are equal in stretching and tiling images + QStringList fillModes; + fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally"; + foreach (QString fillMode, fillModes) { + QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0; + QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0; + QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0; + QTest::newRow(QString(fillMode + " explicit width 300, height 400").toLatin1()) << fillMode << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 400.0 << 400.0; + } +} + +void tst_qquickimage::geometry() +{ + QFETCH(QString, fillMode); + QFETCH(bool, explicitWidth); + QFETCH(bool, explicitHeight); + QFETCH(double, itemWidth); + QFETCH(double, itemHeight); + QFETCH(double, paintedWidth); + QFETCH(double, paintedHeight); + QFETCH(double, boundingWidth); + QFETCH(double, boundingHeight); + + QString src = QUrl::fromLocalFile(TESTDATA("rect.png")).toString(); + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; "; + + if (explicitWidth) + componentStr.append("width: 300; "); + if (explicitHeight) + componentStr.append("height: 400; "); + componentStr.append("}"); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + + QCOMPARE(obj->width(), itemWidth); + QCOMPARE(obj->paintedWidth(), paintedWidth); + QCOMPARE(obj->boundingRect().width(), boundingWidth); + + QCOMPARE(obj->height(), itemHeight); + QCOMPARE(obj->paintedHeight(), paintedHeight); + QCOMPARE(obj->boundingRect().height(), boundingHeight); + delete obj; +} + +void tst_qquickimage::big() +{ + // If the JPEG loader does not implement scaling efficiently, it would + // have to build a 400 MB image. That would be a bug in the JPEG loader. + + QString src = QUrl::fromLocalFile(TESTDATA("big.jpeg")).toString(); + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }"; + + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 100.0); + QCOMPARE(obj->height(), 256.0); + + delete obj; +} + +void tst_qquickimage::tiling_QTBUG_6716() +{ + QFETCH(QString, source); + + QQuickView *canvas = new QQuickView(0); + canvas->setSource(QUrl::fromLocalFile(TESTDATA(source))); + canvas->show(); + qApp->processEvents(); + + QQuickImage *tiling = findItem(canvas->rootObject(), "tiling"); + + QVERIFY(tiling != 0); + QImage img = canvas->grabFrameBuffer(); + for (int x = 0; x < tiling->width(); ++x) { + for (int y = 0; y < tiling->height(); ++y) { + QEXPECT_FAIL("horizontal_tiling", "QTBUG-21005 - stable failing test", Abort); + QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0)); + } + } + delete canvas; +} + +void tst_qquickimage::tiling_QTBUG_6716_data() +{ + QTest::addColumn("source"); + QTest::newRow("vertical_tiling") << "vtiling.qml"; + QTest::newRow("horizontal_tiling") << "htiling.qml"; +} + +void tst_qquickimage::noLoading() +{ + TestHTTPServer server(SERVER_PORT); + QVERIFY(server.isValid()); + server.serveDirectory(TESTDATA("")); + server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png"); + + QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; cache: true }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart.png"))); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QVERIFY(obj->status() == QQuickImage::Ready); + + QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &))); + QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal))); + QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status))); + + // Loading local file + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png"))); + QTRY_VERIFY(obj->status() == QQuickImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + QTRY_COMPARE(sourceSpy.count(), 1); + QTRY_COMPARE(progressSpy.count(), 0); + QTRY_COMPARE(statusSpy.count(), 0); + + // Loading remote file + ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png"); + QTRY_VERIFY(obj->status() == QQuickImage::Loading); + QTRY_VERIFY(obj->progress() == 0.0); + QTRY_VERIFY(obj->status() == QQuickImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + QTRY_COMPARE(sourceSpy.count(), 2); + QTRY_COMPARE(progressSpy.count(), 2); + QTRY_COMPARE(statusSpy.count(), 2); + + // Loading remote file again - should not go through 'Loading' state. + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png"))); + ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png"); + QTRY_VERIFY(obj->status() == QQuickImage::Ready); + QTRY_VERIFY(obj->progress() == 1.0); + QTRY_COMPARE(sourceSpy.count(), 4); + QTRY_COMPARE(progressSpy.count(), 2); + QTRY_COMPARE(statusSpy.count(), 2); + + delete obj; +} + +void tst_qquickimage::paintedWidthHeight() +{ + { + QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString(); + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }"; + + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 200.0); + QCOMPARE(obj->height(), 25.0); + QCOMPARE(obj->paintedWidth(), 25.0); + QCOMPARE(obj->paintedHeight(), 25.0); + + delete obj; + } + + { + QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString(); + QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }"; + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->width(), 26.0); + QCOMPARE(obj->height(), 175.0); + QCOMPARE(obj->paintedWidth(), 26.0); + QCOMPARE(obj->paintedHeight(), 26.0); + + delete obj; + } +} + +void tst_qquickimage::sourceSize_QTBUG_14303() +{ + QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }"; + QDeclarativeContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png"))); + QDeclarativeComponent component(&engine); + component.setData(componentStr.toLatin1(), QUrl::fromLocalFile("")); + QQuickImage *obj = qobject_cast(component.create()); + + QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged())); + + QTRY_VERIFY(obj != 0); + QTRY_VERIFY(obj->status() == QQuickImage::Ready); + + QTRY_COMPARE(obj->sourceSize().width(), 200); + QTRY_COMPARE(obj->sourceSize().height(), 200); + QTRY_COMPARE(sourceSizeSpy.count(), 0); + + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png"))); + QTRY_COMPARE(obj->sourceSize().width(), 120); + QTRY_COMPARE(obj->sourceSize().height(), 120); + QTRY_COMPARE(sourceSizeSpy.count(), 1); + + ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png"))); + QTRY_COMPARE(obj->sourceSize().width(), 200); + QTRY_COMPARE(obj->sourceSize().height(), 200); + QTRY_COMPARE(sourceSizeSpy.count(), 2); + + delete obj; +} + +void tst_qquickimage::sourceSize_QTBUG_16389() +{ + QQuickView *canvas = new QQuickView(0); + canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug_16389.qml"))); + canvas->show(); + qApp->processEvents(); + + QQuickImage *image = findItem(canvas->rootObject(), "iconImage"); + QQuickItem *handle = findItem(canvas->rootObject(), "blueHandle"); + + QCOMPARE(image->sourceSize().width(), 200); + QCOMPARE(image->sourceSize().height(), 200); + QCOMPARE(image->paintedWidth(), 0.0); + QCOMPARE(image->paintedHeight(), 0.0); + + handle->setY(20); + + QCOMPARE(image->sourceSize().width(), 200); + QCOMPARE(image->sourceSize().height(), 200); + QCOMPARE(image->paintedWidth(), 20.0); + QCOMPARE(image->paintedHeight(), 20.0); +} + +static int numberOfWarnings = 0; +static void checkWarnings(QtMsgType, const char *msg) +{ + if (!QString(msg).contains("QGLContext::makeCurrent(): Failed.")) + numberOfWarnings++; +} + +// QTBUG-15690 +void tst_qquickimage::nullPixmapPaint() +{ + QQuickView *canvas = new QQuickView(0); + canvas->setSource(QUrl::fromLocalFile(TESTDATA("nullpixmap.qml"))); + canvas->show(); + + QQuickImage *image = qobject_cast(canvas->rootObject()); + QTRY_VERIFY(image != 0); + image->setSource(SERVER_ADDR + QString("/no-such-file.png")); + + QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings); + + // used to print "QTransform::translate with NaN called" + QPixmap pm = QPixmap::fromImage(canvas->grabFrameBuffer()); + qInstallMsgHandler(previousMsgHandler); + QVERIFY(numberOfWarnings == 0); + delete image; +} + +/* + Find an item with the specified objectName. If index is supplied then the + item must also evaluate the {index} expression equal to index +*/ +template +T *tst_qquickimage::findItem(QQuickItem *parent, const QString &objectName, int index) +{ + const QMetaObject &mo = T::staticMetaObject; + //qDebug() << parent->childItems().count() << "children"; + for (int i = 0; i < parent->childItems().count(); ++i) { + QQuickItem *item = qobject_cast(parent->childItems().at(i)); + if (!item) + continue; + //qDebug() << "try" << item; + if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) { + if (index != -1) { + QDeclarativeExpression e(qmlContext(item), item, "index"); + if (e.evaluate().toInt() == index) + return static_cast(item); + } else { + return static_cast(item); + } + } + item = findItem(item, objectName, index); + if (item) + return static_cast(item); + } + + return 0; +} + +QTEST_MAIN(tst_qquickimage) + +#include "tst_qquickimage.moc" -- cgit v1.2.3