aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp32
-rw-r--r--src/quick/items/qquickspriteengine.cpp2
-rw-r--r--tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml63
-rw-r--r--tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro3
-rw-r--r--tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp113
5 files changed, 200 insertions, 13 deletions
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 3aaec53c54..e816975827 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -388,8 +388,8 @@ void QQuickAnimatedSprite::advance(int frames)
//TODO-C: May not work when running - only when paused
m_curFrame += frames;
while (m_curFrame < 0)
- m_curFrame += m_sprite->frames();
- m_curFrame = m_curFrame % m_sprite->frames();
+ m_curFrame += m_spriteEngine->maxFrames();
+ m_curFrame = m_curFrame % m_spriteEngine->maxFrames();
emit currentFrameChanged(m_curFrame);
}
@@ -574,35 +574,41 @@ void QQuickAnimatedSprite::prepareNextFrame()
int timeInt = m_timestamp.elapsed() + m_pauseOffset;
qreal time = timeInt / 1000.;
- double frameAt; //double just for modf
+ int frameAt;
qreal progress = 0.0;
int lastFrame = m_curFrame;
if (m_running && !m_paused) {
+ const int nColumns = int(m_sheetSize.width()) / m_spriteEngine->spriteWidth();
//Advance State (keeps time for psuedostates)
m_spriteEngine->updateSprites(timeInt);
//Advance AnimatedSprite
qreal animT = m_spriteEngine->spriteStart()/1000.0;
- qreal frameCount = m_spriteEngine->spriteFrames();
- qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount;
+ const int frameCountInRow = m_spriteEngine->spriteFrames();
+ const qreal frameDuration = m_spriteEngine->spriteDuration()/frameCountInRow;
if (frameDuration > 0) {
qreal frame = (time - animT)/(frameDuration / 1000.0);
bool lastLoop = m_loops > 0 && m_curLoop == m_loops-1;
//don't visually interpolate for the last frame of the last loop
- qreal max = lastLoop ? frameCount - qreal(1.0) : frameCount;
- frame = qBound(qreal(0.0), frame, max);
- progress = modf(frame,&frameAt);
- if (m_curFrame > frameAt) //went around
+ const int max = lastLoop ? frameCountInRow - 1 : frameCountInRow;
+ frame = qBound(qreal(0.0), frame, qreal(max));
+ double intpart;
+ progress = modf(frame,&intpart);
+ frameAt = (int)intpart;
+ const int rowIndex = m_spriteEngine->spriteY()/frameHeight();
+ const int newFrame = rowIndex * nColumns + frameAt;
+ if (m_curFrame > newFrame) //went around
m_curLoop++;
- m_curFrame = frameAt;
+ m_curFrame = newFrame;
} else {
m_curFrame++;
- if (m_curFrame >= frameCount){
+ if (m_curFrame >= m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows
m_curFrame = 0;
m_curLoop++;
- m_spriteEngine->advance();
}
- frameAt = m_curFrame;
+ frameAt = m_curFrame % nColumns;
+ if (frameAt == 0)
+ m_spriteEngine->advance();
progress = 0;
}
if (m_loops > 0 && m_curLoop >= m_loops) {
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index 097d512a43..7a48beeda4 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -512,7 +512,9 @@ void QQuickStochasticEngine::start(int index, int state)
else
m_startTimes[index] = 0;
m_goals[index] = -1;
+ m_addAdvance = false;
restart(index);
+ m_addAdvance = true;
}
void QQuickStochasticEngine::stop(int index)
diff --git a/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml b/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml
new file mode 100644
index 0000000000..adcbaeb74f
--- /dev/null
+++ b/tests/auto/quick/qquickanimatedsprite/data/largeAnimation.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ color: "white"
+ width: 512
+ height: 320
+
+ AnimatedSprite {
+ anchors.centerIn: parent
+ objectName: "sprite"
+ source: "image://test/largeAnimation.png"
+ frameCount: 40
+ loops: 3
+ frameSync: true
+ running: false
+ width: 512
+ height: 64
+ frameWidth: 512
+ frameHeight: 64
+
+ }
+}
diff --git a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
index dd56991812..3e47844feb 100644
--- a/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
+++ b/tests/auto/quick/qquickanimatedsprite/qquickanimatedsprite.pro
@@ -12,3 +12,6 @@ CONFIG += parallel_test
QT += core-private gui-private qml-private quick-private network testlib
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
+
+OTHER_FILES += \
+ data/largeAnimation.qml
diff --git a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
index cc5d8274d4..ed97123644 100644
--- a/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
+++ b/tests/auto/quick/qquickanimatedsprite/tst_qquickanimatedsprite.cpp
@@ -35,6 +35,7 @@
#include <QtQuick/qquickview.h>
#include <private/qabstractanimation_p.h>
#include <private/qquickanimatedsprite_p.h>
+#include <QtGui/qpainter.h>
class tst_qquickanimatedsprite : public QQmlDataTest
{
@@ -47,6 +48,8 @@ private slots:
void test_properties();
void test_runningChangedSignal();
void test_frameChangedSignal();
+ void test_largeAnimation_data();
+ void test_largeAnimation();
};
void tst_qquickanimatedsprite::initTestCase()
@@ -103,6 +106,13 @@ void tst_qquickanimatedsprite::test_runningChangedSignal()
delete window;
}
+template <typename T>
+static bool isWithinRange(T min, T value, T max)
+{
+ Q_ASSERT(min < max);
+ return min <= value && value <= max;
+}
+
void tst_qquickanimatedsprite::test_frameChangedSignal()
{
QQuickView *window = new QQuickView(0);
@@ -146,6 +156,109 @@ void tst_qquickanimatedsprite::test_frameChangedSignal()
delete window;
}
+void tst_qquickanimatedsprite::test_largeAnimation_data()
+{
+ QTest::addColumn<bool>("frameSync");
+
+ QTest::newRow("frameSync") << true;
+ QTest::newRow("no_frameSync") << false;
+
+}
+
+class AnimationImageProvider : public QQuickImageProvider
+{
+public:
+ AnimationImageProvider()
+ : QQuickImageProvider(QQuickImageProvider::Pixmap)
+ {
+ }
+
+ QPixmap requestPixmap(const QString &/*id*/, QSize *size, const QSize &requestedSize)
+ {
+ if (requestedSize.isValid())
+ qWarning() << "requestPixmap called with requestedSize of" << requestedSize;
+ // 40 frames.
+ const int nFrames = 40; // 40 is good for texture max width of 4096, 64 is good for 16384
+
+ const int frameWidth = 512;
+ const int frameHeight = 64;
+
+ const QSize pixSize(frameWidth, nFrames * frameHeight);
+ QPixmap pixmap(pixSize);
+ pixmap.fill();
+
+ for (int i = 0; i < nFrames; ++i) {
+ QImage frame(frameWidth, frameHeight, QImage::Format_ARGB32_Premultiplied);
+ frame.fill(Qt::white);
+ QPainter p1(&frame);
+ p1.setRenderHint(QPainter::Antialiasing, true);
+ QRect r(0,0, frameWidth, frameHeight);
+ p1.setBrush(QBrush(Qt::red, Qt::SolidPattern));
+ p1.drawPie(r, i*360*16/nFrames, 90*16);
+ p1.drawText(r, QString::number(i));
+ p1.end();
+
+ QPainter p2(&pixmap);
+ p2.drawImage(0, i * frameHeight, frame);
+ }
+
+ if (size)
+ *size = pixSize;
+ return pixmap;
+ }
+};
+
+void tst_qquickanimatedsprite::test_largeAnimation()
+{
+ QFETCH(bool, frameSync);
+
+ QQuickView *window = new QQuickView(0);
+ window->engine()->addImageProvider(QLatin1String("test"), new AnimationImageProvider);
+ window->setSource(testFileUrl("largeAnimation.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QVERIFY(window->rootObject());
+ QQuickAnimatedSprite* sprite = window->rootObject()->findChild<QQuickAnimatedSprite*>("sprite");
+
+ QVERIFY(sprite);
+
+ QVERIFY(!sprite->running());
+ QVERIFY(!sprite->paused());
+ QCOMPARE(sprite->loops(), 3);
+ QCOMPARE(sprite->frameCount(), 40);
+ sprite->setProperty("frameSync", frameSync);
+ if (!frameSync)
+ sprite->setProperty("frameDuration", 30);
+
+ QSignalSpy frameChangedSpy(sprite, SIGNAL(currentFrameChanged(int)));
+ sprite->setRunning(true);
+ QTRY_VERIFY_WITH_TIMEOUT(!sprite->running(), 100000 /* make sure we wait until its done*/ );
+ if (frameSync)
+ QVERIFY(isWithinRange(3*40, frameChangedSpy.count(), 3*40 + 1));
+ int prevFrame = -1;
+ int loopCounter = 0;
+ int maxFrame = 0;
+ while (!frameChangedSpy.isEmpty()) {
+ QList<QVariant> args = frameChangedSpy.takeFirst();
+ int frame = args.first().toInt();
+ if (frame < prevFrame) {
+ ++loopCounter;
+ } else {
+ QVERIFY(frame > prevFrame);
+ }
+ maxFrame = qMax(frame, maxFrame);
+ prevFrame = frame;
+ }
+ int maxTextureSize;
+ ::glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+ maxTextureSize /= 512;
+ QVERIFY(maxFrame > maxTextureSize); // make sure we go beyond the texture width limitation
+ QCOMPARE(loopCounter, sprite->loops());
+ delete window;
+}
+
+
QTEST_MAIN(tst_qquickanimatedsprite)
#include "tst_qquickanimatedsprite.moc"