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 <QtDeclarative/qdeclarativeengine.h>
43 #include <QtDeclarative/qdeclarativecomponent.h>
44 #include <QtQuick1/qdeclarativeview.h>
45 #include <private/qdeclarativerectangle_p.h>
46 #include <private/qdeclarativeimage_p.h>
47 #include <private/qdeclarativeanimatedimage_p.h>
49 #include <QtDeclarative/qdeclarativecontext.h>
51 #include "../../declarative/shared/testhttpserver.h"
53 class tst_qdeclarativeanimatedimage : public QObject
57 tst_qdeclarativeanimatedimage() {}
65 void mirror_running();
66 void mirror_notRunning();
67 void mirror_notRunning_data();
71 void sourceSizeReadOnly();
74 void progressAndStatusChanges();
77 QPixmap grabScene(QGraphicsScene *scene, int width, int height);
80 QPixmap tst_qdeclarativeanimatedimage::grabScene(QGraphicsScene *scene, int width, int height)
82 QPixmap screenshot(width, height);
84 QPainter p_screenshot(&screenshot);
85 scene->render(&p_screenshot, QRect(0, 0, width, height), QRect(0, 0, width, height));
89 void tst_qdeclarativeanimatedimage::play()
91 QDeclarativeEngine engine;
92 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickman.qml"));
93 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
95 QVERIFY(anim->isPlaying());
100 void tst_qdeclarativeanimatedimage::pause()
102 QDeclarativeEngine engine;
103 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"));
104 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
106 QVERIFY(anim->isPlaying());
107 QVERIFY(anim->isPaused());
112 void tst_qdeclarativeanimatedimage::stopped()
114 QDeclarativeEngine engine;
115 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanstopped.qml"));
116 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
118 QVERIFY(!anim->isPlaying());
119 QCOMPARE(anim->currentFrame(), 0);
124 void tst_qdeclarativeanimatedimage::setFrame()
126 QDeclarativeEngine engine;
127 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml"));
128 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
130 QVERIFY(anim->isPlaying());
131 QCOMPARE(anim->currentFrame(), 2);
136 void tst_qdeclarativeanimatedimage::frameCount()
138 QDeclarativeEngine engine;
139 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/colors.qml"));
140 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
142 QVERIFY(anim->isPlaying());
143 QCOMPARE(anim->frameCount(), 3);
148 void tst_qdeclarativeanimatedimage::mirror_running()
150 // test where mirror is set to true after animation has started
152 QDeclarativeEngine engine;
153 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/hearts.qml"));
154 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
157 QGraphicsScene scene;
158 int width = anim->property("width").toInt();
159 int height = anim->property("height").toInt();
160 scene.addItem(qobject_cast<QGraphicsObject *>(anim));
162 QCOMPARE(anim->currentFrame(), 0);
163 QPixmap frame0 = grabScene(&scene, width, height);
164 anim->setCurrentFrame(1);
165 QPixmap frame1 = grabScene(&scene, width, height);
167 anim->setCurrentFrame(0);
169 QSignalSpy spy(anim, SIGNAL(frameChanged()));
170 anim->setPlaying(true);
172 QTRY_VERIFY(spy.count() == 1); spy.clear();
173 anim->setProperty("mirror", true);
175 QCOMPARE(anim->currentFrame(), 1);
176 QPixmap frame1_flipped = grabScene(&scene, width, height);
178 QTRY_VERIFY(spy.count() == 1); spy.clear();
179 QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
180 QPixmap frame0_flipped = grabScene(&scene, width, height);
182 QTransform transform;
183 transform.translate(width, 0).scale(-1, 1.0);
184 QPixmap frame0_expected = frame0.transformed(transform);
185 QPixmap frame1_expected = frame1.transformed(transform);
187 QCOMPARE(frame0_flipped, frame0_expected);
188 QCOMPARE(frame1_flipped, frame1_expected);
191 void tst_qdeclarativeanimatedimage::mirror_notRunning()
193 QFETCH(QUrl, fileUrl);
195 QDeclarativeEngine engine;
196 QDeclarativeComponent component(&engine, fileUrl);
197 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
200 QGraphicsScene scene;
201 int width = anim->property("width").toInt();
202 int height = anim->property("height").toInt();
203 scene.addItem(qobject_cast<QGraphicsObject *>(anim));
204 QPixmap screenshot = grabScene(&scene, width, height);
206 QTransform transform;
207 transform.translate(width, 0).scale(-1, 1.0);
208 QPixmap expected = screenshot.transformed(transform);
210 int frame = anim->currentFrame();
211 bool playing = anim->isPlaying();
212 bool paused = anim->isPlaying();
214 anim->setProperty("mirror", true);
215 screenshot = grabScene(&scene, width, height);
217 QCOMPARE(screenshot, expected);
219 // mirroring should not change the current frame or playing status
220 QCOMPARE(anim->currentFrame(), frame);
221 QCOMPARE(anim->isPlaying(), playing);
222 QCOMPARE(anim->isPaused(), paused);
227 void tst_qdeclarativeanimatedimage::mirror_notRunning_data()
229 QTest::addColumn<QUrl>("fileUrl");
231 QTest::newRow("paused") << QUrl::fromLocalFile(SRCDIR "/data/stickmanpause.qml");
232 QTest::newRow("stopped") << QUrl::fromLocalFile(SRCDIR "/data/stickmanstopped.qml");
235 void tst_qdeclarativeanimatedimage::remote()
237 QFETCH(QString, fileName);
238 QFETCH(bool, paused);
240 TestHTTPServer server(14449);
241 QVERIFY(server.isValid());
242 server.serveDirectory(SRCDIR "/data");
244 QDeclarativeEngine engine;
245 QDeclarativeComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
246 QTRY_VERIFY(component.isReady());
248 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
251 QTRY_VERIFY(anim->isPlaying());
253 QTRY_VERIFY(anim->isPaused());
254 QCOMPARE(anim->currentFrame(), 2);
256 QVERIFY(anim->status() != QDeclarative1AnimatedImage::Error);
261 void tst_qdeclarativeanimatedimage::sourceSize()
263 QDeclarativeEngine engine;
264 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanscaled.qml"));
265 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
267 QCOMPARE(anim->width(),240.0);
268 QCOMPARE(anim->height(),180.0);
269 QCOMPARE(anim->sourceSize(),QSize(160,120));
274 void tst_qdeclarativeanimatedimage::sourceSizeReadOnly()
276 QDeclarativeEngine engine;
277 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/stickmanerror1.qml"));
278 QVERIFY(component.isError());
279 QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
282 void tst_qdeclarativeanimatedimage::remote_data()
284 QTest::addColumn<QString>("fileName");
285 QTest::addColumn<bool>("paused");
287 QTest::newRow("playing") << "stickman.qml" << false;
288 QTest::newRow("paused") << "stickmanpause.qml" << true;
291 void tst_qdeclarativeanimatedimage::invalidSource()
293 QDeclarativeEngine engine;
294 QDeclarativeComponent component(&engine);
295 component.setData("import QtQuick 1.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
296 QVERIFY(component.isReady());
298 QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
300 QDeclarative1AnimatedImage *anim = qobject_cast<QDeclarative1AnimatedImage *>(component.create());
303 QVERIFY(!anim->isPlaying());
304 QVERIFY(!anim->isPaused());
305 QCOMPARE(anim->currentFrame(), 0);
306 QCOMPARE(anim->frameCount(), 0);
307 QTRY_VERIFY(anim->status() == 3);
310 void tst_qdeclarativeanimatedimage::qtbug_16520()
312 TestHTTPServer server(14449);
313 QVERIFY(server.isValid());
314 server.serveDirectory(SRCDIR "/data");
316 QDeclarativeEngine engine;
317 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/qtbug-16520.qml"));
318 QTRY_VERIFY(component.isReady());
320 QDeclarative1Rectangle *root = qobject_cast<QDeclarative1Rectangle *>(component.create());
322 QDeclarative1AnimatedImage *anim = root->findChild<QDeclarative1AnimatedImage*>("anim");
324 anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
326 QTRY_VERIFY(anim->opacity() == 0);
327 QTRY_VERIFY(anim->opacity() == 1);
332 void tst_qdeclarativeanimatedimage::progressAndStatusChanges()
334 TestHTTPServer server(14449);
335 QVERIFY(server.isValid());
336 server.serveDirectory(SRCDIR "/data");
338 QDeclarativeEngine engine;
339 QString componentStr = "import QtQuick 1.0\nAnimatedImage { source: srcImage }";
340 QDeclarativeContext *ctxt = engine.rootContext();
341 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/stickman.gif"));
342 QDeclarativeComponent component(&engine);
343 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
344 QDeclarative1Image *obj = qobject_cast<QDeclarative1Image*>(component.create());
346 QVERIFY(obj->status() == QDeclarative1Image::Ready);
347 QTRY_VERIFY(obj->progress() == 1.0);
349 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
350 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
351 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QDeclarative1ImageBase::Status)));
353 // Loading local file
354 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(SRCDIR "/data/colors.gif"));
355 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
356 QTRY_VERIFY(obj->progress() == 1.0);
357 QTRY_COMPARE(sourceSpy.count(), 1);
358 QTRY_COMPARE(progressSpy.count(), 0);
359 QTRY_COMPARE(statusSpy.count(), 0);
361 // Loading remote file
362 ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
363 QTRY_VERIFY(obj->status() == QDeclarative1Image::Loading);
364 QTRY_VERIFY(obj->progress() == 0.0);
365 QTRY_VERIFY(obj->status() == QDeclarative1Image::Ready);
366 QTRY_VERIFY(obj->progress() == 1.0);
367 QTRY_COMPARE(sourceSpy.count(), 2);
368 QTRY_VERIFY(progressSpy.count() > 1);
369 QTRY_COMPARE(statusSpy.count(), 2);
371 ctxt->setContextProperty("srcImage", "");
372 QTRY_VERIFY(obj->status() == QDeclarative1Image::Null);
373 QTRY_VERIFY(obj->progress() == 0.0);
374 QTRY_COMPARE(sourceSpy.count(), 3);
375 QTRY_VERIFY(progressSpy.count() > 2);
376 QTRY_COMPARE(statusSpy.count(), 3);
379 QTEST_MAIN(tst_qdeclarativeanimatedimage)
381 #include "tst_qdeclarativeanimatedimage.moc"