From b63ce68f316c91b0a3107d3d20e160628f5cefef Mon Sep 17 00:00:00 2001 From: Charles Yin Date: Thu, 22 Mar 2012 14:07:28 +1000 Subject: [PATCH] Fix crash issue for path animation and path interpulator When set progress value out of [0,1], path animation and path interpulator should make sure the value be modified in the valid value range, otherwise the QQuickPath::backwardsPointAt() will crash. Task-number: QTBUG-24308 Change-Id: Icd6e9165c9f844ddb8ec84c229eac4db5246a749 Reviewed-by: Michael Brasser --- src/quick/items/qquickitemanimation.cpp | 2 ++ src/quick/util/qquickpath.cpp | 2 ++ src/quick/util/qquickpathinterpolator.cpp | 2 ++ .../data/pathAnimationInOutBackCrash.qml | 26 +++++++++++++++++++ .../qquickanimations/tst_qquickanimations.cpp | 24 +++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp index a1c398eeb6..3e84eb6115 100644 --- a/src/quick/items/qquickitemanimation.cpp +++ b/src/quick/items/qquickitemanimation.cpp @@ -927,6 +927,8 @@ QAbstractAnimationJob* QQuickPathAnimation::transition(QQuickStateActions &actio void QQuickPathAnimationUpdater::setValue(qreal v) { + v = qMin(qMax(v, (qreal)0.0), (qreal)1.0);; + if (interruptStart.isValid()) { if (reverse) v = 1 - v; diff --git a/src/quick/util/qquickpath.cpp b/src/quick/util/qquickpath.cpp index adf4242cdc..8dadab620a 100644 --- a/src/quick/util/qquickpath.cpp +++ b/src/quick/util/qquickpath.cpp @@ -527,6 +527,8 @@ QPointF QQuickPath::sequentialPointAt(qreal p, qreal *angle) const QPointF QQuickPath::sequentialPointAt(const QPainterPath &path, const qreal &pathLength, const QList &attributePoints, QQuickCachedBezier &prevBez, qreal p, qreal *angle) { + Q_ASSERT(p >= 0.0 && p <= 1.0); + if (!prevBez.isValid) return p > .5 ? backwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle) : forwardsPointAt(path, pathLength, attributePoints, prevBez, p, angle); diff --git a/src/quick/util/qquickpathinterpolator.cpp b/src/quick/util/qquickpathinterpolator.cpp index 2b5fb62872..ee1424b70f 100644 --- a/src/quick/util/qquickpathinterpolator.cpp +++ b/src/quick/util/qquickpathinterpolator.cpp @@ -102,6 +102,8 @@ qreal QQuickPathInterpolator::progress() const void QQuickPathInterpolator::setProgress(qreal progress) { + progress = qMin(qMax(progress, (qreal)0.0), (qreal)1.0); + if (progress == _progress) return; _progress = progress; diff --git a/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml new file mode 100644 index 0000000000..1ee76f6906 --- /dev/null +++ b/tests/auto/quick/qquickanimations/data/pathAnimationInOutBackCrash.qml @@ -0,0 +1,26 @@ +import QtQuick 2.0 +Item { + id: root + width: 450; height: 600 + + Rectangle { + objectName:"rect" + id: rect + x:200 + y:500 + width: 225; height: 40 + color: "lightsteelblue" + } + PathAnimation { + id:anim + running:true + duration: 200 + + easing.type: Easing.InOutBack + + target:rect + path: Path { + PathLine { x: 0; y: 0 } + } + } +} \ No newline at end of file diff --git a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp index d71100d120..166f4b8276 100644 --- a/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp +++ b/tests/auto/quick/qquickanimations/tst_qquickanimations.cpp @@ -107,6 +107,7 @@ private slots: void pauseBug(); void loopingBug(); void anchorBug(); + void pathAnimationInOutBackBug(); }; #define QTIMED_COMPARE(lhs, rhs) do { \ @@ -455,6 +456,13 @@ void tst_qquickanimations::pathInterpolator() QCOMPARE(interpolator->x(), qreal(300)); QCOMPARE(interpolator->y(), qreal(300)); QCOMPARE(interpolator->angle(), qreal(0)); + + //for path interpulator the progress value must be [0,1] range. + interpolator->setProgress(1.1); + QCOMPARE(interpolator->progress(), qreal(1)); + + interpolator->setProgress(-0.000123); + QCOMPARE(interpolator->progress(), qreal(0)); } void tst_qquickanimations::pathInterpolatorBackwardJump() @@ -1171,6 +1179,22 @@ void tst_qquickanimations::runningTrueBug() QVERIFY(cloud->x() > qreal(0)); } +//QTBUG-24308 +void tst_qquickanimations::pathAnimationInOutBackBug() +{ + //ensure we don't pass bad progress value (out of [0,1]) to QQuickPath::backwardsPointAt() + QQmlEngine engine; + QQmlComponent c(&engine, testFileUrl("pathAnimationInOutBackCrash.qml")); + QQuickItem *item = qobject_cast(c.create()); + QVERIFY(item); + + QQuickRectangle *rect = item->findChild("rect"); + QVERIFY(rect); + QTest::qWait(1000); + QCOMPARE(rect->x(), qreal(0)); + QCOMPARE(rect->y(), qreal(0)); +} + //QTBUG-12805 void tst_qquickanimations::nonTransitionBug() {