#include <QtTest/QSignalSpy>
#include <QtGui/QPainter>
#include <QtGui/QImageReader>
+#include <QQuickWindow>
#include "../../shared/util.h"
#include "../../shared/testhttpserver.h"
tst_qquickimage();
private slots:
+ void cleanup();
void noSource();
void imageSource();
void imageSource_data();
void smooth();
void mirror();
void svg();
+ void svg_data();
void geometry();
void geometry_data();
void big();
void imageCrash_QTBUG_22125();
void sourceSize_data();
void sourceSize();
+ void progressAndStatusChanges();
+ void sourceSizeChanges();
private:
QQmlEngine engine;
{
}
+void tst_qquickimage::cleanup()
+{
+ QQuickWindow window;
+ window.releaseResources();
+ engine.clearComponentCache();
+}
+
void tst_qquickimage::noSource()
{
QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }";
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 << "";
-
+ if (QImageReader::supportedImageFormats().contains("svgz"))
+ QTest::newRow("remote svgz") << SERVER_ADDR "/heart.svgz" << 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::preserveAspectRatio()
{
- QQuickView *canvas = new QQuickView(0);
- canvas->show();
+ QQuickView *window = new QQuickView(0);
+ window->show();
- canvas->setSource(testFileUrl("aspectratio.qml"));
- QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ window->setSource(testFileUrl("aspectratio.qml"));
+ QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
QVERIFY(image != 0);
image->setWidth(80.0);
QCOMPARE(image->width(), 80.);
QCOMPARE(image->height(), 80.);
- canvas->setSource(testFileUrl("aspectratio.qml"));
- image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ window->setSource(testFileUrl("aspectratio.qml"));
+ image = qobject_cast<QQuickImage*>(window->rootObject());
image->setHeight(60.0);
QVERIFY(image != 0);
QCOMPARE(image->height(), 60.);
QCOMPARE(image->width(), 60.);
- delete canvas;
+ delete window;
}
void tst_qquickimage::smooth()
void tst_qquickimage::mirror()
{
- QSKIP("Test is broken on multiple levels, will need incremental fixes");
-
QMap<QQuickImage::FillMode, QImage> screenshots;
QList<QQuickImage::FillMode> fillModes;
fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
- << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally;
+ << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally << QQuickImage::Pad;
qreal width = 300;
qreal height = 250;
foreach (QQuickImage::FillMode fillMode, fillModes) {
- QQuickView *canvas = new QQuickView;
- canvas->setSource(testFileUrl("mirror.qml"));
+ QQuickView *window = new QQuickView;
+ window->setSource(testFileUrl("mirror.qml"));
- QQuickImage *obj = canvas->rootObject()->findChild<QQuickImage*>("image");
+ QQuickImage *obj = window->rootObject()->findChild<QQuickImage*>("image");
QVERIFY(obj != 0);
obj->setFillMode(fillMode);
obj->setProperty("mirror", true);
- canvas->show();
+ window->show();
+ window->requestActivateWindow();
+ QTest::qWaitForWindowShown(window);
- QImage screenshot = canvas->grabFrameBuffer();
+ QImage screenshot = window->grabWindow();
screenshots[fillMode] = screenshot;
- delete canvas;
+ delete window;
}
foreach (QQuickImage::FillMode fillMode, fillModes) {
transform.translate(width, 0).scale(-1, 1.0);
p_e.setTransform(transform);
+ QPoint offset(width / 2 - srcPixmap.width() / 2, height / 2 - srcPixmap.height() / 2);
+
switch (fillMode) {
case QQuickImage::Stretch:
p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
break;
}
case QQuickImage::Tile:
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, -offset);
break;
case QQuickImage::TileVertically:
transform.scale(width / srcPixmap.width(), 1.0);
p_e.setTransform(transform);
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, QPoint(0, -offset.y()));
break;
case QQuickImage::TileHorizontally:
transform.scale(1.0, height / srcPixmap.height());
p_e.setTransform(transform);
- p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
+ p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, QPoint(-offset.x(), 0));
break;
case QQuickImage::Pad:
+ p_e.drawPixmap(offset, srcPixmap);
break;
}
QImage img = expected.toImage();
- QEXPECT_FAIL("", "QTBUG-21005 fails", Continue);
QCOMPARE(screenshots[fillMode], img);
}
}
+void tst_qquickimage::svg_data()
+{
+ QTest::addColumn<QString>("src");
+ QTest::addColumn<QByteArray>("format");
+
+ QTest::newRow("svg") << testFileUrl("heart.svg").toString() << QByteArray("svg");
+ QTest::newRow("svgz") << testFileUrl("heart.svgz").toString() << QByteArray("svgz");
+}
+
void tst_qquickimage::svg()
{
- if (!QImageReader::supportedImageFormats().contains("svg"))
+ QFETCH(QString, src);
+ QFETCH(QByteArray, format);
+ if (!QImageReader::supportedImageFormats().contains(format))
QSKIP("svg support not available");
- QString src = testFileUrl("heart.svg").toString();
QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
QQmlComponent component(&engine);
component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
QVERIFY(obj != 0);
QCOMPARE(obj->width(), 300.0);
- QCOMPARE(obj->height(), 300.0);
+ QCOMPARE(obj->height(), 273.0);
obj->setSourceSize(QSize(200,200));
QCOMPARE(obj->width(), 200.0);
- QCOMPARE(obj->height(), 200.0);
+ QCOMPARE(obj->height(), 182.0);
delete obj;
}
delete obj;
}
-// As tiling_QTBUG_6716 doesn't complete, it doesn't delete the
-// canvas which causes leak warnings. Use this delete on stack
-// destruction pattern to work around this.
-template<typename T>
-struct AutoDelete {
- AutoDelete(T *t) : t(t) {}
- ~AutoDelete() { delete t; }
-private:
- T *t;
-};
-
void tst_qquickimage::tiling_QTBUG_6716()
{
- QSKIP("Test is broken on multiple levels, will need incremental fixes");
-
QFETCH(QString, source);
- QQuickView *canvas = new QQuickView(0);
- AutoDelete<QQuickView> del(canvas);
-
- canvas->setSource(testFileUrl(source));
- canvas->show();
- qApp->processEvents();
+ QQuickView view(testFileUrl(source));
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
- QQuickImage *tiling = findItem<QQuickImage>(canvas->rootObject(), "tiling");
+ QQuickImage *tiling = findItem<QQuickImage>(view.rootObject(), "tiling");
QVERIFY(tiling != 0);
- QImage img = canvas->grabFrameBuffer();
+ QImage img = view.grabWindow();
for (int x = 0; x < tiling->width(); ++x) {
for (int y = 0; y < tiling->height(); ++y) {
QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
}
}
-
- delete canvas;
}
void tst_qquickimage::tiling_QTBUG_6716_data()
QTRY_VERIFY(obj->progress() == 1.0);
QTRY_COMPARE(sourceSpy.count(), 1);
QTRY_COMPARE(progressSpy.count(), 0);
- QTRY_COMPARE(statusSpy.count(), 0);
+ QTRY_COMPARE(statusSpy.count(), 1);
// Loading remote file
ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
QTRY_VERIFY(obj->progress() == 1.0);
QTRY_COMPARE(sourceSpy.count(), 2);
QTRY_COMPARE(progressSpy.count(), 2);
- QTRY_COMPARE(statusSpy.count(), 2);
+ QTRY_COMPARE(statusSpy.count(), 3);
// Loading remote file again - should not go through 'Loading' state.
ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
QTRY_VERIFY(obj->progress() == 1.0);
QTRY_COMPARE(sourceSpy.count(), 4);
QTRY_COMPARE(progressSpy.count(), 2);
- QTRY_COMPARE(statusSpy.count(), 2);
+ QTRY_COMPARE(statusSpy.count(), 5);
delete obj;
}
void tst_qquickimage::sourceSize_QTBUG_16389()
{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(testFileUrl("qtbug_16389.qml"));
- canvas->show();
+ QQuickView *window = new QQuickView(0);
+ window->setSource(testFileUrl("qtbug_16389.qml"));
+ window->show();
qApp->processEvents();
- QQuickImage *image = findItem<QQuickImage>(canvas->rootObject(), "iconImage");
- QQuickItem *handle = findItem<QQuickItem>(canvas->rootObject(), "blueHandle");
+ QQuickImage *image = findItem<QQuickImage>(window->rootObject(), "iconImage");
+ QQuickItem *handle = findItem<QQuickItem>(window->rootObject(), "blueHandle");
QCOMPARE(image->sourceSize().width(), 200);
QCOMPARE(image->sourceSize().height(), 200);
QCOMPARE(image->paintedWidth(), 20.0);
QCOMPARE(image->paintedHeight(), 20.0);
- delete canvas;
+ delete window;
}
static int numberOfWarnings = 0;
// QTBUG-15690
void tst_qquickimage::nullPixmapPaint()
{
- QQuickView *canvas = new QQuickView(0);
- canvas->setSource(testFileUrl("nullpixmap.qml"));
- canvas->show();
+ QQuickView *window = new QQuickView(0);
+ window->setSource(testFileUrl("nullpixmap.qml"));
+ window->show();
- QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ QQuickImage *image = qobject_cast<QQuickImage*>(window->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());
+ QPixmap pm = QPixmap::fromImage(window->grabWindow());
qInstallMsgHandler(previousMsgHandler);
QVERIFY(numberOfWarnings == 0);
delete image;
- delete canvas;
+ delete window;
}
void tst_qquickimage::imageCrash_QTBUG_22125()
QFETCH(qreal, implicitWidth);
QFETCH(qreal, implicitHeight);
- QQuickView *canvas = new QQuickView(0);
- QQmlContext *ctxt = canvas->rootContext();
+ QQuickView *window = new QQuickView(0);
+ QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("srcWidth", sourceWidth);
ctxt->setContextProperty("srcHeight", sourceHeight);
- canvas->setSource(testFileUrl("sourceSize.qml"));
- canvas->show();
+ window->setSource(testFileUrl("sourceSize.qml"));
+ window->show();
qApp->processEvents();
- QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
+ QQuickImage *image = qobject_cast<QQuickImage*>(window->rootObject());
QVERIFY(image);
QCOMPARE(image->sourceSize().width(), sourceWidth);
QCOMPARE(image->implicitWidth(), implicitWidth);
QCOMPARE(image->implicitHeight(), implicitHeight);
- delete canvas;
+ delete window;
+}
+
+void tst_qquickimage::sourceSizeChanges()
+{
+ TestHTTPServer server(14449);
+ QVERIFY(server.isValid());
+ server.serveDirectory(dataDirectory());
+
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.setData("import QtQuick 2.0\nImage { source: srcImage }", QUrl::fromLocalFile(""));
+ QTRY_VERIFY(component.isReady());
+ QQmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", "");
+ QQuickImage *img = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(img != 0);
+
+ QSignalSpy sourceSizeSpy(img, SIGNAL(sourceSizeChanged()));
+
+ // Local
+ ctxt->setContextProperty("srcImage", QUrl(""));
+ QTRY_COMPARE(img->status(), QQuickImage::Null);
+ QTRY_COMPARE(sourceSizeSpy.count(), 0);
+
+ ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
+
+ ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
+
+ ctxt->setContextProperty("srcImage", testFileUrl("heart_copy.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 1);
+
+ ctxt->setContextProperty("srcImage", testFileUrl("colors.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 2);
+
+ ctxt->setContextProperty("srcImage", QUrl(""));
+ QTRY_COMPARE(img->status(), QQuickImage::Null);
+ QTRY_COMPARE(sourceSizeSpy.count(), 3);
+
+ // Remote
+ ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/heart.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
+
+ ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/heart.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
+
+ ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/heart_copy.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 4);
+
+ ctxt->setContextProperty("srcImage", QUrl("http://127.0.0.1:14449/colors.png"));
+ QTRY_COMPARE(img->status(), QQuickImage::Ready);
+ QTRY_COMPARE(sourceSizeSpy.count(), 5);
+
+ ctxt->setContextProperty("srcImage", QUrl(""));
+ QTRY_COMPARE(img->status(), QQuickImage::Null);
+ QTRY_COMPARE(sourceSizeSpy.count(), 6);
+
+ delete img;
+}
+
+void tst_qquickimage::progressAndStatusChanges()
+{
+ TestHTTPServer server(14449);
+ QVERIFY(server.isValid());
+ server.serveDirectory(dataDirectory());
+
+ QQmlEngine engine;
+ QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
+ QQmlContext *ctxt = engine.rootContext();
+ ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
+ QQmlComponent component(&engine);
+ component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
+ QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
+ QVERIFY(obj != 0);
+ QVERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+
+ qRegisterMetaType<QQuickImageBase::Status>();
+ QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
+ QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
+ QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
+
+ // Same image
+ ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
+ QTRY_VERIFY(obj->status() == QQuickImage::Ready);
+ QTRY_VERIFY(obj->progress() == 1.0);
+ QTRY_COMPARE(sourceSpy.count(), 0);
+ QTRY_COMPARE(progressSpy.count(), 0);
+ QTRY_COMPARE(statusSpy.count(), 0);
+
+ // Loading local file
+ ctxt->setContextProperty("srcImage", testFileUrl("colors.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(), 1);
+
+ // Loading remote file
+ ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/heart.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_VERIFY(progressSpy.count() > 1);
+ QTRY_COMPARE(statusSpy.count(), 3);
+
+ ctxt->setContextProperty("srcImage", "");
+ QTRY_VERIFY(obj->status() == QQuickImage::Null);
+ QTRY_VERIFY(obj->progress() == 0.0);
+ QTRY_COMPARE(sourceSpy.count(), 3);
+ QTRY_VERIFY(progressSpy.count() > 2);
+ QTRY_COMPARE(statusSpy.count(), 4);
+
+ delete obj;
}
QTEST_MAIN(tst_qquickimage)