1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QTextDocument>
47 #include <QtQml/qqmlengine.h>
48 #include <QtQml/qqmlcomponent.h>
49 #include <QtQuick/qquickview.h>
50 #include <private/qquickimage_p.h>
51 #include <private/qquickimagebase_p.h>
52 #include <private/qquickloader_p.h>
53 #include <QtQml/qqmlcontext.h>
54 #include <QtQml/qqmlexpression.h>
55 #include <QtTest/QSignalSpy>
56 #include <QtGui/QPainter>
57 #include <QtGui/QImageReader>
59 #include "../../shared/util.h"
60 #include "../../shared/testhttpserver.h"
61 #include "../shared/visualtestutil.h"
63 #define SERVER_PORT 14451
64 #define SERVER_ADDR "http://127.0.0.1:14451"
67 using namespace QQuickVisualTestUtil;
69 Q_DECLARE_METATYPE(QQuickImageBase::Status)
71 class tst_qquickimage : public QQmlDataTest
80 void imageSource_data();
83 void preserveAspectRatio();
90 void tiling_QTBUG_6716();
91 void tiling_QTBUG_6716_data();
93 void paintedWidthHeight();
94 void sourceSize_QTBUG_14303();
95 void sourceSize_QTBUG_16389();
96 void nullPixmapPaint();
97 void imageCrash_QTBUG_22125();
98 void sourceSize_data();
105 tst_qquickimage::tst_qquickimage()
109 void tst_qquickimage::noSource()
111 QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }";
112 QQmlComponent component(&engine);
113 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
114 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
116 QCOMPARE(obj->source(), QUrl());
117 QVERIFY(obj->status() == QQuickImage::Null);
118 QCOMPARE(obj->width(), 0.);
119 QCOMPARE(obj->height(), 0.);
120 QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
121 QCOMPARE(obj->progress(), 0.0);
126 void tst_qquickimage::imageSource_data()
128 QTest::addColumn<QString>("source");
129 QTest::addColumn<double>("width");
130 QTest::addColumn<double>("height");
131 QTest::addColumn<bool>("remote");
132 QTest::addColumn<bool>("async");
133 QTest::addColumn<bool>("cache");
134 QTest::addColumn<QString>("error");
136 QTest::newRow("local") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << true << "";
137 QTest::newRow("local no cache") << testFileUrl("colors.png").toString() << 120.0 << 120.0 << false << false << false << "";
138 QTest::newRow("local async") << testFileUrl("colors1.png").toString() << 120.0 << 120.0 << false << true << true << "";
139 QTest::newRow("local not found") << testFileUrl("no-such-file.png").toString() << 0.0 << 0.0 << false
140 << false << true << "file::2:1: QML Image: Cannot open: " + testFileUrl("no-such-file.png").toString();
141 QTest::newRow("local async not found") << testFileUrl("no-such-file-1.png").toString() << 0.0 << 0.0 << false
142 << true << true << "file::2:1: QML Image: Cannot open: " + testFileUrl("no-such-file-1.png").toString();
143 QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << "";
144 QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
145 if (QImageReader::supportedImageFormats().contains("svg"))
146 QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << "";
148 QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
149 << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
153 void tst_qquickimage::imageSource()
155 QFETCH(QString, source);
156 QFETCH(double, width);
157 QFETCH(double, height);
158 QFETCH(bool, remote);
161 QFETCH(QString, error);
163 TestHTTPServer server(SERVER_PORT);
165 QVERIFY(server.isValid());
166 server.serveDirectory(dataDirectory());
167 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
170 if (!error.isEmpty())
171 QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
173 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: "
174 + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
175 + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
176 QQmlComponent component(&engine);
177 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
178 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
182 QVERIFY(obj->asynchronous() == true);
184 QVERIFY(obj->asynchronous() == false);
187 QVERIFY(obj->cache() == true);
189 QVERIFY(obj->cache() == false);
192 QTRY_VERIFY(obj->status() == QQuickImage::Loading);
194 QCOMPARE(obj->source(), remote ? source : QUrl(source));
196 if (error.isEmpty()) {
197 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
198 QCOMPARE(obj->width(), qreal(width));
199 QCOMPARE(obj->height(), qreal(height));
200 QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
201 QCOMPARE(obj->progress(), 1.0);
203 QTRY_VERIFY(obj->status() == QQuickImage::Error);
209 void tst_qquickimage::clearSource()
211 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
212 QQmlContext *ctxt = engine.rootContext();
213 ctxt->setContextProperty("srcImage", testFileUrl("colors.png"));
214 QQmlComponent component(&engine);
215 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
216 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
218 QVERIFY(obj->status() == QQuickImage::Ready);
219 QCOMPARE(obj->width(), 120.);
220 QCOMPARE(obj->height(), 120.);
221 QCOMPARE(obj->progress(), 1.0);
223 ctxt->setContextProperty("srcImage", "");
224 QVERIFY(obj->source().isEmpty());
225 QVERIFY(obj->status() == QQuickImage::Null);
226 QCOMPARE(obj->width(), 0.);
227 QCOMPARE(obj->height(), 0.);
228 QCOMPARE(obj->progress(), 0.0);
233 void tst_qquickimage::resized()
235 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + testFile("colors.png") + "\"; width: 300; height: 300 }";
236 QQmlComponent component(&engine);
237 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
238 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
240 QCOMPARE(obj->width(), 300.);
241 QCOMPARE(obj->height(), 300.);
242 QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
247 void tst_qquickimage::preserveAspectRatio()
249 QQuickView *canvas = new QQuickView(0);
252 canvas->setSource(testFileUrl("aspectratio.qml"));
253 QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
255 image->setWidth(80.0);
256 QCOMPARE(image->width(), 80.);
257 QCOMPARE(image->height(), 80.);
259 canvas->setSource(testFileUrl("aspectratio.qml"));
260 image = qobject_cast<QQuickImage*>(canvas->rootObject());
261 image->setHeight(60.0);
263 QCOMPARE(image->height(), 60.);
264 QCOMPARE(image->width(), 60.);
268 void tst_qquickimage::smooth()
270 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + testFile("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
271 QQmlComponent component(&engine);
272 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
273 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
275 QCOMPARE(obj->width(), 300.);
276 QCOMPARE(obj->height(), 300.);
277 QCOMPARE(obj->smooth(), true);
278 QCOMPARE(obj->fillMode(), QQuickImage::Stretch);
283 void tst_qquickimage::mirror()
285 QMap<QQuickImage::FillMode, QImage> screenshots;
286 QList<QQuickImage::FillMode> fillModes;
287 fillModes << QQuickImage::Stretch << QQuickImage::PreserveAspectFit << QQuickImage::PreserveAspectCrop
288 << QQuickImage::Tile << QQuickImage::TileVertically << QQuickImage::TileHorizontally << QQuickImage::Pad;
293 foreach (QQuickImage::FillMode fillMode, fillModes) {
294 QQuickView *canvas = new QQuickView;
295 canvas->setSource(testFileUrl("mirror.qml"));
297 QQuickImage *obj = canvas->rootObject()->findChild<QQuickImage*>("image");
300 obj->setFillMode(fillMode);
301 obj->setProperty("mirror", true);
303 canvas->requestActivateWindow();
304 QTest::qWaitForWindowShown(canvas);
306 QImage screenshot = canvas->grabFrameBuffer();
307 screenshots[fillMode] = screenshot;
311 foreach (QQuickImage::FillMode fillMode, fillModes) {
313 QVERIFY(srcPixmap.load(testFile("pattern.png")));
315 QPixmap expected(width, height);
317 QPainter p_e(&expected);
318 QTransform transform;
319 transform.translate(width, 0).scale(-1, 1.0);
320 p_e.setTransform(transform);
322 QPoint offset(width / 2 - srcPixmap.width() / 2, height / 2 - srcPixmap.height() / 2);
325 case QQuickImage::Stretch:
326 p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
328 case QQuickImage::PreserveAspectFit:
329 p_e.drawPixmap(QRect(25, 0, height, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
331 case QQuickImage::PreserveAspectCrop:
333 qreal ratio = width/srcPixmap.width(); // width is the longer side
334 QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio);
335 rect.moveCenter(QRect(0, 0, width, height).center());
336 p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
339 case QQuickImage::Tile:
340 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, -offset);
342 case QQuickImage::TileVertically:
343 transform.scale(width / srcPixmap.width(), 1.0);
344 p_e.setTransform(transform);
345 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, QPoint(0, -offset.y()));
347 case QQuickImage::TileHorizontally:
348 transform.scale(1.0, height / srcPixmap.height());
349 p_e.setTransform(transform);
350 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap, QPoint(-offset.x(), 0));
352 case QQuickImage::Pad:
353 p_e.drawPixmap(offset, srcPixmap);
357 QImage img = expected.toImage();
358 QCOMPARE(screenshots[fillMode], img);
362 void tst_qquickimage::svg()
364 if (!QImageReader::supportedImageFormats().contains("svg"))
365 QSKIP("svg support not available");
367 QString src = testFileUrl("heart.svg").toString();
368 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
369 QQmlComponent component(&engine);
370 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
371 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
373 QCOMPARE(obj->width(), 300.0);
374 QCOMPARE(obj->height(), 273.0);
375 obj->setSourceSize(QSize(200,200));
377 QCOMPARE(obj->width(), 200.0);
378 QCOMPARE(obj->height(), 182.0);
382 void tst_qquickimage::geometry_data()
384 QTest::addColumn<QString>("fillMode");
385 QTest::addColumn<bool>("explicitWidth");
386 QTest::addColumn<bool>("explicitHeight");
387 QTest::addColumn<double>("itemWidth");
388 QTest::addColumn<double>("paintedWidth");
389 QTest::addColumn<double>("boundingWidth");
390 QTest::addColumn<double>("itemHeight");
391 QTest::addColumn<double>("paintedHeight");
392 QTest::addColumn<double>("boundingHeight");
394 // tested image has width 200, height 100
396 // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match
397 QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
398 QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0;
399 QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0;
400 QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0;
402 // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match
403 QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
404 QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0;
405 QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
406 QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
408 // bounding rect, painted rect and item rect are equal in stretching and tiling images
409 QStringList fillModes;
410 fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
411 foreach (QString fillMode, fillModes) {
412 QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
413 QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
414 QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
415 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;
419 void tst_qquickimage::geometry()
421 QFETCH(QString, fillMode);
422 QFETCH(bool, explicitWidth);
423 QFETCH(bool, explicitHeight);
424 QFETCH(double, itemWidth);
425 QFETCH(double, itemHeight);
426 QFETCH(double, paintedWidth);
427 QFETCH(double, paintedHeight);
428 QFETCH(double, boundingWidth);
429 QFETCH(double, boundingHeight);
431 QString src = testFileUrl("rect.png").toString();
432 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; ";
435 componentStr.append("width: 300; ");
437 componentStr.append("height: 400; ");
438 componentStr.append("}");
439 QQmlComponent component(&engine);
440 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
441 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
444 QCOMPARE(obj->width(), itemWidth);
445 QCOMPARE(obj->paintedWidth(), paintedWidth);
446 QCOMPARE(obj->boundingRect().width(), boundingWidth);
448 QCOMPARE(obj->height(), itemHeight);
449 QCOMPARE(obj->paintedHeight(), paintedHeight);
450 QCOMPARE(obj->boundingRect().height(), boundingHeight);
454 void tst_qquickimage::big()
456 // If the JPEG loader does not implement scaling efficiently, it would
457 // have to build a 400 MB image. That would be a bug in the JPEG loader.
459 QString src = testFileUrl("big.jpeg").toString();
460 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }";
462 QQmlComponent component(&engine);
463 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
464 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
466 QCOMPARE(obj->width(), 100.0);
467 QCOMPARE(obj->height(), 256.0);
472 void tst_qquickimage::tiling_QTBUG_6716()
474 QFETCH(QString, source);
476 QQuickView view(testFileUrl(source));
478 view.requestActivateWindow();
479 QTest::qWaitForWindowShown(&view);
481 QQuickImage *tiling = findItem<QQuickImage>(view.rootObject(), "tiling");
483 QVERIFY(tiling != 0);
484 QImage img = view.grabFrameBuffer();
485 for (int x = 0; x < tiling->width(); ++x) {
486 for (int y = 0; y < tiling->height(); ++y) {
487 QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
492 void tst_qquickimage::tiling_QTBUG_6716_data()
494 QTest::addColumn<QString>("source");
495 QTest::newRow("vertical_tiling") << "vtiling.qml";
496 QTest::newRow("horizontal_tiling") << "htiling.qml";
499 void tst_qquickimage::noLoading()
501 qRegisterMetaType<QQuickImageBase::Status>();
503 TestHTTPServer server(SERVER_PORT);
504 QVERIFY(server.isValid());
505 server.serveDirectory(dataDirectory());
506 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
508 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; cache: true }";
509 QQmlContext *ctxt = engine.rootContext();
510 ctxt->setContextProperty("srcImage", testFileUrl("heart.png"));
511 QQmlComponent component(&engine);
512 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
513 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
515 QVERIFY(obj->status() == QQuickImage::Ready);
517 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
518 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
519 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QQuickImageBase::Status)));
521 // Loading local file
522 ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
523 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
524 QTRY_VERIFY(obj->progress() == 1.0);
525 QTRY_COMPARE(sourceSpy.count(), 1);
526 QTRY_COMPARE(progressSpy.count(), 0);
527 QTRY_COMPARE(statusSpy.count(), 0);
529 // Loading remote file
530 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
531 QTRY_VERIFY(obj->status() == QQuickImage::Loading);
532 QTRY_VERIFY(obj->progress() == 0.0);
533 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
534 QTRY_VERIFY(obj->progress() == 1.0);
535 QTRY_COMPARE(sourceSpy.count(), 2);
536 QTRY_COMPARE(progressSpy.count(), 2);
537 QTRY_COMPARE(statusSpy.count(), 2);
539 // Loading remote file again - should not go through 'Loading' state.
540 ctxt->setContextProperty("srcImage", testFileUrl("green.png"));
541 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
542 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
543 QTRY_VERIFY(obj->progress() == 1.0);
544 QTRY_COMPARE(sourceSpy.count(), 4);
545 QTRY_COMPARE(progressSpy.count(), 2);
546 QTRY_COMPARE(statusSpy.count(), 2);
551 void tst_qquickimage::paintedWidthHeight()
554 QString src = testFileUrl("heart.png").toString();
555 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }";
557 QQmlComponent component(&engine);
558 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
559 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
561 QCOMPARE(obj->width(), 200.0);
562 QCOMPARE(obj->height(), 25.0);
563 QCOMPARE(obj->paintedWidth(), 25.0);
564 QCOMPARE(obj->paintedHeight(), 25.0);
570 QString src = testFileUrl("heart.png").toString();
571 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }";
572 QQmlComponent component(&engine);
573 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
574 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
576 QCOMPARE(obj->width(), 26.0);
577 QCOMPARE(obj->height(), 175.0);
578 QCOMPARE(obj->paintedWidth(), 26.0);
579 QCOMPARE(obj->paintedHeight(), 26.0);
585 void tst_qquickimage::sourceSize_QTBUG_14303()
587 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
588 QQmlContext *ctxt = engine.rootContext();
589 ctxt->setContextProperty("srcImage", testFileUrl("heart200.png"));
590 QQmlComponent component(&engine);
591 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
592 QQuickImage *obj = qobject_cast<QQuickImage*>(component.create());
594 QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
596 QTRY_VERIFY(obj != 0);
597 QTRY_VERIFY(obj->status() == QQuickImage::Ready);
599 QTRY_COMPARE(obj->sourceSize().width(), 200);
600 QTRY_COMPARE(obj->sourceSize().height(), 200);
601 QTRY_COMPARE(sourceSizeSpy.count(), 0);
603 ctxt->setContextProperty("srcImage", testFileUrl("colors.png"));
604 QTRY_COMPARE(obj->sourceSize().width(), 120);
605 QTRY_COMPARE(obj->sourceSize().height(), 120);
606 QTRY_COMPARE(sourceSizeSpy.count(), 1);
608 ctxt->setContextProperty("srcImage", testFileUrl("heart200.png"));
609 QTRY_COMPARE(obj->sourceSize().width(), 200);
610 QTRY_COMPARE(obj->sourceSize().height(), 200);
611 QTRY_COMPARE(sourceSizeSpy.count(), 2);
616 void tst_qquickimage::sourceSize_QTBUG_16389()
618 QQuickView *canvas = new QQuickView(0);
619 canvas->setSource(testFileUrl("qtbug_16389.qml"));
621 qApp->processEvents();
623 QQuickImage *image = findItem<QQuickImage>(canvas->rootObject(), "iconImage");
624 QQuickItem *handle = findItem<QQuickItem>(canvas->rootObject(), "blueHandle");
626 QCOMPARE(image->sourceSize().width(), 200);
627 QCOMPARE(image->sourceSize().height(), 200);
628 QCOMPARE(image->paintedWidth(), 0.0);
629 QCOMPARE(image->paintedHeight(), 0.0);
633 QCOMPARE(image->sourceSize().width(), 200);
634 QCOMPARE(image->sourceSize().height(), 200);
635 QCOMPARE(image->paintedWidth(), 20.0);
636 QCOMPARE(image->paintedHeight(), 20.0);
641 static int numberOfWarnings = 0;
642 static void checkWarnings(QtMsgType, const char *msg)
644 if (!QString(msg).contains("QGLContext::makeCurrent(): Failed."))
649 void tst_qquickimage::nullPixmapPaint()
651 QQuickView *canvas = new QQuickView(0);
652 canvas->setSource(testFileUrl("nullpixmap.qml"));
655 QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
656 QTRY_VERIFY(image != 0);
657 image->setSource(SERVER_ADDR + QString("/no-such-file.png"));
659 QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings);
661 // used to print "QTransform::translate with NaN called"
662 QPixmap pm = QPixmap::fromImage(canvas->grabFrameBuffer());
663 qInstallMsgHandler(previousMsgHandler);
664 QVERIFY(numberOfWarnings == 0);
670 void tst_qquickimage::imageCrash_QTBUG_22125()
672 TestHTTPServer server(SERVER_PORT);
673 QVERIFY(server.isValid());
674 server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
677 QQuickView view(testFileUrl("qtbug_22125.qml"));
679 qApp->processEvents();
680 qApp->processEvents();
681 // shouldn't crash when the view drops out of scope due to
682 // QQuickPixmapData attempting to dereference a pointer to
683 // the destroyed reader.
686 // shouldn't crash when deleting cancelled QQmlPixmapReplys.
687 QTest::qWait(520); // Delay mode delays for 500 ms.
688 QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
689 QCoreApplication::processEvents();
692 void tst_qquickimage::sourceSize_data()
694 QTest::addColumn<int>("sourceWidth");
695 QTest::addColumn<int>("sourceHeight");
696 QTest::addColumn<qreal>("implicitWidth");
697 QTest::addColumn<qreal>("implicitHeight");
699 QTest::newRow("unscaled") << 0 << 0 << 300.0 << 300.0;
700 QTest::newRow("scale width") << 100 << 0 << 100.0 << 100.0;
701 QTest::newRow("scale height") << 0 << 150 << 150.0 << 150.0;
702 QTest::newRow("larger sourceSize") << 400 << 400 << 300.0 << 300.0;
705 void tst_qquickimage::sourceSize()
707 QFETCH(int, sourceWidth);
708 QFETCH(int, sourceHeight);
709 QFETCH(qreal, implicitWidth);
710 QFETCH(qreal, implicitHeight);
712 QQuickView *canvas = new QQuickView(0);
713 QQmlContext *ctxt = canvas->rootContext();
714 ctxt->setContextProperty("srcWidth", sourceWidth);
715 ctxt->setContextProperty("srcHeight", sourceHeight);
717 canvas->setSource(testFileUrl("sourceSize.qml"));
719 qApp->processEvents();
721 QQuickImage *image = qobject_cast<QQuickImage*>(canvas->rootObject());
724 QCOMPARE(image->sourceSize().width(), sourceWidth);
725 QCOMPARE(image->sourceSize().height(), sourceHeight);
726 QCOMPARE(image->implicitWidth(), implicitWidth);
727 QCOMPARE(image->implicitHeight(), implicitHeight);
732 QTEST_MAIN(tst_qquickimage)
734 #include "tst_qquickimage.moc"