aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2012-01-04 11:08:24 +1000
committerQt by Nokia <qt-info@nokia.com>2012-01-27 06:23:00 +0100
commitabd8ff8b03038f349c8b54f094e500516e249f1b (patch)
tree1cb8780770798d7b4c6f7f5e85499724805b2ee7
parenta838eea33313967e501a5a045d2a68d2a35e7533 (diff)
Prevent PathAnimation from hanging when jumping backwards to beginning.
Task-number: QTBUG-23076 Change-Id: I2aecdfd28f0c3d45b3b805640edaecbd5be2e6fd Reviewed-by: Yunqiao Yin <charles.yin@nokia.com> Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
-rw-r--r--src/quick/items/qquickanimation.cpp1
-rw-r--r--src/quick/util/qdeclarativepath.cpp12
-rw-r--r--src/quick/util/qdeclarativepath_p.h1
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack2.qml10
-rw-r--r--tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp81
5 files changed, 76 insertions, 29 deletions
diff --git a/src/quick/items/qquickanimation.cpp b/src/quick/items/qquickanimation.cpp
index 34377e92dd..b64095db65 100644
--- a/src/quick/items/qquickanimation.cpp
+++ b/src/quick/items/qquickanimation.cpp
@@ -645,6 +645,7 @@ void QQuickPathAnimation::transition(QDeclarativeStateActions &actions,
(modified.count() > origModifiedSize || data->toDefined)) {
data->target = d->target;
data->path = d->path;
+ data->path->invalidateSequentialHistory();
if (!d->rangeIsSet) {
d->pa->setStartValue(qreal(0));
d->pa->setEndValue(qreal(1));
diff --git a/src/quick/util/qdeclarativepath.cpp b/src/quick/util/qdeclarativepath.cpp
index 842b5465b7..52d0245ee0 100644
--- a/src/quick/util/qdeclarativepath.cpp
+++ b/src/quick/util/qdeclarativepath.cpp
@@ -513,6 +513,12 @@ void QDeclarativePath::createPointCache() const
}
}
+void QDeclarativePath::invalidateSequentialHistory() const
+{
+ Q_D(const QDeclarativePath);
+ d->prevBez.isValid = false;
+}
+
QPointF QDeclarativePath::sequentialPointAt(qreal p, qreal *angle) const
{
Q_D(const QDeclarativePath);
@@ -590,7 +596,7 @@ QPointF QDeclarativePath::backwardsPointAt(const QPainterPath &path, const qreal
if (pathLength <= 0 || qIsNaN(pathLength))
return path.pointAtPercent(0);
- const int firstElement = 0;
+ const int firstElement = 1; //element 0 is always a MoveTo, which we ignore
bool haveCachedBez = prevBez.isValid;
int currElement = haveCachedBez ? prevBez.element : path.elementCount();
qreal bezLength = haveCachedBez ? prevBez.bezLength : 0;
@@ -612,7 +618,9 @@ QPointF QDeclarativePath::backwardsPointAt(const QPainterPath &path, const qreal
Q_ASSERT(!(currElement < firstElement));
Q_UNUSED(firstElement);
currBez = nextBezier(path, &currElement, &bezLength, true /*reverse*/);
- currLength = prevLength;
+ //special case for first element is to avoid floating point math
+ //causing an epc that never hits 0.
+ currLength = (currElement == firstElement) ? bezLength : prevLength;
prevLength = currLength - bezLength;
epc = prevLength / pathLength;
}
diff --git a/src/quick/util/qdeclarativepath_p.h b/src/quick/util/qdeclarativepath_p.h
index 93e132e423..fd8be57d6b 100644
--- a/src/quick/util/qdeclarativepath_p.h
+++ b/src/quick/util/qdeclarativepath_p.h
@@ -385,6 +385,7 @@ public:
qreal attributeAt(const QString &, qreal) const;
QPointF pointAt(qreal) const;
QPointF sequentialPointAt(qreal p, qreal *angle = 0) const;
+ void invalidateSequentialHistory() const;
Q_SIGNALS:
void changed();
diff --git a/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack2.qml b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack2.qml
new file mode 100644
index 0000000000..eb3d4c3f86
--- /dev/null
+++ b/tests/auto/qtquick2/qdeclarativeanimations/data/pathInterpolatorBack2.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+PathInterpolator {
+ path: Path {
+ startX: 200; startY: 280
+ PathCurve { x: 150; y: 280 }
+ PathCurve { x: 150; y: 80 }
+ PathCurve { x: 0; y: 80 }
+ }
+}
diff --git a/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp b/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
index f58010998f..bc4e132e30 100644
--- a/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
+++ b/tests/auto/qtquick2/qdeclarativeanimations/tst_qdeclarativeanimations.cpp
@@ -322,34 +322,61 @@ void tst_qdeclarativeanimations::pathInterpolator()
void tst_qdeclarativeanimations::pathInterpolatorBackwardJump()
{
- QDeclarativeEngine engine;
- QDeclarativeComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
- QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
- QVERIFY(interpolator);
-
- QCOMPARE(interpolator->progress(), qreal(0));
- QCOMPARE(interpolator->x(), qreal(50));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(270));
-
- interpolator->setProgress(.5);
- QCOMPARE(interpolator->progress(), qreal(.5));
- QCOMPARE(interpolator->x(), qreal(100));
- QCOMPARE(interpolator->y(), qreal(75));
- QCOMPARE(interpolator->angle(), qreal(90));
-
- interpolator->setProgress(1);
- QCOMPARE(interpolator->progress(), qreal(1));
- QCOMPARE(interpolator->x(), qreal(200));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(0));
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, testFileUrl("pathInterpolatorBack.qml"));
+ QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
+ QVERIFY(interpolator);
+
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(270));
+
+ interpolator->setProgress(.5);
+ QCOMPARE(interpolator->progress(), qreal(.5));
+ QCOMPARE(interpolator->x(), qreal(100));
+ QCOMPARE(interpolator->y(), qreal(75));
+ QCOMPARE(interpolator->angle(), qreal(90));
+
+ interpolator->setProgress(1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+ QCOMPARE(interpolator->x(), qreal(200));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(0));
+
+ //make sure we don't get caught in infinite loop here
+ interpolator->setProgress(0);
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(50));
+ QCOMPARE(interpolator->y(), qreal(50));
+ QCOMPARE(interpolator->angle(), qreal(270));
+ }
- //make sure we don't get caught in infinite loop here
- interpolator->setProgress(0);
- QCOMPARE(interpolator->progress(), qreal(0));
- QCOMPARE(interpolator->x(), qreal(50));
- QCOMPARE(interpolator->y(), qreal(50));
- QCOMPARE(interpolator->angle(), qreal(270));
+ {
+ QDeclarativeEngine engine;
+ QDeclarativeComponent c(&engine, testFileUrl("pathInterpolatorBack2.qml"));
+ QDeclarativePathInterpolator *interpolator = qobject_cast<QDeclarativePathInterpolator*>(c.create());
+ QVERIFY(interpolator);
+
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(200));
+ QCOMPARE(interpolator->y(), qreal(280));
+ QCOMPARE(interpolator->angle(), qreal(180));
+
+ interpolator->setProgress(1);
+ QCOMPARE(interpolator->progress(), qreal(1));
+ QCOMPARE(interpolator->x(), qreal(0));
+ QCOMPARE(interpolator->y(), qreal(80));
+ QCOMPARE(interpolator->angle(), qreal(180));
+
+ //make sure we don't get caught in infinite loop here
+ interpolator->setProgress(0);
+ QCOMPARE(interpolator->progress(), qreal(0));
+ QCOMPARE(interpolator->x(), qreal(200));
+ QCOMPARE(interpolator->y(), qreal(280));
+ QCOMPARE(interpolator->angle(), qreal(180));
+ }
}
void tst_qdeclarativeanimations::pathWithNoStart()