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 <QtDeclarative/qsgview.h>
45 #include <private/qsgrectangle_p.h>
46 #include <private/qsgimage_p.h>
47 #include <private/qsganimatedimage_p.h>
49 #include <QtDeclarative/qdeclarativecontext.h>
51 #include "../shared/testhttpserver.h"
52 #include "../shared/util.h"
54 class tst_qsganimatedimage : public QObject
58 tst_qsganimatedimage() {}
66 void mirror_running();
67 void mirror_notRunning();
68 void mirror_notRunning_data();
72 void sourceSizeReadOnly();
75 void progressAndStatusChanges();
79 void tst_qsganimatedimage::play()
81 QDeclarativeEngine engine;
82 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickman.qml")));
83 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
85 QVERIFY(anim->isPlaying());
90 void tst_qsganimatedimage::pause()
92 QDeclarativeEngine engine;
93 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
94 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
96 QVERIFY(anim->isPlaying());
97 QVERIFY(anim->isPaused());
102 void tst_qsganimatedimage::stopped()
104 QDeclarativeEngine engine;
105 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml")));
106 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
108 QVERIFY(!anim->isPlaying());
109 QCOMPARE(anim->currentFrame(), 0);
114 void tst_qsganimatedimage::setFrame()
116 QDeclarativeEngine engine;
117 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanpause.qml")));
118 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
120 QVERIFY(anim->isPlaying());
121 QCOMPARE(anim->currentFrame(), 2);
126 void tst_qsganimatedimage::frameCount()
128 QDeclarativeEngine engine;
129 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("colors.qml")));
130 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
132 QVERIFY(anim->isPlaying());
133 QCOMPARE(anim->frameCount(), 3);
138 void tst_qsganimatedimage::mirror_running()
140 // test where mirror is set to true after animation has started
142 QSGView *canvas = new QSGView;
145 canvas->setSource(QUrl::fromLocalFile(TESTDATA("hearts.qml")));
146 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(canvas->rootObject());
149 int width = anim->property("width").toInt();
151 QCOMPARE(anim->currentFrame(), 0);
152 QPixmap frame0 = QPixmap::fromImage(canvas->grabFrameBuffer());
154 anim->setCurrentFrame(1);
155 QPixmap frame1 = QPixmap::fromImage(canvas->grabFrameBuffer());
157 anim->setCurrentFrame(0);
159 QSignalSpy spy(anim, SIGNAL(frameChanged()));
160 anim->setPlaying(true);
162 QTRY_VERIFY(spy.count() == 1); spy.clear();
163 anim->setProperty("mirror", true);
165 QCOMPARE(anim->currentFrame(), 1);
166 QPixmap frame1_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
168 QTRY_VERIFY(spy.count() == 1); spy.clear();
169 QCOMPARE(anim->currentFrame(), 0); // animation only has 2 frames, should cycle back to first
170 QPixmap frame0_flipped = QPixmap::fromImage(canvas->grabFrameBuffer());
172 QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
174 QTransform transform;
175 transform.translate(width, 0).scale(-1, 1.0);
176 QPixmap frame0_expected = frame0.transformed(transform);
177 QPixmap frame1_expected = frame1.transformed(transform);
179 QCOMPARE(frame0_flipped, frame0_expected);
180 QCOMPARE(frame1_flipped, frame1_expected);
185 void tst_qsganimatedimage::mirror_notRunning()
187 QFETCH(QUrl, fileUrl);
189 QSGView *canvas = new QSGView;
192 canvas->setSource(fileUrl);
193 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(canvas->rootObject());
196 int width = anim->property("width").toInt();
197 QPixmap screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
199 QTransform transform;
200 transform.translate(width, 0).scale(-1, 1.0);
201 QPixmap expected = screenshot.transformed(transform);
203 int frame = anim->currentFrame();
204 bool playing = anim->isPlaying();
205 bool paused = anim->isPlaying();
207 anim->setProperty("mirror", true);
208 screenshot = QPixmap::fromImage(canvas->grabFrameBuffer());
210 QSKIP("Skip while QTBUG-19351 and QTBUG-19252 are not resolved");
211 QCOMPARE(screenshot, expected);
213 // mirroring should not change the current frame or playing status
214 QCOMPARE(anim->currentFrame(), frame);
215 QCOMPARE(anim->isPlaying(), playing);
216 QCOMPARE(anim->isPaused(), paused);
221 void tst_qsganimatedimage::mirror_notRunning_data()
223 QTest::addColumn<QUrl>("fileUrl");
225 QTest::newRow("paused") << QUrl::fromLocalFile(TESTDATA("stickmanpause.qml"));
226 QTest::newRow("stopped") << QUrl::fromLocalFile(TESTDATA("stickmanstopped.qml"));
229 void tst_qsganimatedimage::remote()
231 QFETCH(QString, fileName);
232 QFETCH(bool, paused);
234 TestHTTPServer server(14449);
235 QVERIFY(server.isValid());
236 server.serveDirectory(TESTDATA(""));
238 QDeclarativeEngine engine;
239 QDeclarativeComponent component(&engine, QUrl("http://127.0.0.1:14449/" + fileName));
240 QTRY_VERIFY(component.isReady());
242 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
245 QTRY_VERIFY(anim->isPlaying());
247 QTRY_VERIFY(anim->isPaused());
248 QCOMPARE(anim->currentFrame(), 2);
250 QVERIFY(anim->status() != QSGAnimatedImage::Error);
255 void tst_qsganimatedimage::sourceSize()
257 QDeclarativeEngine engine;
258 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanscaled.qml")));
259 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
261 QCOMPARE(anim->width(),240.0);
262 QCOMPARE(anim->height(),180.0);
263 QCOMPARE(anim->sourceSize(),QSize(160,120));
268 void tst_qsganimatedimage::sourceSizeReadOnly()
270 QDeclarativeEngine engine;
271 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("stickmanerror1.qml")));
272 QVERIFY(component.isError());
273 QCOMPARE(component.errors().at(0).description(), QString("Invalid property assignment: \"sourceSize\" is a read-only property"));
276 void tst_qsganimatedimage::remote_data()
278 QTest::addColumn<QString>("fileName");
279 QTest::addColumn<bool>("paused");
281 QTest::newRow("playing") << "stickman.qml" << false;
282 QTest::newRow("paused") << "stickmanpause.qml" << true;
285 void tst_qsganimatedimage::invalidSource()
287 QDeclarativeEngine engine;
288 QDeclarativeComponent component(&engine);
289 component.setData("import QtQuick 2.0\n AnimatedImage { source: \"no-such-file.gif\" }", QUrl::fromLocalFile(""));
290 QVERIFY(component.isReady());
292 QTest::ignoreMessage(QtWarningMsg, "file::2:2: QML AnimatedImage: Error Reading Animated Image File file:no-such-file.gif");
294 QSGAnimatedImage *anim = qobject_cast<QSGAnimatedImage *>(component.create());
297 QVERIFY(!anim->isPlaying());
298 QVERIFY(!anim->isPaused());
299 QCOMPARE(anim->currentFrame(), 0);
300 QCOMPARE(anim->frameCount(), 0);
301 QTRY_VERIFY(anim->status() == 3);
304 void tst_qsganimatedimage::qtbug_16520()
306 TestHTTPServer server(14449);
307 QVERIFY(server.isValid());
308 server.serveDirectory(TESTDATA(""));
310 QDeclarativeEngine engine;
311 QDeclarativeComponent component(&engine, QUrl::fromLocalFile(TESTDATA("qtbug-16520.qml")));
312 QTRY_VERIFY(component.isReady());
314 QSGRectangle *root = qobject_cast<QSGRectangle *>(component.create());
316 QSGAnimatedImage *anim = root->findChild<QSGAnimatedImage*>("anim");
318 anim->setProperty("source", "http://127.0.0.1:14449/stickman.gif");
320 QTRY_VERIFY(anim->opacity() == 0);
321 QTRY_VERIFY(anim->opacity() == 1);
326 void tst_qsganimatedimage::progressAndStatusChanges()
328 TestHTTPServer server(14449);
329 QVERIFY(server.isValid());
330 server.serveDirectory(TESTDATA(""));
332 QDeclarativeEngine engine;
333 QString componentStr = "import QtQuick 2.0\nAnimatedImage { source: srcImage }";
334 QDeclarativeContext *ctxt = engine.rootContext();
335 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("stickman.gif")));
336 QDeclarativeComponent component(&engine);
337 component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
338 QSGImage *obj = qobject_cast<QSGImage*>(component.create());
340 QVERIFY(obj->status() == QSGImage::Ready);
341 QTRY_VERIFY(obj->progress() == 1.0);
343 QSignalSpy sourceSpy(obj, SIGNAL(sourceChanged(const QUrl &)));
344 QSignalSpy progressSpy(obj, SIGNAL(progressChanged(qreal)));
345 QSignalSpy statusSpy(obj, SIGNAL(statusChanged(QSGImageBase::Status)));
347 // Loading local file
348 ctxt->setContextProperty("srcImage", QUrl::fromLocalFile(TESTDATA("colors.gif")));
349 QTRY_VERIFY(obj->status() == QSGImage::Ready);
350 QTRY_VERIFY(obj->progress() == 1.0);
351 QTRY_COMPARE(sourceSpy.count(), 1);
352 QTRY_COMPARE(progressSpy.count(), 0);
353 QTRY_COMPARE(statusSpy.count(), 0);
355 // Loading remote file
356 ctxt->setContextProperty("srcImage", "http://127.0.0.1:14449/stickman.gif");
357 QTRY_VERIFY(obj->status() == QSGImage::Loading);
358 QTRY_VERIFY(obj->progress() == 0.0);
359 QTRY_VERIFY(obj->status() == QSGImage::Ready);
360 QTRY_VERIFY(obj->progress() == 1.0);
361 QTRY_COMPARE(sourceSpy.count(), 2);
362 QTRY_VERIFY(progressSpy.count() > 1);
363 QTRY_COMPARE(statusSpy.count(), 2);
365 ctxt->setContextProperty("srcImage", "");
366 QTRY_VERIFY(obj->status() == QSGImage::Null);
367 QTRY_VERIFY(obj->progress() == 0.0);
368 QTRY_COMPARE(sourceSpy.count(), 3);
369 QTRY_VERIFY(progressSpy.count() > 2);
370 QTRY_COMPARE(statusSpy.count(), 3);
373 QTEST_MAIN(tst_qsganimatedimage)
375 #include "tst_qsganimatedimage.moc"