Bug 1676791 - Part 5: Define the finite timeline and use it in Play() and Pause(). r=hiro

Based on https://github.com/w3c/csswg-drafts/pull/4842, we define
"has finite timeline", which is a timeline that's not monotonically increasing.
We need this to update start time and hold time for scroll-timeline, so
we play scroll-linked animations as we expected, e.g. GetLocalTime() returns
the correct time value from GetCurrentTimeAsDuration().

Known issue: we still have bugs when setting "animation-play-state:paused".
Will do that in Bug 1741255.

Differential Revision: https://phabricator.services.mozilla.com/D131168
This commit is contained in:
Boris Chiou 2021-12-08 01:16:30 +00:00
Родитель 7ea5fa0013
Коммит fcbeb1d2b0
5 изменённых файлов: 37 добавлений и 8 удалений

Просмотреть файл

@ -493,7 +493,7 @@ void Animation::UpdatePlaybackRate(double aPlaybackRate) {
// https://drafts.csswg.org/web-animations/#play-state
AnimationPlayState Animation::PlayState() const {
Nullable<TimeDuration> currentTime = GetCurrentTimeAsDuration();
if (currentTime.IsNull() && !Pending()) {
if (currentTime.IsNull() && mStartTime.IsNull() && !Pending()) {
return AnimationPlayState::Idle;
}
@ -1350,15 +1350,15 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
AutoMutationBatchForAnimation mb(*this);
bool abortedPause = mPendingState == PendingState::PausePending;
double effectivePlaybackRate = CurrentOrPendingPlaybackRate();
Nullable<TimeDuration> currentTime = GetCurrentTimeAsDuration();
Nullable<TimeDuration> seekTime;
if (effectivePlaybackRate > 0.0 &&
(currentTime.IsNull() || (aLimitBehavior == LimitBehavior::AutoRewind &&
(currentTime.Value() < TimeDuration() ||
currentTime.Value() >= EffectEnd())))) {
mHoldTime.SetValue(TimeDuration(0));
seekTime.SetValue(TimeDuration(0));
} else if (effectivePlaybackRate < 0.0 &&
(currentTime.IsNull() ||
(aLimitBehavior == LimitBehavior::AutoRewind &&
@ -1368,9 +1368,19 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
return aRv.ThrowInvalidStateError(
"Can't rewind animation with infinite effect end");
}
mHoldTime.SetValue(TimeDuration(EffectEnd()));
seekTime.SetValue(TimeDuration(EffectEnd()));
} else if (effectivePlaybackRate == 0.0 && currentTime.IsNull()) {
mHoldTime.SetValue(TimeDuration(0));
seekTime.SetValue(TimeDuration(0));
}
if (!seekTime.IsNull()) {
if (HasFiniteTimeline()) {
mStartTime = seekTime;
mHoldTime.SetNull();
ApplyPendingPlaybackRate();
} else {
mHoldTime = seekTime;
}
}
bool reuseReadyPromise = false;
@ -1390,7 +1400,8 @@ void Animation::PlayNoUpdate(ErrorResult& aRv, LimitBehavior aLimitBehavior) {
// (b) If we have timing changes (specifically a change to the playbackRate)
// that should be applied asynchronously.
//
if (mHoldTime.IsNull() && !abortedPause && !mPendingPlaybackRate) {
if (mHoldTime.IsNull() && seekTime.IsNull() && !abortedPause &&
!mPendingPlaybackRate) {
return;
}
@ -1443,15 +1454,24 @@ void Animation::Pause(ErrorResult& aRv) {
AutoMutationBatchForAnimation mb(*this);
Nullable<TimeDuration> seekTime;
// If we are transitioning from idle, fill in the current time
if (GetCurrentTimeAsDuration().IsNull()) {
if (mPlaybackRate >= 0.0) {
mHoldTime.SetValue(TimeDuration(0));
seekTime.SetValue(TimeDuration(0));
} else {
if (EffectEnd() == TimeDuration::Forever()) {
return aRv.ThrowInvalidStateError("Can't seek to infinite effect end");
}
mHoldTime.SetValue(TimeDuration(EffectEnd()));
seekTime.SetValue(TimeDuration(EffectEnd()));
}
}
if (!seekTime.IsNull()) {
if (HasFiniteTimeline()) {
mStartTime = seekTime;
} else {
mHoldTime = seekTime;
}
}

Просмотреть файл

@ -557,6 +557,10 @@ class Animation : public DOMEventTargetHelper,
Document* GetRenderedDocument() const;
Document* GetTimelineDocument() const;
bool HasFiniteTimeline() const {
return mTimeline && !mTimeline->IsMonotonicallyIncreasing();
}
RefPtr<AnimationTimeline> mTimeline;
RefPtr<AnimationEffect> mEffect;
// The beginning of the delay period.

Просмотреть файл

@ -101,6 +101,8 @@ class AnimationTimeline : public nsISupports, public nsWrapperCache {
virtual Document* GetDocument() const = 0;
virtual bool IsMonotonicallyIncreasing() const = 0;
virtual bool IsScrollTimeline() const { return false; }
protected:

Просмотреть файл

@ -68,6 +68,8 @@ class DocumentTimeline final : public AnimationTimeline,
Document* GetDocument() const override { return mDocument; }
bool IsMonotonicallyIncreasing() const override { return true; }
protected:
TimeStamp GetCurrentTimeStamp() const;
nsRefreshDriver* GetRefreshDriver() const;

Просмотреть файл

@ -87,6 +87,7 @@ class ScrollTimeline final : public AnimationTimeline {
return {};
}
Document* GetDocument() const override { return mDocument; }
bool IsMonotonicallyIncreasing() const override { return false; }
bool IsScrollTimeline() const override { return true; }
void ScheduleAnimations() {