|
@@ -2360,85 +2360,84 @@ void Document::dispatch_events_for_animation_if_necessary(GC::Ref<Animations::An
|
|
|
auto current_phase = effect->phase();
|
|
|
auto current_iteration = effect->current_iteration().value_or(0.0);
|
|
|
|
|
|
- if (previous_phase != current_phase) {
|
|
|
- auto owning_element = css_animation.owning_element();
|
|
|
-
|
|
|
- auto dispatch_event = [&](FlyString const& name, double elapsed_time) {
|
|
|
- append_pending_animation_event({
|
|
|
- .event = CSS::AnimationEvent::create(
|
|
|
- owning_element->realm(),
|
|
|
- name,
|
|
|
- {
|
|
|
- { .bubbles = true },
|
|
|
- css_animation.id(),
|
|
|
- elapsed_time,
|
|
|
- }),
|
|
|
- .animation = css_animation,
|
|
|
- .target = *target,
|
|
|
- .scheduled_event_time = HighResolutionTime::unsafe_shared_current_time(),
|
|
|
- });
|
|
|
- };
|
|
|
+ auto owning_element = css_animation.owning_element();
|
|
|
|
|
|
- // For calculating the elapsedTime of each event, the following definitions are used:
|
|
|
+ auto dispatch_event = [&](FlyString const& name, double elapsed_time) {
|
|
|
+ append_pending_animation_event({
|
|
|
+ .event = CSS::AnimationEvent::create(
|
|
|
+ owning_element->realm(),
|
|
|
+ name,
|
|
|
+ {
|
|
|
+ { .bubbles = true },
|
|
|
+ css_animation.id(),
|
|
|
+ elapsed_time,
|
|
|
+ }),
|
|
|
+ .animation = css_animation,
|
|
|
+ .target = *target,
|
|
|
+ .scheduled_event_time = HighResolutionTime::unsafe_shared_current_time(),
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- // - interval start = max(min(-start delay, active duration), 0)
|
|
|
- auto interval_start = max(min(-effect->start_delay(), effect->active_duration()), 0.0);
|
|
|
+ // For calculating the elapsedTime of each event, the following definitions are used:
|
|
|
|
|
|
- // - interval end = max(min(associated effect end - start delay, active duration), 0)
|
|
|
- auto interval_end = max(min(effect->end_time() - effect->start_delay(), effect->active_duration()), 0.0);
|
|
|
+ // - interval start = max(min(-start delay, active duration), 0)
|
|
|
+ auto interval_start = max(min(-effect->start_delay(), effect->active_duration()), 0.0);
|
|
|
|
|
|
- switch (previous_phase) {
|
|
|
- case Animations::AnimationEffect::Phase::Before:
|
|
|
- [[fallthrough]];
|
|
|
- case Animations::AnimationEffect::Phase::Idle:
|
|
|
- if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
- dispatch_event(HTML::EventNames::animationstart, interval_start);
|
|
|
- } else if (current_phase == Animations::AnimationEffect::Phase::After) {
|
|
|
- dispatch_event(HTML::EventNames::animationstart, interval_start);
|
|
|
- dispatch_event(HTML::EventNames::animationend, interval_end);
|
|
|
- }
|
|
|
- break;
|
|
|
- case Animations::AnimationEffect::Phase::Active:
|
|
|
- if (current_phase == Animations::AnimationEffect::Phase::Before) {
|
|
|
- dispatch_event(HTML::EventNames::animationend, interval_start);
|
|
|
- } else if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
- auto previous_current_iteration = effect->previous_current_iteration();
|
|
|
- if (previous_current_iteration != current_iteration) {
|
|
|
- // The elapsed time for an animationiteration event is defined as follows:
|
|
|
-
|
|
|
- // 1. Let previous current iteration be the current iteration from the previous animation frame.
|
|
|
-
|
|
|
- // 2. If previous current iteration is greater than current iteration, let iteration boundary be current iteration + 1,
|
|
|
- // otherwise let it be current iteration.
|
|
|
- auto iteration_boundary = previous_current_iteration > current_iteration ? current_iteration + 1 : current_iteration;
|
|
|
-
|
|
|
- // 3. The elapsed time is the result of evaluating (iteration boundary - iteration start) × iteration duration).
|
|
|
- auto iteration_duration_variant = effect->iteration_duration();
|
|
|
- auto iteration_duration = iteration_duration_variant.has<String>() ? 0.0 : iteration_duration_variant.get<double>();
|
|
|
- auto elapsed_time = (iteration_boundary - effect->iteration_start()) * iteration_duration;
|
|
|
-
|
|
|
- dispatch_event(HTML::EventNames::animationiteration, elapsed_time);
|
|
|
- }
|
|
|
- } else if (current_phase == Animations::AnimationEffect::Phase::After) {
|
|
|
- dispatch_event(HTML::EventNames::animationend, interval_end);
|
|
|
- }
|
|
|
- break;
|
|
|
- case Animations::AnimationEffect::Phase::After:
|
|
|
- if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
- dispatch_event(HTML::EventNames::animationstart, interval_end);
|
|
|
- } else if (current_phase == Animations::AnimationEffect::Phase::Before) {
|
|
|
- dispatch_event(HTML::EventNames::animationstart, interval_end);
|
|
|
- dispatch_event(HTML::EventNames::animationend, interval_start);
|
|
|
+ // - interval end = max(min(associated effect end - start delay, active duration), 0)
|
|
|
+ auto interval_end = max(min(effect->end_time() - effect->start_delay(), effect->active_duration()), 0.0);
|
|
|
+
|
|
|
+ switch (previous_phase) {
|
|
|
+ case Animations::AnimationEffect::Phase::Before:
|
|
|
+ [[fallthrough]];
|
|
|
+ case Animations::AnimationEffect::Phase::Idle:
|
|
|
+ if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
+ dispatch_event(HTML::EventNames::animationstart, interval_start);
|
|
|
+ } else if (current_phase == Animations::AnimationEffect::Phase::After) {
|
|
|
+ dispatch_event(HTML::EventNames::animationstart, interval_start);
|
|
|
+ dispatch_event(HTML::EventNames::animationend, interval_end);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case Animations::AnimationEffect::Phase::Active:
|
|
|
+ if (current_phase == Animations::AnimationEffect::Phase::Before) {
|
|
|
+ dispatch_event(HTML::EventNames::animationend, interval_start);
|
|
|
+ } else if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
+ auto previous_current_iteration = effect->previous_current_iteration();
|
|
|
+ if (previous_current_iteration != current_iteration) {
|
|
|
+ // The elapsed time for an animationiteration event is defined as follows:
|
|
|
+
|
|
|
+ // 1. Let previous current iteration be the current iteration from the previous animation frame.
|
|
|
+
|
|
|
+ // 2. If previous current iteration is greater than current iteration, let iteration boundary be current iteration + 1,
|
|
|
+ // otherwise let it be current iteration.
|
|
|
+ auto iteration_boundary = previous_current_iteration > current_iteration ? current_iteration + 1 : current_iteration;
|
|
|
+
|
|
|
+ // 3. The elapsed time is the result of evaluating (iteration boundary - iteration start) × iteration duration).
|
|
|
+ auto iteration_duration_variant = effect->iteration_duration();
|
|
|
+ auto iteration_duration = iteration_duration_variant.has<String>() ? 0.0 : iteration_duration_variant.get<double>();
|
|
|
+ auto elapsed_time = (iteration_boundary - effect->iteration_start()) * iteration_duration;
|
|
|
+
|
|
|
+ dispatch_event(HTML::EventNames::animationiteration, elapsed_time);
|
|
|
}
|
|
|
- break;
|
|
|
+ } else if (current_phase == Animations::AnimationEffect::Phase::After) {
|
|
|
+ dispatch_event(HTML::EventNames::animationend, interval_end);
|
|
|
}
|
|
|
-
|
|
|
- if (current_phase == Animations::AnimationEffect::Phase::Idle && previous_phase != Animations::AnimationEffect::Phase::Idle && previous_phase != Animations::AnimationEffect::Phase::After) {
|
|
|
- // FIXME: Calculate a non-zero time when the animation is cancelled by means other than calling cancel()
|
|
|
- auto cancel_time = animation->release_saved_cancel_time().value_or(0.0);
|
|
|
- dispatch_event(HTML::EventNames::animationcancel, cancel_time);
|
|
|
+ break;
|
|
|
+ case Animations::AnimationEffect::Phase::After:
|
|
|
+ if (current_phase == Animations::AnimationEffect::Phase::Active) {
|
|
|
+ dispatch_event(HTML::EventNames::animationstart, interval_end);
|
|
|
+ } else if (current_phase == Animations::AnimationEffect::Phase::Before) {
|
|
|
+ dispatch_event(HTML::EventNames::animationstart, interval_end);
|
|
|
+ dispatch_event(HTML::EventNames::animationend, interval_start);
|
|
|
}
|
|
|
+ break;
|
|
|
}
|
|
|
+
|
|
|
+ if (current_phase == Animations::AnimationEffect::Phase::Idle && previous_phase != Animations::AnimationEffect::Phase::Idle && previous_phase != Animations::AnimationEffect::Phase::After) {
|
|
|
+ // FIXME: Calculate a non-zero time when the animation is cancelled by means other than calling cancel()
|
|
|
+ auto cancel_time = animation->release_saved_cancel_time().value_or(0.0);
|
|
|
+ dispatch_event(HTML::EventNames::animationcancel, cancel_time);
|
|
|
+ }
|
|
|
+
|
|
|
effect->set_previous_phase(current_phase);
|
|
|
effect->set_previous_current_iteration(current_iteration);
|
|
|
}
|