Fix QEasingCurve possible imprecision at endpoints

Both the spline curves and (most of) the predefines curves are defined
as having start value 0.0 and end value 1.0. The spline and In/OutBack
functions would sometimes not produce that result precisely, so code
could not reliably depend on expressions like (easedValue < 1.0)
becoming false. Fix by explicitly handling endpoints.

Fixes: QTBUG-76781
Fixes: QTBUG-72630
Change-Id: I21be43af469a76c090154bffef8406a9baf2d0b1
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Eirik Aavitsland 2019-10-09 10:29:00 +02:00
parent eaf4911db2
commit c54083ff93
2 changed files with 23 additions and 0 deletions

View File

@ -583,6 +583,13 @@ struct BezierEase : public QEasingCurveFunction
qWarning("QEasingCurve: Invalid bezier curve");
return x;
}
// The bezier computation is not always precise on the endpoints, so handle explicitly
if (!(x > 0))
return 0;
if (!(x < 1))
return 1;
SingleCubicBezier *singleCubicBezier = 0;
getBezierSegment(singleCubicBezier, x);
@ -998,6 +1005,11 @@ struct BackEase : public QEasingCurveFunction
qreal value(qreal t) override
{
// The *Back() functions are not always precise on the endpoints, so handle explicitly
if (!(t > 0))
return 0;
if (!(t < 1))
return 1;
qreal o = (_o < 0) ? qreal(1.70158) : _o;
switch(_t) {
case QEasingCurve::InBack:

View File

@ -404,6 +404,11 @@ void tst_QEasingCurve::valueForProgress()
const qreal error = qAbs(ex - curve.valueForProgress(at.at(i)/qreal(100)));
QVERIFY(error <= errorBound);
}
if (type != QEasingCurve::SineCurve && type != QEasingCurve::CosineCurve) {
QVERIFY( !(curve.valueForProgress(0) > 0) );
QVERIFY( !(curve.valueForProgress(1) < 1) );
}
#endif
}
@ -632,6 +637,9 @@ void tst_QEasingCurve::bezierSpline()
QCOMPARE(value, ex);
QVERIFY(error <= errorBound);
}
QVERIFY( !(bezierEasingCurve.valueForProgress(0) > 0) );
QVERIFY( !(bezierEasingCurve.valueForProgress(1) < 1) );
}
void tst_QEasingCurve::tcbSpline_data()
@ -691,6 +699,9 @@ void tst_QEasingCurve::tcbSpline()
QCOMPARE(value, ex);
QVERIFY(error <= errorBound);
}
QVERIFY( !(tcbEasingCurve.valueForProgress(0) > 0) );
QVERIFY( !(tcbEasingCurve.valueForProgress(1) < 1) );
}
/*This is single precision code for a cubic root used inside the spline easing curve.