Commit 473c692f authored by alancutter's avatar alancutter Committed by Commit bot

Web Animations: Account for end delay in after phase active time

This change implements a tweak to the Web Animations spec:
https://github.com/w3c/web-animations/commit/a9ba51338ed09170d16c47317f8e4e2eef122a82

Negative end delay now affects the progress used in the after phase.

Review-Url: https://codereview.chromium.org/2030843002
Cr-Commit-Position: refs/heads/master@{#407690}
parent b3886ee2
This is a testharness.js-based test.
PASS changed duration immediately updates its computed styles
PASS changed iterations immediately updates its computed styles
PASS change currentTime when fill is none and endDelay is positive
PASS change currentTime when fill forwards and endDelay is positive
PASS change currentTime when fill none and endDelay is negative
FAIL change currentTime when fill forwards and endDelay is negative assert_equals: set currentTime same as endTime expected "0" but got "0.5"
PASS change direction from "normal" to "reverse"
PASS change direction from "normal" to "alternate"
PASS change direction from "normal" to "alternate-reverse"
PASS change direction from "normal" to "reverse"
Harness: the test ran to completion.
...@@ -48,8 +48,8 @@ testTiming({ ...@@ -48,8 +48,8 @@ testTiming({
{ at: 1, expect: 0 }, { at: 1, expect: 0 },
{ at: 2, expect: 0.1 }, { at: 2, expect: 0.1 },
{ at: 9, expect: 0.8 }, { at: 9, expect: 0.8 },
{ at: 10, expect: 1 }, { at: 10, expect: 0.9 },
{ at: 11, expect: 1 }, { at: 11, expect: 0.9 },
], ],
}, 'Positive delay and negative endDelay'); }, 'Positive delay and negative endDelay');
...@@ -84,9 +84,9 @@ testTiming({ ...@@ -84,9 +84,9 @@ testTiming({
{ at: 0, expect: 0.1 }, { at: 0, expect: 0.1 },
{ at: 1, expect: 0.2 }, { at: 1, expect: 0.2 },
{ at: 7, expect: 0.8 }, { at: 7, expect: 0.8 },
{ at: 8, expect: 1 }, { at: 8, expect: 0.9 },
{ at: 9, expect: 1 }, { at: 9, expect: 0.9 },
{ at: 10, expect: 1 }, { at: 10, expect: 0.9 },
], ],
}, 'delay and endDelay both negative'); }, 'delay and endDelay both negative');
...@@ -99,12 +99,12 @@ testTiming({ ...@@ -99,12 +99,12 @@ testTiming({
}, },
expectations: [ expectations: [
{ at: -2, expect: 0 }, { at: -2, expect: 0 },
{ at: -1, expect: 1 }, { at: -1, expect: 0 },
{ at: 0, expect: 1 }, { at: 0, expect: 0 },
{ at: 5, expect: 1 }, { at: 5, expect: 0 },
{ at: 10, expect: 1 }, { at: 10, expect: 0 },
{ at: 11, expect: 1 }, { at: 11, expect: 0 },
{ at: 12, expect: 1 }, { at: 12, expect: 0 },
], ],
}, 'Negative endDelay that eclipses delay and duration'); }, 'Negative endDelay that eclipses delay and duration');
</script> </script>
<!DOCTYPE html>
<meta charset=utf-8>
<title>Tests for effect clipping via negative end delay</title>
<link rel="help" href="http://w3c.github.io/web-animations/#calculating-the-active-time">
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="../imported/wpt/web-animations/testcommon.js"></script>
<body>
<script>
'use strict';
test(function(t) {
var animation = createDiv(t).animate(null, {
fill: 'forwards',
duration: 1,
endDelay: -1,
});
animation.currentTime = 10;
assert_equals(animation.effect.getComputedTiming().progress, 0,
'Progress should be zero since we clip to the start of the animation');
}, 'Negative end delay clipping into the start of the animation');
test(function(t) {
var animation = createDiv(t).animate(null, {
fill: 'forwards',
duration: 1,
iterations: 2,
endDelay: -1,
});
animation.currentTime = 10;
assert_equals(animation.effect.getComputedTiming().progress, 1,
'Progress should be 1 since we clip to the end of the first iteration ' +
'and the second iteration does not have a chance to start');
}, 'Negative end delay clipping to the end of the the first iteration');
test(function(t) {
var animation = createDiv(t).animate(null, {
fill: 'forwards',
duration: 1,
iterations: 2,
endDelay: -0.75,
});
animation.currentTime = 10;
assert_equals(animation.effect.getComputedTiming().progress, 0.25,
'Progress should be 0.25 since we clip part way through the second iteration');
}, 'Negative end delay clipping part way into the second iteration');
test(function(t) {
var animation = createDiv(t).animate(null, {
fill: 'forwards',
duration: 1,
iterations: 0,
endDelay: -1,
});
animation.currentTime = 10;
assert_equals(animation.effect.getComputedTiming().progress, 0,
'Progress should be 0 since there are no iterations to make progress in');
}, 'Negative end delay clipping into zero iterations');
</script>
</body>
...@@ -156,7 +156,7 @@ void AnimationEffect::updateInheritedTime(double inheritedTime, TimingUpdateReas ...@@ -156,7 +156,7 @@ void AnimationEffect::updateInheritedTime(double inheritedTime, TimingUpdateReas
const double startOffset = multiplyZeroAlwaysGivesZero(m_timing.iterationStart, iterationDuration); const double startOffset = multiplyZeroAlwaysGivesZero(m_timing.iterationStart, iterationDuration);
ASSERT(startOffset >= 0); ASSERT(startOffset >= 0);
const double scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, m_timing); const double scaledActiveTime = calculateScaledActiveTime(activeDuration, activeTime, startOffset, m_timing);
const double iterationTime = calculateIterationTime(iterationDuration, repeatedDuration(), scaledActiveTime, startOffset, m_timing); const double iterationTime = calculateIterationTime(iterationDuration, repeatedDuration(), scaledActiveTime, startOffset, currentPhase, m_timing);
currentIteration = calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, m_timing); currentIteration = calculateCurrentIteration(iterationDuration, iterationTime, scaledActiveTime, m_timing);
const double transformedTime = calculateTransformedTime(currentIteration, iterationDuration, iterationTime, m_timing); const double transformedTime = calculateTransformedTime(currentIteration, iterationDuration, iterationTime, m_timing);
...@@ -187,7 +187,7 @@ void AnimationEffect::updateInheritedTime(double inheritedTime, TimingUpdateReas ...@@ -187,7 +187,7 @@ void AnimationEffect::updateInheritedTime(double inheritedTime, TimingUpdateReas
const double startOffset = m_timing.iterationStart * localIterationDuration; const double startOffset = m_timing.iterationStart * localIterationDuration;
ASSERT(startOffset >= 0); ASSERT(startOffset >= 0);
const double scaledActiveTime = calculateScaledActiveTime(localActiveDuration, localActiveTime, startOffset, m_timing); const double scaledActiveTime = calculateScaledActiveTime(localActiveDuration, localActiveTime, startOffset, m_timing);
const double iterationTime = calculateIterationTime(localIterationDuration, localRepeatedDuration, scaledActiveTime, startOffset, m_timing); const double iterationTime = calculateIterationTime(localIterationDuration, localRepeatedDuration, scaledActiveTime, startOffset, currentPhase, m_timing);
currentIteration = calculateCurrentIteration(localIterationDuration, iterationTime, scaledActiveTime, m_timing); currentIteration = calculateCurrentIteration(localIterationDuration, iterationTime, scaledActiveTime, m_timing);
progress = calculateTransformedTime(currentIteration, localIterationDuration, iterationTime, m_timing); progress = calculateTransformedTime(currentIteration, localIterationDuration, iterationTime, m_timing);
......
...@@ -89,7 +89,7 @@ static inline double calculateActiveTime(double activeDuration, Timing::FillMode ...@@ -89,7 +89,7 @@ static inline double calculateActiveTime(double activeDuration, Timing::FillMode
return nullValue(); return nullValue();
case AnimationEffect::PhaseAfter: case AnimationEffect::PhaseAfter:
if (fillMode == Timing::FillModeForwards || fillMode == Timing::FillModeBoth) if (fillMode == Timing::FillModeForwards || fillMode == Timing::FillModeBoth)
return activeDuration; return std::max(0.0, std::min(activeDuration, activeDuration + specified.endDelay));
return nullValue(); return nullValue();
case AnimationEffect::PhaseNone: case AnimationEffect::PhaseNone:
ASSERT(isNull(localTime)); ASSERT(isNull(localTime));
...@@ -125,7 +125,8 @@ static inline bool endsOnIterationBoundary(double iterationCount, double iterati ...@@ -125,7 +125,8 @@ static inline bool endsOnIterationBoundary(double iterationCount, double iterati
return !fmod(iterationCount + iterationStart, 1); return !fmod(iterationCount + iterationStart, 1);
} }
static inline double calculateIterationTime(double iterationDuration, double repeatedDuration, double scaledActiveTime, double startOffset, const Timing& specified) // TODO(crbug.com/630915): Align this function with current Web Animations spec text.
static inline double calculateIterationTime(double iterationDuration, double repeatedDuration, double scaledActiveTime, double startOffset, AnimationEffect::Phase phase, const Timing& specified)
{ {
ASSERT(iterationDuration > 0); ASSERT(iterationDuration > 0);
ASSERT(repeatedDuration == multiplyZeroAlwaysGivesZero(iterationDuration, specified.iterationCount)); ASSERT(repeatedDuration == multiplyZeroAlwaysGivesZero(iterationDuration, specified.iterationCount));
...@@ -141,7 +142,17 @@ static inline double calculateIterationTime(double iterationDuration, double rep ...@@ -141,7 +142,17 @@ static inline double calculateIterationTime(double iterationDuration, double rep
return iterationDuration; return iterationDuration;
ASSERT(std::isfinite(scaledActiveTime)); ASSERT(std::isfinite(scaledActiveTime));
return fmod(scaledActiveTime, iterationDuration); double iterationTime = fmod(scaledActiveTime, iterationDuration);
// This implements step 3 of
// http://w3c.github.io/web-animations/#calculating-the-simple-iteration-progress
if (iterationTime == 0
&& phase == AnimationEffect::PhaseAfter
&& repeatedDuration != 0
&& scaledActiveTime != 0)
return iterationDuration;
return iterationTime;
} }
static inline double calculateCurrentIteration(double iterationDuration, double iterationTime, double scaledActiveTime, const Timing& specified) static inline double calculateCurrentIteration(double iterationDuration, double iterationTime, double scaledActiveTime, const Timing& specified)
......
...@@ -101,20 +101,20 @@ TEST(AnimationTimingCalculationsTest, IterationTime) ...@@ -101,20 +101,20 @@ TEST(AnimationTimingCalculationsTest, IterationTime)
{ {
Timing timing; Timing timing;
// calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, timing) // calculateIterationTime(iterationDuration, repeatedDuration, scaledActiveTime, startOffset, phase, timing)
// if the scaled active time is null // if the scaled active time is null
EXPECT_TRUE(isNull(calculateIterationTime(1, 1, nullValue(), 1, timing))); EXPECT_TRUE(isNull(calculateIterationTime(1, 1, nullValue(), 1, AnimationEffect::PhaseActive, timing)));
// if (complex-conditions)... // if (complex-conditions)...
EXPECT_EQ(12, calculateIterationTime(12, 12, 12, 0, timing)); EXPECT_EQ(12, calculateIterationTime(12, 12, 12, 0, AnimationEffect::PhaseActive, timing));
// otherwise // otherwise
timing.iterationCount = 10; timing.iterationCount = 10;
EXPECT_EQ(5, calculateIterationTime(10, 100, 25, 4, timing)); EXPECT_EQ(5, calculateIterationTime(10, 100, 25, 4, AnimationEffect::PhaseActive, timing));
EXPECT_EQ(7, calculateIterationTime(11, 110, 29, 1, timing)); EXPECT_EQ(7, calculateIterationTime(11, 110, 29, 1, AnimationEffect::PhaseActive, timing));
timing.iterationStart = 1.1; timing.iterationStart = 1.1;
EXPECT_EQ(8, calculateIterationTime(12, 120, 20, 7, timing)); EXPECT_EQ(8, calculateIterationTime(12, 120, 20, 7, AnimationEffect::PhaseActive, timing));
} }
TEST(AnimationTimingCalculationsTest, CurrentIteration) TEST(AnimationTimingCalculationsTest, CurrentIteration)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment