LibWeb: Implement Animation.updatePlaybackRate()

This commit is contained in:
Matthew Olsson 2024-02-10 15:55:53 -07:00 committed by Andreas Kling
parent d351389d72
commit 9ab73f2675
Notes: sideshowbarker 2024-07-17 12:02:22 +09:00
3 changed files with 67 additions and 1 deletions

View file

@ -700,6 +700,71 @@ WebIDL::ExceptionOr<void> Animation::pause()
return {};
}
// https://www.w3.org/TR/web-animations-1/#dom-animation-updateplaybackrate
WebIDL::ExceptionOr<void> Animation::update_playback_rate(double new_playback_rate)
{
// 1. Let previous play state be animations play state.
// Note: It is necessary to record the play state before updating animations effective playback rate since, in the
// following logic, we want to immediately apply the pending playback rate of animation if it is currently
// finished regardless of whether or not it will still be finished after we apply the pending playback rate.
auto previous_play_state = play_state();
// 2. Let animations pending playback rate be new playback rate.
m_pending_playback_rate = new_playback_rate;
// 3. Perform the steps corresponding to the first matching condition from below:
// -> If animation has a pending play task or a pending pause task,
if (pending()) {
// Abort these steps.
// Note: The different types of pending tasks will apply the pending playback rate when they run so there is no
// further action required in this case.
return {};
}
// -> If previous play state is idle or paused, or animations current time is unresolved,
if (previous_play_state == Bindings::AnimationPlayState::Idle || previous_play_state == Bindings::AnimationPlayState::Paused || !current_time().has_value()) {
// Apply any pending playback rate on animation.
// Note: the second condition above is required so that if we have a running animation with an unresolved
// current time and no pending play task, we do not attempt to play it below.
apply_any_pending_playback_rate();
}
// -> If previous play state is finished,
else if (previous_play_state == Bindings::AnimationPlayState::Finished) {
// 1. Let the unconstrained current time be the result of calculating the current time of animation
// substituting an unresolved time value for the hold time.
Optional<double> unconstrained_current_time;
{
TemporaryChange change(m_hold_time, {});
unconstrained_current_time = current_time();
}
// 2. Let animations start time be the result of evaluating the following expression:
// timeline time - (unconstrained current time / pending playback rate)
// Where timeline time is the current time value of the timeline associated with animation.
// If pending playback rate is zero, let animations start time be timeline time.
if (m_pending_playback_rate.value() == 0.0) {
m_start_time = m_timeline->current_time().value();
} else {
m_start_time = m_timeline->current_time().value() - (unconstrained_current_time.value() / m_pending_playback_rate.value());
}
// 3. Apply any pending playback rate on animation.
apply_any_pending_playback_rate();
// 4. Run the procedure to update an animations finished state for animation with the did seek flag set to
// false, and the synchronously notify flag set to false.
update_finished_state(DidSeek::No, SynchronouslyNotify::No);
}
// -> Otherwise,
else {
// Run the procedure to play an animation for animation with the auto-rewind flag set to false.
TRY(play_an_animation(AutoRewind::No));
}
return {};
}
// https://www.w3.org/TR/web-animations-1/#dom-animation-persist
void Animation::persist()
{

View file

@ -75,6 +75,7 @@ public:
WebIDL::ExceptionOr<void> play();
WebIDL::ExceptionOr<void> play_an_animation(AutoRewind);
WebIDL::ExceptionOr<void> pause();
WebIDL::ExceptionOr<void> update_playback_rate(double);
void persist();
Optional<double> convert_an_animation_time_to_timeline_time(Optional<double>) const;

View file

@ -28,7 +28,7 @@ interface Animation : EventTarget {
undefined finish();
undefined play();
undefined pause();
// FIXME: undefined updatePlaybackRate(double playbackRate);
undefined updatePlaybackRate(double playbackRate);
// FIXME: undefined reverse();
undefined persist();
// FIXME: [CEReactions] undefined commitStyles();