1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <QtQuick1/qdeclarativeview.h>
50 #include <QtQuick1/private/qdeclarativeimage_p.h>
51 #include <QtQuick1/private/qdeclarativeimagebase_p.h>
52 #include <QtQuick1/private/qdeclarativeloader_p.h>
53 #include <QtDeclarative/qdeclarativecontext.h>
54 #include <QtDeclarative/qdeclarativeexpression.h>
55 #include <QtTest/QSignalSpy>
57 #include "../../shared/testhttpserver.h"
59 #define SERVER_PORT 14451
60 #define SERVER_ADDR "http://127.0.0.1:14451"
62 class tst_qdeclarativeimage : public QObject
66 tst_qdeclarativeimage();
71 void imageSource_data();
74 void preserveAspectRatio();
82 void tiling_QTBUG_6716();
84 void paintedWidthHeight();
85 void sourceSize_QTBUG_14303();
86 void sourceSize_QTBUG_16389();
87 void nullPixmapPaint();
88 void resetSourceSize();
89 void testQtQuick11Attributes();
90 void testQtQuick11Attributes_data();
94 T *findItem(QGraphicsObject *parent, const QString &id, int index=-1);
96 QDeclarativeEngine engine;
99 tst_qdeclarativeimage::tst_qdeclarativeimage()
103 void tst_qdeclarativeimage::noSource()
105 QString componentStr = "import QtQuick 1.0\nImage { source: \"\" }";
106 QDeclarativeComponent component(&engine);
107 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
108 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
110 QCOMPARE(obj->source(), QUrl());
111 QVERIFY(obj->status() == QDeclarative1Image::Null);
112 QCOMPARE(obj->width(), 0.);
113 QCOMPARE(obj->height(), 0.);
114 QCOMPARE(obj->fillMode(), QDeclarative1Image::Stretch);
115 QCOMPARE(obj->progress(), 0.0);
120 void tst_qdeclarativeimage::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(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << true << "";
131 QTest::newRow("local no cache") << QUrl::fromLocalFile(SRCDIR "/data/colors.png").toString() << 120.0 << 120.0 << false << false << false << "";
132 QTest::newRow("local async") << QUrl::fromLocalFile(SRCDIR "/data/colors1.png").toString() << 120.0 << 120.0 << false << true << true << "";
133 QTest::newRow("local not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString() << 0.0 << 0.0 << false
134 << false << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/no-such-file.png").toString();
135 QTest::newRow("local async not found") << QUrl::fromLocalFile(SRCDIR "/data/no-such-file-1.png").toString() << 0.0 << 0.0 << false
136 << true << true << "file::2:1: QML Image: Cannot open: " + QUrl::fromLocalFile(SRCDIR "/data/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 QTest::newRow("remote svg") << SERVER_ADDR "/heart.svg" << 550.0 << 500.0 << true << false << false << "";
140 QTest::newRow("remote not found") << SERVER_ADDR "/no-such-file.png" << 0.0 << 0.0 << true
141 << false << true << "file::2:1: QML Image: Error downloading " SERVER_ADDR "/no-such-file.png - server replied: Not found";
145 void tst_qdeclarativeimage::imageSource()
147 QFETCH(QString, source);
148 QFETCH(double, width);
149 QFETCH(double, height);
150 QFETCH(bool, remote);
153 QFETCH(QString, error);
155 TestHTTPServer server(SERVER_PORT);
157 QVERIFY(server.isValid());
158 server.serveDirectory(SRCDIR "/data");
159 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
162 if (!error.isEmpty())
163 QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
165 QString componentStr = "import QtQuick 1.1\nImage { source: \"" + source + "\"; asynchronous: "
166 + (async ? QLatin1String("true") : QLatin1String("false")) + "; cache: "
167 + (cache ? QLatin1String("true") : QLatin1String("false")) + " }";
168 QDeclarativeComponent component(&engine);
169 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
170 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
174 QVERIFY(obj->asynchronous() == true);
176 QVERIFY(obj->asynchronous() == false);
179 QVERIFY(obj->cache() == true);
181 QVERIFY(obj->cache() == false);
184 QTRY_VERIFY(obj->status() == QDeclarative1Image::Loading);
186 QCOMPARE(obj->source(), remote ? source : QUrl(source));
188 if (error.isEmpty()) {
189 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
190 QCOMPARE(obj->width(), qreal(width));
191 QCOMPARE(obj->height(), qreal(height));
192 QCOMPARE(obj->fillMode(), QDeclarative1Image::Stretch);
193 QCOMPARE(obj->progress(), 1.0);
195 QTRY_VERIFY(obj->status() == QDeclarative1Image::Error);
201 void tst_qdeclarativeimage::clearSource()
203 QString componentStr = "import QtQuick 1.0\nImage { source: srcImage }";
204 QDeclarativeContext *ctxt = engine.rootContext();
205 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png"));
206 QDeclarativeComponent component(&engine);
207 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
208 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
210 QVERIFY(obj->status() == QDeclarative1Image::Ready);
211 QCOMPARE(obj->width(), 120.);
212 QCOMPARE(obj->height(), 120.);
213 QCOMPARE(obj->progress(), 1.0);
215 ctxt->setContextProperty("srcImage", "");
216 QVERIFY(obj->source().isEmpty());
217 QVERIFY(obj->status() == QDeclarative1Image::Null);
218 QCOMPARE(obj->width(), 0.);
219 QCOMPARE(obj->height(), 0.);
220 QCOMPARE(obj->progress(), 0.0);
225 void tst_qdeclarativeimage::resized()
227 QString componentStr = "import QtQuick 1.0\nImage { source: \"" SRCDIR "/data/colors.png\"; width: 300; height: 300 }";
228 QDeclarativeComponent component(&engine);
229 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
230 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
232 QCOMPARE(obj->width(), 300.);
233 QCOMPARE(obj->height(), 300.);
234 QCOMPARE(obj->fillMode(), QDeclarative1Image::Stretch);
239 void tst_qdeclarativeimage::preserveAspectRatio()
241 QDeclarativeView *canvas = new QDeclarativeView(0);
244 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/aspectratio.qml"));
245 QDeclarative1Image *image = qobject_cast<QDeclarative1Image*>(canvas->rootObject());
247 QCOMPARE(image->property("widthChange").toInt(), 1);
248 QCOMPARE(image->property("heightChange").toInt(), 1);
249 image->setWidth(80.0);
250 QCOMPARE(image->property("widthChange").toInt(), 2);
251 QCOMPARE(image->property("heightChange").toInt(), 2);
252 QCOMPARE(image->width(), 80.);
253 QCOMPARE(image->height(), 80.);
255 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/aspectratio.qml"));
256 image = qobject_cast<QDeclarative1Image*>(canvas->rootObject());
258 QCOMPARE(image->property("widthChange").toInt(), 1);
259 QCOMPARE(image->property("heightChange").toInt(), 1);
260 image->setHeight(60.0);
261 QCOMPARE(image->property("widthChange").toInt(), 2);
262 QCOMPARE(image->property("heightChange").toInt(), 2);
263 QCOMPARE(image->height(), 60.);
264 QCOMPARE(image->width(), 60.);
268 void tst_qdeclarativeimage::smooth()
270 QString componentStr = "import QtQuick 1.0\nImage { source: \"" SRCDIR "/data/colors.png\"; smooth: true; width: 300; height: 300 }";
271 QDeclarativeComponent component(&engine);
272 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
273 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
275 QCOMPARE(obj->width(), 300.);
276 QCOMPARE(obj->height(), 300.);
277 QCOMPARE(obj->smooth(), true);
278 QCOMPARE(obj->fillMode(), QDeclarative1Image::Stretch);
283 void tst_qdeclarativeimage::mirror()
285 QFETCH(int, fillMode);
290 QString src = QUrl::fromLocalFile(SRCDIR "/data/heart200.png").toString();
291 QString componentStr = "import QtQuick 1.1\nImage { source: \"" + src + "\"; }";
293 QDeclarativeComponent component(&engine);
294 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
295 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
298 obj->setProperty("width", width);
299 obj->setProperty("height", height);
300 obj->setFillMode((QDeclarative1Image::FillMode)fillMode);
301 obj->setProperty("mirror", true);
303 QGraphicsScene scene;
304 scene.addItem(qobject_cast<QGraphicsObject *>(obj));
305 QPixmap screenshot(width, height);
307 QPainter p_screenshot(&screenshot);
308 scene.render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height));
311 QVERIFY(srcPixmap.load(SRCDIR "/data/heart200.png"));
313 QPixmap expected(width, height);
315 QPainter p_e(&expected);
316 QTransform transform;
317 transform.translate(width, 0).scale(-1, 1.0);
318 p_e.setTransform(transform);
321 case QDeclarative1Image::Stretch:
322 p_e.drawPixmap(QRect(0, 0, width, height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
324 case QDeclarative1Image::PreserveAspectFit:
325 QEXPECT_FAIL("", "QTBUG-19538", Continue);
326 p_e.drawPixmap(QRect(25, 0, width / (width/height), height), srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
328 case QDeclarative1Image::PreserveAspectCrop:
330 qreal ratio = width/srcPixmap.width(); // width is the longer side
331 QRect rect(0, 0, srcPixmap.width()*ratio, srcPixmap.height()*ratio);
332 rect.moveCenter(QRect(0, 0, width, height).center());
333 p_e.drawPixmap(rect, srcPixmap, QRect(0, 0, srcPixmap.width(), srcPixmap.height()));
336 case QDeclarative1Image::Tile:
337 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
339 case QDeclarative1Image::TileVertically:
340 transform.scale(width / srcPixmap.width(), 1.0);
341 p_e.setTransform(transform);
342 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
344 case QDeclarative1Image::TileHorizontally:
345 transform.scale(1.0, height / srcPixmap.height());
346 p_e.setTransform(transform);
347 p_e.drawTiledPixmap(QRect(0, 0, width, height), srcPixmap);
351 QCOMPARE(screenshot, expected);
356 void tst_qdeclarativeimage::mirror_data()
358 QTest::addColumn<int>("fillMode");
360 QTest::newRow("Stretch") << int(QDeclarative1Image::Stretch);
361 QTest::newRow("PreserveAspectFit") << int(QDeclarative1Image::PreserveAspectFit);
362 QTest::newRow("PreserveAspectCrop") << int(QDeclarative1Image::PreserveAspectCrop);
363 QTest::newRow("Tile") << int(QDeclarative1Image::Tile);
364 QTest::newRow("TileVertically") << int(QDeclarative1Image::TileVertically);
365 QTest::newRow("TileHorizontally") << int(QDeclarative1Image::TileHorizontally);
368 void tst_qdeclarativeimage::svg()
370 QString src = QUrl::fromLocalFile(SRCDIR "/data/heart.svg").toString();
371 QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; sourceSize.width: 300; sourceSize.height: 300 }";
372 QDeclarativeComponent component(&engine);
373 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
374 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
376 QCOMPARE(obj->pixmap().width(), 300);
377 QCOMPARE(obj->pixmap().height(), 300);
378 QCOMPARE(obj->width(), 300.0);
379 QCOMPARE(obj->height(), 300.0);
380 #if defined(Q_OS_LINUX)
381 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart.png"));
382 #elif defined(Q_OS_WIN32)
383 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart-win32.png"));
386 obj->setSourceSize(QSize(200,200));
388 QCOMPARE(obj->pixmap().width(), 200);
389 QCOMPARE(obj->pixmap().height(), 200);
390 QCOMPARE(obj->width(), 200.0);
391 QCOMPARE(obj->height(), 200.0);
392 #if defined(Q_OS_LINUX)
393 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart200.png"));
394 #elif defined(Q_OS_WIN32)
395 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart200-win32.png"));
400 void tst_qdeclarativeimage::geometry_data()
402 QTest::addColumn<QString>("fillMode");
403 QTest::addColumn<bool>("explicitWidth");
404 QTest::addColumn<bool>("explicitHeight");
405 QTest::addColumn<double>("itemWidth");
406 QTest::addColumn<double>("paintedWidth");
407 QTest::addColumn<double>("boundingWidth");
408 QTest::addColumn<double>("itemHeight");
409 QTest::addColumn<double>("paintedHeight");
410 QTest::addColumn<double>("boundingHeight");
412 // tested image has width 200, height 100
414 // bounding rect and item rect are equal with fillMode PreserveAspectFit, painted rect may be smaller if the aspect ratio doesn't match
415 QTest::newRow("PreserveAspectFit") << "PreserveAspectFit" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
416 QTest::newRow("PreserveAspectFit explicit width 300") << "PreserveAspectFit" << true << false << 300.0 << 200.0 << 300.0 << 100.0 << 100.0 << 100.0;
417 QTest::newRow("PreserveAspectFit explicit height 400") << "PreserveAspectFit" << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 100.0 << 400.0;
418 QTest::newRow("PreserveAspectFit explicit width 300, height 400") << "PreserveAspectFit" << true << true << 300.0 << 300.0 << 300.0 << 400.0 << 150.0 << 400.0;
420 // bounding rect and painted rect are equal with fillMode PreserveAspectCrop, item rect may be smaller if the aspect ratio doesn't match
421 QTest::newRow("PreserveAspectCrop") << "PreserveAspectCrop" << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
422 QTest::newRow("PreserveAspectCrop explicit width 300") << "PreserveAspectCrop" << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 150.0 << 150.0;
423 QTest::newRow("PreserveAspectCrop explicit height 400") << "PreserveAspectCrop" << false << true << 200.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
424 QTest::newRow("PreserveAspectCrop explicit width 300, height 400") << "PreserveAspectCrop" << true << true << 300.0 << 800.0 << 800.0 << 400.0 << 400.0 << 400.0;
426 // bounding rect, painted rect and item rect are equal in stretching and tiling images
427 QStringList fillModes;
428 fillModes << "Stretch" << "Tile" << "TileVertically" << "TileHorizontally";
429 foreach (QString fillMode, fillModes) {
430 QTest::newRow(fillMode.toLatin1()) << fillMode << false << false << 200.0 << 200.0 << 200.0 << 100.0 << 100.0 << 100.0;
431 QTest::newRow(QString(fillMode + " explicit width 300").toLatin1()) << fillMode << true << false << 300.0 << 300.0 << 300.0 << 100.0 << 100.0 << 100.0;
432 QTest::newRow(QString(fillMode + " explicit height 400").toLatin1()) << fillMode << false << true << 200.0 << 200.0 << 200.0 << 400.0 << 400.0 << 400.0;
433 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;
437 void tst_qdeclarativeimage::geometry()
439 QFETCH(QString, fillMode);
440 QFETCH(bool, explicitWidth);
441 QFETCH(bool, explicitHeight);
442 QFETCH(double, itemWidth);
443 QFETCH(double, itemHeight);
444 QFETCH(double, paintedWidth);
445 QFETCH(double, paintedHeight);
446 QFETCH(double, boundingWidth);
447 QFETCH(double, boundingHeight);
449 QString src = QUrl::fromLocalFile(SRCDIR "/data/rect.png").toString();
450 QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; fillMode: Image." + fillMode + "; ";
453 componentStr.append("width: 300; ");
455 componentStr.append("height: 400; ");
456 componentStr.append("}");
457 QDeclarativeComponent component(&engine);
458 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
459 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
462 QCOMPARE(obj->width(), itemWidth);
463 QCOMPARE(obj->paintedWidth(), paintedWidth);
464 QCOMPARE(obj->boundingRect().width(), boundingWidth);
466 QCOMPARE(obj->height(), itemHeight);
467 QCOMPARE(obj->paintedHeight(), paintedHeight);
468 QCOMPARE(obj->boundingRect().height(), boundingHeight);
472 void tst_qdeclarativeimage::big()
474 // If the JPEG loader does not implement scaling efficiently, it would
475 // have to build a 400 MB image. That would be a bug in the JPEG loader.
477 QString src = QUrl::fromLocalFile(SRCDIR "/data/big.jpeg").toString();
478 QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; width: 100; sourceSize.height: 256 }";
480 QDeclarativeComponent component(&engine);
481 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
482 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
484 QCOMPARE(obj->pixmap().width(), 256);
485 QCOMPARE(obj->pixmap().height(), 256);
486 QCOMPARE(obj->width(), 100.0);
487 QCOMPARE(obj->height(), 256.0);
488 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/big256.png"));
493 void tst_qdeclarativeimage::tiling_QTBUG_6716()
495 QDeclarativeView *canvas = new QDeclarativeView(0);
496 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/tiling.qml"));
498 qApp->processEvents();
500 QDeclarative1Image *vTiling = findItem<QDeclarative1Image>(canvas->rootObject(), "vTiling");
501 QDeclarative1Image *hTiling = findItem<QDeclarative1Image>(canvas->rootObject(), "hTiling");
503 QVERIFY(vTiling != 0);
504 QVERIFY(hTiling != 0);
507 QPixmap pm(vTiling->width(), vTiling->height());
509 vTiling->paint(&p, 0, 0);
511 QImage img = pm.toImage();
512 for (int x = 0; x < vTiling->width(); ++x) {
513 for (int y = 0; y < vTiling->height(); ++y) {
514 QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
520 QPixmap pm(hTiling->width(), hTiling->height());
522 hTiling->paint(&p, 0, 0);
524 QImage img = pm.toImage();
525 for (int x = 0; x < hTiling->width(); ++x) {
526 for (int y = 0; y < hTiling->height(); ++y) {
527 QVERIFY(img.pixel(x, y) == qRgb(0, 255, 0));
535 void tst_qdeclarativeimage::noLoading()
537 TestHTTPServer server(SERVER_PORT);
538 QVERIFY(server.isValid());
539 server.serveDirectory(SRCDIR "/data");
540 server.addRedirect("oldcolors.png", SERVER_ADDR "/colors.png");
542 QString componentStr = "import QtQuick 1.1\nImage { source: srcImage; cache: true }";
543 QDeclarativeContext *ctxt = engine.rootContext();
544 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/heart.png"));
545 QDeclarativeComponent component(&engine);
546 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
547 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
549 QVERIFY(obj->status() == QDeclarative1Image::Ready);
551 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
552 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
553 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QDeclarative1ImageBase::Status)));
555 // Loading local file
556 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/green.png"));
557 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
558 QTRY_VERIFY(obj->progress() == 1.0);
559 QTRY_COMPARE(sourceSpy.count(), 1);
560 QTRY_COMPARE(progressSpy.count(), 0);
561 QTRY_COMPARE(statusSpy.count(), 0);
563 // Loading remote file
564 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
565 QTRY_VERIFY(obj->status() == QDeclarative1Image::Loading);
566 QTRY_VERIFY(obj->progress() == 0.0);
567 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
568 QTRY_VERIFY(obj->progress() == 1.0);
569 QTRY_COMPARE(sourceSpy.count(), 2);
570 QTRY_COMPARE(progressSpy.count(), 2);
571 QTRY_COMPARE(statusSpy.count(), 2);
573 // Loading remote file again - should not go through 'Loading' state.
574 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/green.png"));
575 ctxt->setContextProperty("srcImage", QString(SERVER_ADDR) + "/rect.png");
576 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
577 QTRY_VERIFY(obj->progress() == 1.0);
578 QTRY_COMPARE(sourceSpy.count(), 4);
579 QTRY_COMPARE(progressSpy.count(), 2);
580 QTRY_COMPARE(statusSpy.count(), 2);
585 void tst_qdeclarativeimage::paintedWidthHeight()
588 QString src = QUrl::fromLocalFile(SRCDIR "/data/heart.png").toString();
589 QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; width: 200; height: 25; fillMode: Image.PreserveAspectFit }";
591 QDeclarativeComponent component(&engine);
592 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
593 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
595 QCOMPARE(obj->pixmap().width(), 300);
596 QCOMPARE(obj->pixmap().height(), 300);
597 QCOMPARE(obj->width(), 200.0);
598 QCOMPARE(obj->height(), 25.0);
599 QCOMPARE(obj->paintedWidth(), 25.0);
600 QCOMPARE(obj->paintedHeight(), 25.0);
601 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart.png"));
607 QString src = QUrl::fromLocalFile(SRCDIR "/data/heart.png").toString();
608 QString componentStr = "import QtQuick 1.0\nImage { source: \"" + src + "\"; width: 26; height: 175; fillMode: Image.PreserveAspectFit }";
609 QDeclarativeComponent component(&engine);
610 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
611 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
613 QCOMPARE(obj->pixmap().width(), 300);
614 QCOMPARE(obj->pixmap().height(), 300);
615 QCOMPARE(obj->width(), 26.0);
616 QCOMPARE(obj->height(), 175.0);
617 QCOMPARE(obj->paintedWidth(), 26.0);
618 QCOMPARE(obj->paintedHeight(), 26.0);
619 QCOMPARE(obj->pixmap(), QPixmap(SRCDIR "/data/heart.png"));
625 void tst_qdeclarativeimage::sourceSize_QTBUG_14303()
627 QString componentStr = "import QtQuick 1.0\nImage { source: srcImage }";
628 QDeclarativeContext *ctxt = engine.rootContext();
629 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/heart200.png"));
630 QDeclarativeComponent component(&engine);
631 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
632 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
634 QSignalSpy sourceSizeSpy(obj, SIGNAL(sourceSizeChanged()));
636 QTRY_VERIFY(obj != 0);
637 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
639 QTRY_COMPARE(obj->sourceSize().width(), 200);
640 QTRY_COMPARE(obj->sourceSize().height(), 200);
641 QTRY_COMPARE(sourceSizeSpy.count(), 0);
643 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.png"));
644 QTRY_COMPARE(obj->sourceSize().width(), 120);
645 QTRY_COMPARE(obj->sourceSize().height(), 120);
646 QTRY_COMPARE(sourceSizeSpy.count(), 1);
648 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/heart200.png"));
649 QTRY_COMPARE(obj->sourceSize().width(), 200);
650 QTRY_COMPARE(obj->sourceSize().height(), 200);
651 QTRY_COMPARE(sourceSizeSpy.count(), 2);
656 void tst_qdeclarativeimage::sourceSize_QTBUG_16389()
658 QDeclarativeView *canvas = new QDeclarativeView(0);
659 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug_16389.qml"));
661 qApp->processEvents();
663 QDeclarative1Image *image = findItem<QDeclarative1Image>(canvas->rootObject(), "iconImage");
664 QDeclarativeItem *handle = findItem<QDeclarativeItem>(canvas->rootObject(), "blueHandle");
666 QCOMPARE(image->sourceSize().width(), 200);
667 QCOMPARE(image->sourceSize().height(), 200);
668 QCOMPARE(image->paintedWidth(), 0.0);
669 QCOMPARE(image->paintedHeight(), 0.0);
673 QCOMPARE(image->sourceSize().width(), 200);
674 QCOMPARE(image->sourceSize().height(), 200);
675 QCOMPARE(image->paintedWidth(), 20.0);
676 QCOMPARE(image->paintedHeight(), 20.0);
679 static int numberOfWarnings = 0;
680 static void checkWarnings(QtMsgType, const char *)
686 void tst_qdeclarativeimage::nullPixmapPaint()
688 QString componentStr = QString("import QtQuick 1.0\nImage { width: 10; height:10; fillMode: Image.PreserveAspectFit; source: \"")
689 + SERVER_ADDR + QString("/no-such-file.png\" }");
690 QDeclarativeComponent component(&engine);
691 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
692 QDeclarative1Image *image = qobject_cast<QDeclarative1Image*>(component.create());
694 QTRY_VERIFY(image != 0);
696 QtMsgHandler previousMsgHandler = qInstallMsgHandler(checkWarnings);
698 QPixmap pm(100, 100);
701 // used to print "QTransform::translate with NaN called"
702 image->paint(&p, 0, 0);
703 qInstallMsgHandler(previousMsgHandler);
704 QVERIFY(numberOfWarnings == 0);
708 void tst_qdeclarativeimage::resetSourceSize()
710 QString src = QUrl::fromLocalFile(SRCDIR "/data/heart200.png").toString();
711 QString componentStr = "import QtQuick 1.1\nImage { function reset() { sourceSize = undefined }\nsource: \"" + src + "\"; sourceSize: Qt.size(100,100) }";
713 QDeclarativeComponent component(&engine);
714 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
715 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
717 QCOMPARE(obj->pixmap().width(), 100);
718 QCOMPARE(obj->pixmap().height(), 100);
719 QCOMPARE(obj->sourceSize().height(), 100);
720 QCOMPARE(obj->sourceSize().width(), 100);
722 QMetaObject::invokeMethod(obj, "reset");
723 QCOMPARE(obj->pixmap().width(), 200);
724 QCOMPARE(obj->pixmap().height(), 200);
725 QCOMPARE(obj->sourceSize().height(), 200);
726 QCOMPARE(obj->sourceSize().width(), 200);
729 void tst_qdeclarativeimage::testQtQuick11Attributes()
731 QFETCH(QString, code);
732 QFETCH(QString, warning);
733 QFETCH(QString, error);
735 QDeclarativeEngine engine;
738 QDeclarativeComponent valid(&engine);
739 valid.setData("import QtQuick 1.1; Image { " + code.toUtf8() + " }", QUrl(""));
740 obj = valid.create();
742 QVERIFY(valid.errorString().isEmpty());
745 QDeclarativeComponent invalid(&engine);
746 invalid.setData("import QtQuick 1.0; Image { " + code.toUtf8() + " }", QUrl(""));
747 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
748 obj = invalid.create();
749 QCOMPARE(invalid.errorString(), error);
753 void tst_qdeclarativeimage::testQtQuick11Attributes_data()
755 QTest::addColumn<QString>("code");
756 QTest::addColumn<QString>("warning");
757 QTest::addColumn<QString>("error");
759 QTest::newRow("mirror") << "mirror: true"
760 << "QDeclarativeComponent: Component is not ready"
761 << ":1 \"Image.mirror\" is not available in QtQuick 1.0.\n";
763 QTest::newRow("cache") << "cache: true"
764 << "QDeclarativeComponent: Component is not ready"
765 << ":1 \"Image.cache\" is not available in QtQuick 1.0.\n";
769 Find an item with the specified objectName. If index is supplied then the
770 item must also evaluate the {index} expression equal to index
773 T *tst_qdeclarativeimage::findItem(QGraphicsObject *parent, const QString &objectName, int index)
775 const QMetaObject &mo = T::staticMetaObject;
776 //qDebug() << parent->childItems().count() << "children";
777 for (int i = 0; i < parent->childItems().count(); ++i) {
778 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
781 //qDebug() << "try" << item;
782 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
784 QDeclarativeExpression e(qmlContext(item), item, "index");
785 if (e.evaluate().toInt() == index)
786 return static_cast<T*>(item);
788 return static_cast<T*>(item);
791 item = findItem<T>(item, objectName, index);
793 return static_cast<T*>(item);
799 QTEST_MAIN(tst_qdeclarativeimage)
801 #include "tst_qdeclarativeimage.moc"