Bug 1460234 - Calculate the position in a keyframe segment using double precision; r?hiro
The added test fails without the code changes in this patch.
MozReview-Commit-ID: HXPaxLu1osC
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -743,24 +743,27 @@ Gecko_ElementTransitions_EndValueAt(RawG
double
Gecko_GetProgressFromComputedTiming(RawGeckoComputedTimingBorrowed aComputedTiming)
{
return aComputedTiming->mProgress.Value();
}
double
Gecko_GetPositionInSegment(RawGeckoAnimationPropertySegmentBorrowed aSegment,
- double aProgress,
- ComputedTimingFunction::BeforeFlag aBeforeFlag)
+ double aProgress,
+ ComputedTimingFunction::BeforeFlag aBeforeFlag)
{
MOZ_ASSERT(aSegment->mFromKey < aSegment->mToKey,
"The segment from key should be less than to key");
- double positionInSegment =
- (aProgress - aSegment->mFromKey) / (aSegment->mToKey - aSegment->mFromKey);
+ double positionInSegment = (aProgress - aSegment->mFromKey) /
+ // To avoid floating precision inaccuracies, make
+ // sure we calculate both the numerator and
+ // denominator using double precision.
+ (double(aSegment->mToKey) - aSegment->mFromKey);
return ComputedTimingFunction::GetPortion(aSegment->mTimingFunction,
positionInSegment,
aBeforeFlag);
}
RawServoAnimationValueBorrowedOrNull
Gecko_AnimationGetBaseStyle(void* aBaseStyles, nsCSSPropertyID aProperty)
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -373834,16 +373834,22 @@
]
],
"web-animations/animation-model/keyframe-effects/effect-value-context.html": [
[
"/web-animations/animation-model/keyframe-effects/effect-value-context.html",
{}
]
],
+ "web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html": [
+ [
+ "/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html",
+ {}
+ ]
+ ],
"web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [
[
"/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html",
{}
]
],
"web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
[
@@ -546826,17 +546832,17 @@
"a8cfa83e572a766b61e4eae5946e7efb62e9eab7",
"testharness"
],
"css/geometry/DOMMatrix-002.html": [
"c38b9321ebb06ecae2a4217b36493f46b8649636",
"testharness"
],
"css/geometry/DOMMatrix-003.html": [
- "9e2d031f83fbcc4d32a3891fdf2c2d8bc2cc774c",
+ "ed9ca53d25463a9b38414ab9062cf3eb2f8991cb",
"testharness"
],
"css/geometry/DOMMatrix-a-f-alias.html": [
"6041bd4e7fd1535d9c8515f1b2f07981b2bdd366",
"testharness"
],
"css/geometry/DOMMatrix-attributes.html": [
"433984b90fc4579257db57b07a09ae36f7e5b4d3",
@@ -615493,16 +615499,20 @@
"web-animations/animation-model/combining-effects/effect-composition.html": [
"5d6c3904de02eb3b6c890163ccdc6b8cb6499e56",
"testharness"
],
"web-animations/animation-model/keyframe-effects/effect-value-context.html": [
"da405e4bfc35d5d0b4c151706b09eb1a84d2f0da",
"testharness"
],
+ "web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html": [
+ "1610fc05399b88b92f35d556b80a8623d03a5a87",
+ "testharness"
+ ],
"web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html": [
"2c424570af86e1a4541d4f0a67c7693cfcac8abc",
"testharness"
],
"web-animations/animation-model/keyframe-effects/effect-value-overlapping-keyframes.html": [
"2b10d6fb1cb925290caf57e4cefc3c3f8161777c",
"testharness"
],
@@ -615666,17 +615676,17 @@
"e0918d83187c0fbdadaebb14be72c6f34f8dfc03",
"support"
],
"web-animations/resources/xhr-doc.py": [
"de68c45fc1d38a49946f9046f34031e9278a1531",
"support"
],
"web-animations/testcommon.js": [
- "039db95bc6b54f00d6e106241d001ae980566f92",
+ "57883097f4a440ae95b9e665bf8d9e36a187f7d8",
"support"
],
"web-animations/timing-model/animation-effects/active-time.html": [
"f05ff3594dde7248c84db42f8a80a6d0136b5f54",
"testharness"
],
"web-animations/timing-model/animation-effects/current-iteration.html": [
"617bfd8c533d159c4e56ea823917d580fe262bf6",
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/web-animations/animation-model/keyframe-effects/effect-value-interval-distance.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>The effect value of a keyframe effect: Calculating the interval
+ distance between keyframes</title>
+<link rel="help" href="https://drafts.csswg.org/web-animations/#the-effect-value-of-a-keyframe-animation-effect">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../../testcommon.js"></script>
+<body>
+<div id="log"></div>
+<script>
+'use strict';
+
+test(t => {
+ // In Firefox there was a floating precision bug in the calculation of the
+ // progress at the end of the 0.2<->1.0 interval. This test exercises that
+ // calculation in case other UAs suffer from the same problem.
+ const target = createDiv(t);
+ const anim = target.animate(
+ [
+ { opacity: 0 },
+ { offset: 0.2, opacity: 1, easing: 'step-end' },
+ { opacity: 0 },
+ ],
+ {
+ duration: 1000,
+ fill: 'forwards',
+ }
+ );
+
+ anim.currentTime = 1000;
+ assert_equals(getComputedStyle(target).opacity, '0');
+}, 'Interval distance is calculated correctly (precision test)');
+
+</script>
+</body>