1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QTextDocument>
47 #include <QtDeclarative/qdeclarativeengine.h>
48 #include <QtDeclarative/qdeclarativecomponent.h>
49 #include <QtDeclarative/qsgview.h>
50 #include <private/qsgimage_p.h>
51 #include <private/qsgimagebase_p.h>
52 #include <private/qsgloader_p.h>
53 #include <QtDeclarative/qdeclarativecontext.h>
54 #include <QtDeclarative/qdeclarativeexpression.h>
55 #include <QtTest/QSignalSpy>
56 #include <QtGui/QPainter>
57 #include <QtGui/QImageReader>
59 #include "../shared/util.h"
60 #include "../shared/testhttpserver.h"
62 #define SERVER_PORT 14451
63 #define SERVER_ADDR "http://127.0.0.1:14451"
65 class tst_qsgimage : public QObject
74 void imageSource_data();
77 void preserveAspectRatio();
84 void tiling_QTBUG_6716();
85 void tiling_QTBUG_6716_data();
87 void paintedWidthHeight();
88 void sourceSize_QTBUG_14303();
89 void sourceSize_QTBUG_16389();
90 void nullPixmapPaint();
94 T *findItem(QSGItem *parent, const QString &id, int index=-1);
96 QDeclarativeEngine engine;
99 tst_qsgimage::tst_qsgimage()
103 void tst_qsgimage::noSource()
105 QString componentStr = "import QtQuick 2.0\nImage { source: \"\" }";
106 QDeclarativeComponent component(&engine);
107 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
108 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
110 QCOMPARE(obj->source(), QUrl());
111 QVERIFY(obj->status() == QSGImage::Null);
112 QCOMPARE(obj->width(), 0.);
113 QCOMPARE(obj->height(), 0.);
114 QCOMPARE(obj->fillMode(), QSGImage::Stretch);
115 QCOMPARE(obj->progress(), 0.0);
120 void tst_qsgimage::imageSource_data()
122 QTest::addColumn<QString>("source");
123 QTest::addColumn<double>("width");
124 QTest::addColumn<double>("height");
125 QTest::addColumn<bool>("remote");
126 QTest::addColumn<bool>("async");
127 QTest::addColumn<bool>("cache");
128 QTest::addColumn<QString>("error");
130 QTest::newRow("local") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << true << "";
131 QTest::newRow("local no cache") << QUrl::fromLocalFile(TESTDATA("colors.png")).toString() << 120.0 << 120.0 << false << false << false << "";
132 QTest::newRow("local async") << QUrl::fromLocalFile(TESTDATA("colors1.png")).toString() << 120.0 << 120.0 << false << true << true << "";
133 QTest::newRow("local not found") << QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString() << 0.0 << 0.0 << false
134 << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file.png")).toString();
135 QTest::newRow("local async not found") << QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString() << 0.0 << 0.0 << false
136 << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(TESTDATA("no-such-file-1.png")).toString();
137 QTest::newRow("remote") << SERVER_ADDR "/colors.png" << 120.0 << 120.0 << true << false << true << "";
138 QTest::newRow("remote redirected") << SERVER_ADDR "/oldcolors.png" << 120.0 << 120.0 << true << false << false << "";
139 if (QImageReader::supportedImageFormats().contains("svg"))
140 QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << "";
142 QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
143 << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
147 void tst_qsgimage::imageSource()
149 QFETCH(QString, source);
150 QFETCH(double, width);
151 QFETCH(double, height);
152 QFETCH(bool, remote);
155 QFETCH(QString, error);
157 TestHTTPServer server(SERVER_PORT);
159 QVERIFY(server.isValid());
160 server.serveDirectory(TESTDATA(""));
161 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
164 if (!error.isEmpty())
165 QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
167 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + source + "\"; asynchronous: "
168 + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
169 + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
170 QDeclarativeComponent component(&engine);
171 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
172 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
176 QVERIFY(obj->asynchronous() == true);
178 QVERIFY(obj->asynchronous() == false);
181 QVERIFY(obj->cache() == true);
183 QVERIFY(obj->cache() == false);
186 QTRY_VERIFY(obj->status() == QSGImage::Loading);
188 QCOMPARE(obj->source(), remote ? source : QUrl(source));
190 if (error.isEmpty()) {
191 QTRY_VERIFY(obj->status() == QSGImage::Ready);
192 QCOMPARE(obj->width(), qreal(width));
193 QCOMPARE(obj->height(), qreal(height));
194 QCOMPARE(obj->fillMode(), QSGImage::Stretch);
195 QCOMPARE(obj->progress(), 1.0);
197 QTRY_VERIFY(obj->status() == QSGImage::Error);
203 void tst_qsgimage::clearSource()
205 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
206 QDeclarativeContext *ctxt = engine.rootContext();
207 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
208 QDeclarativeComponent component(&engine);
209 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
210 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
212 QVERIFY(obj->status() == QSGImage::Ready);
213 QCOMPARE(obj->width(), 120.);
214 QCOMPARE(obj->height(), 120.);
215 QCOMPARE(obj->progress(), 1.0);
217 ctxt->setContextProperty("srcImage", "");
218 QVERIFY(obj->source().isEmpty());
219 QVERIFY(obj->status() == QSGImage::Null);
220 QCOMPARE(obj->width(), 0.);
221 QCOMPARE(obj->height(), 0.);
222 QCOMPARE(obj->progress(), 0.0);
227 void tst_qsgimage::resized()
229 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; width: 300; height: 300 }";
230 QDeclarativeComponent component(&engine);
231 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
232 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
234 QCOMPARE(obj->width(), 300.);
235 QCOMPARE(obj->height(), 300.);
236 QCOMPARE(obj->fillMode(), QSGImage::Stretch);
241 void tst_qsgimage::preserveAspectRatio()
243 QSGView *canvas = new QSGView(0);
246 canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
247 QSGImage *image = qobject_cast<QSGImage*>(canvas->rootObject());
249 image->setWidth(80.0);
250 QCOMPARE(image->width(), 80.);
251 QCOMPARE(image->height(), 80.);
253 canvas->setSource(QUrl::fromLocalFile(TESTDATA("aspectratio.qml")));
254 image = qobject_cast<QSGImage*>(canvas->rootObject());
255 image->setHeight(60.0);
257 QCOMPARE(image->height(), 60.);
258 QCOMPARE(image->width(), 60.);
262 void tst_qsgimage::smooth()
264 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + TESTDATA("colors.png") + "\"; smooth: true; width: 300; height: 300 }";
265 QDeclarativeComponent component(&engine);
266 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
267 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
269 QCOMPARE(obj->width(), 300.);
270 QCOMPARE(obj->height(), 300.);
271 QCOMPARE(obj->smooth(), true);
272 QCOMPARE(obj->fillMode(), QSGImage::Stretch);
277 void tst_qsgimage::mirror()
279 QMap<QSGImage::FillMode, QImage> screenshots;
280 QList<QSGImage::FillMode> fillModes;
281 fillModes << QSGImage::Stretch << QSGImage::PreserveAspectFit << QSGImage::PreserveAspectCrop
282 << QSGImage::Tile << QSGImage::TileVertically << QSGImage::TileHorizontally;
287 foreach (QSGImage::FillMode fillMode, fillModes) {
288 QSGView *canvas = new QSGView;
289 canvas->setSource(QUrl::fromLocalFile(TESTDATA("mirror.qml")));
291 QSGImage *obj = canvas->rootObject()->findChild<QSGImage*>("image");
294 obj->setFillMode(fillMode);
295 obj->setProperty("mirror", true);
298 QImage screenshot = canvas->grabFrameBuffer();
299 screenshots[fillMode] = screenshot;
303 foreach (QSGImage::FillMode fillMode, fillModes) {
305 QVERIFY(srcPixmap.load(TESTDATA("pattern.png")));
307 QPixmap expected(width, height);
309 QPainter p_e(&expected);
310 QTransform transform;
311 transform.translate(width, 0).scale(-1, 1.0);
312 p_e.setTransform(transform);
315 case QSGImage::Stretch:
316 p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
318 case QSGImage::PreserveAspectFit:
319 p_e.drawPixmap(QRect(25, 0, height, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
321 case QSGImage::PreserveAspectCrop:
323 qreal ratio = width/srcPixmap.width(); // width is the longer side
324 QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio);
325 rect.moveCenter(QRect(0, 0, width, height).center());
326 p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
330 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
332 case QSGImage::TileVertically:
333 transform.scale(width / srcPixmap.width(), 1.0);
334 p_e.setTransform(transform);
335 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
337 case QSGImage::TileHorizontally:
338 transform.scale(1.0, height / srcPixmap.height());
339 p_e.setTransform(transform);
340 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
344 QImage img = expected.toImage();
346 QEXPECT_FAIL("", "QTBUG-21005 fails", Continue);
348 QCOMPARE(screenshots[fillMode], img);
352 void tst_qsgimage::svg()
354 if (!QImageReader::supportedImageFormats().contains("svg"))
355 QSKIP("svg support not available");
357 QString src = QUrl::fromLocalFile(TESTDATA("heart.svg")).toString();
358 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
359 QDeclarativeComponent component(&engine);
360 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
361 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
363 QCOMPARE(obj->width(), 300.0);
364 QCOMPARE(obj->height(), 300.0);
365 obj->setSourceSize(QSize(200,200));
367 QCOMPARE(obj->width(), 200.0);
368 QCOMPARE(obj->height(), 200.0);
372 void tst_qsgimage::geometry_data()
374 QTest::addColumn<QString>("fillMode");
375 QTest::addColumn<bool>("explicitWidth");
376 QTest::addColumn<bool>("explicitHeight");
377 QTest::addColumn<double>("itemWidth");
378 QTest::addColumn<double>("paintedWidth");
379 QTest::addColumn<double>("boundingWidth");
380 QTest::addColumn<double>("itemHeight");
381 QTest::addColumn<double>("paintedHeight");
382 QTest::addColumn<double>("boundingHeight");
384 // tested image has width 200, height 100
386 // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match
387 QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
388 QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0;
389 QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0;
390 QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0;
392 // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match
393 QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
394 QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0;
395 QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
396 QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
398 // bounding rect, painted rect and item rect are equal in stretching and tiling images
399 QStringList fillModes;
400 fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
401 foreach (QString fillMode, fillModes) {
402 QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
403 QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
404 QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
405 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;
409 void tst_qsgimage::geometry()
411 QFETCH(QString, fillMode);
412 QFETCH(bool, explicitWidth);
413 QFETCH(bool, explicitHeight);
414 QFETCH(double, itemWidth);
415 QFETCH(double, itemHeight);
416 QFETCH(double, paintedWidth);
417 QFETCH(double, paintedHeight);
418 QFETCH(double, boundingWidth);
419 QFETCH(double, boundingHeight);
421 QString src = QUrl::fromLocalFile(TESTDATA("rect.png")).toString();
422 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; ";
425 componentStr.append("width: 300; ");
427 componentStr.append("height: 400; ");
428 componentStr.append("}");
429 QDeclarativeComponent component(&engine);
430 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
431 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
434 QCOMPARE(obj->width(), itemWidth);
435 QCOMPARE(obj->paintedWidth(), paintedWidth);
436 QCOMPARE(obj->boundingRect().width(), boundingWidth);
438 QCOMPARE(obj->height(), itemHeight);
439 QCOMPARE(obj->paintedHeight(), paintedHeight);
440 QCOMPARE(obj->boundingRect().height(), boundingHeight);
444 void tst_qsgimage::big()
446 // If the JPEG loader does not implement scaling efficiently, it would
447 // have to build a 400 MB image. That would be a bug in the JPEG loader.
449 QString src = QUrl::fromLocalFile(TESTDATA("big.jpeg")).toString();
450 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }";
452 QDeclarativeComponent component(&engine);
453 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
454 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
456 QCOMPARE(obj->width(), 100.0);
457 QCOMPARE(obj->height(), 256.0);
462 void tst_qsgimage::tiling_QTBUG_6716()
464 QFETCH(QString, source);
466 QSGView *canvas = new QSGView(0);
467 canvas->setSource(QUrl::fromLocalFile(TESTDATA(source)));
469 qApp->processEvents();
471 QSGImage *tiling = findItem<QSGImage>(canvas->rootObject(), "tiling");
473 QVERIFY(tiling != 0);
474 QImage img = canvas->grabFrameBuffer();
475 for (int x = 0; x < tiling->width(); ++x) {
476 for (int y = 0; y < tiling->height(); ++y) {
477 QEXPECT_FAIL("horizontal_tiling", "QTBUG-21005 - stable failing test", Abort);
478 QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
484 void tst_qsgimage::tiling_QTBUG_6716_data()
486 QTest::addColumn<QString>("source");
487 QTest::newRow("vertical_tiling") << "vtiling.qml";
488 QTest::newRow("horizontal_tiling") << "htiling.qml";
491 void tst_qsgimage::noLoading()
493 TestHTTPServer server(SERVER_PORT);
494 QVERIFY(server.isValid());
495 server.serveDirectory(TESTDATA(""));
496 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
498 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage; cache: true }";
499 QDeclarativeContext *ctxt = engine.rootContext();
500 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart.png")));
501 QDeclarativeComponent component(&engine);
502 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
503 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
505 QVERIFY(obj->status() == QSGImage::Ready);
507 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
508 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
509 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QSGImageBase::Status)));
511 // Loading local file
512 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
513 QTRY_VERIFY(obj->status() == QSGImage::Ready);
514 QTRY_VERIFY(obj->progress() == 1.0);
515 QTRY_COMPARE(sourceSpy.count(), 1);
516 QTRY_COMPARE(progressSpy.count(), 0);
517 QTRY_COMPARE(statusSpy.count(), 0);
519 // Loading remote file
520 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
521 QTRY_VERIFY(obj->status() == QSGImage::Loading);
522 QTRY_VERIFY(obj->progress() == 0.0);
523 QTRY_VERIFY(obj->status() == QSGImage::Ready);
524 QTRY_VERIFY(obj->progress() == 1.0);
525 QTRY_COMPARE(sourceSpy.count(), 2);
526 QTRY_COMPARE(progressSpy.count(), 2);
527 QTRY_COMPARE(statusSpy.count(), 2);
529 // Loading remote file again - should not go through 'Loading' state.
530 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("green.png")));
531 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
532 QTRY_VERIFY(obj->status() == QSGImage::Ready);
533 QTRY_VERIFY(obj->progress() == 1.0);
534 QTRY_COMPARE(sourceSpy.count(), 4);
535 QTRY_COMPARE(progressSpy.count(), 2);
536 QTRY_COMPARE(statusSpy.count(), 2);
541 void tst_qsgimage::paintedWidthHeight()
544 QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
545 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }";
547 QDeclarativeComponent component(&engine);
548 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
549 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
551 QCOMPARE(obj->width(), 200.0);
552 QCOMPARE(obj->height(), 25.0);
553 QCOMPARE(obj->paintedWidth(), 25.0);
554 QCOMPARE(obj->paintedHeight(), 25.0);
560 QString src = QUrl::fromLocalFile(TESTDATA("heart.png")).toString();
561 QString componentStr = "import QtQuick 2.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }";
562 QDeclarativeComponent component(&engine);
563 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
564 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
566 QCOMPARE(obj->width(), 26.0);
567 QCOMPARE(obj->height(), 175.0);
568 QCOMPARE(obj->paintedWidth(), 26.0);
569 QCOMPARE(obj->paintedHeight(), 26.0);
575 void tst_qsgimage::sourceSize_QTBUG_14303()
577 QString componentStr = "import QtQuick 2.0\nImage { source: srcImage }";
578 QDeclarativeContext *ctxt = engine.rootContext();
579 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
580 QDeclarativeComponent component(&engine);
581 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
582 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
584 QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
586 QTRY_VERIFY(obj != 0);
587 QTRY_VERIFY(obj->status() == QSGImage::Ready);
589 QTRY_COMPARE(obj->sourceSize().width(), 200);
590 QTRY_COMPARE(obj->sourceSize().height(), 200);
591 QTRY_COMPARE(sourceSizeSpy.count(), 0);
593 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.png")));
594 QTRY_COMPARE(obj->sourceSize().width(), 120);
595 QTRY_COMPARE(obj->sourceSize().height(), 120);
596 QTRY_COMPARE(sourceSizeSpy.count(), 1);
598 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("heart200.png")));
599 QTRY_COMPARE(obj->sourceSize().width(), 200);
600 QTRY_COMPARE(obj->sourceSize().height(), 200);
601 QTRY_COMPARE(sourceSizeSpy.count(), 2);
606 void tst_qsgimage::sourceSize_QTBUG_16389()
608 QSGView *canvas = new QSGView(0);
609 canvas->setSource(QUrl::fromLocalFile(TESTDATA("qtbug_16389.qml")));
611 qApp->processEvents();
613 QSGImage *image = findItem<QSGImage>(canvas->rootObject(), "iconImage");
614 QSGItem *handle = findItem<QSGItem>(canvas->rootObject(), "blueHandle");
616 QCOMPARE(image->sourceSize().width(), 200);
617 QCOMPARE(image->sourceSize().height(), 200);
618 QCOMPARE(image->paintedWidth(), 0.0);
619 QCOMPARE(image->paintedHeight(), 0.0);
623 QCOMPARE(image->sourceSize().width(), 200);
624 QCOMPARE(image->sourceSize().height(), 200);
625 QCOMPARE(image->paintedWidth(), 20.0);
626 QCOMPARE(image->paintedHeight(), 20.0);
629 static int numberOfWarnings = 0;
630 static void checkWarnings(QtMsgType, const char *msg)
632 if (!QString(msg).contains("QGLContext::makeCurrent(): Failed."))
637 void tst_qsgimage::nullPixmapPaint()
639 QSGView *canvas = new QSGView(0);
640 canvas->setSource(QUrl::fromLocalFile(TESTDATA("nullpixmap.qml")));
643 QSGImage *image = qobject_cast<QSGImage*>(canvas->rootObject());
644 QTRY_VERIFY(image != 0);
645 image->setSource(SERVER_ADDR + QString("/no-such-file.png"));
647 QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings);
649 // used to print "QTransform::translate with NaN called"
650 QPixmap pm = QPixmap::fromImage(canvas->grabFrameBuffer());
651 qInstallMsgHandler(previousMsgHandler);
652 QVERIFY(numberOfWarnings == 0);
657 Find an item with the specified objectName. If index is supplied then the
658 item must also evaluate the {index} expression equal to index
661 T *tst_qsgimage::findItem(QSGItem *parent, const QString &objectName, int index)
663 const QMetaObject &mo = T::staticMetaObject;
664 //qDebug() << parent->childItems().count() << "children";
665 for (int i = 0; i < parent->childItems().count(); ++i) {
666 QSGItem *item = qobject_cast<QSGItem*>(parent->childItems().at(i));
669 //qDebug() << "try" << item;
670 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
672 QDeclarativeExpression e(qmlContext(item), item, "index");
673 if (e.evaluate().toInt() == index)
674 return static_cast<T*>(item);
676 return static_cast<T*>(item);
679 item = findItem<T>(item, objectName, index);
681 return static_cast<T*>(item);
687 QTEST_MAIN(tst_qsgimage)
689 #include "tst_qsgimage.moc"