1use crate::context::{CascadeInputs, SharedStyleContext};
11use crate::derives::*;
12use crate::dom::{OpaqueNode, TDocument, TElement, TNode};
13use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
14use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
15use crate::properties::longhands::animation_fill_mode::computed_value::single_value::T as AnimationFillMode;
16use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
17use crate::properties::AnimationDeclarations;
18use crate::properties::{
19 ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
20 PropertyDeclarationIdSet,
21};
22use crate::rule_tree::{CascadeLevel, CascadeOrigin, RuleCascadeFlags};
23use crate::selector_parser::PseudoElement;
24use crate::shared_lock::{Locked, SharedRwLock};
25use crate::style_resolver::StyleResolverForElement;
26use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
27use crate::stylesheets::layer_rule::LayerOrder;
28use crate::values::animated::{Animate, Procedure};
29use crate::values::computed::TimingFunction;
30use crate::values::generics::easing::BeforeFlag;
31use crate::values::specified::TransitionBehavior;
32use crate::Atom;
33use parking_lot::RwLock;
34use rustc_hash::FxHashMap;
35use servo_arc::Arc;
36use std::fmt;
37
38#[derive(Clone, Debug, MallocSizeOf)]
40pub struct PropertyAnimation {
41 from: AnimationValue,
43
44 to: AnimationValue,
46
47 timing_function: TimingFunction,
49
50 pub duration: f64,
52}
53
54impl PropertyAnimation {
55 pub fn property_id(&self) -> PropertyDeclarationId<'_> {
57 debug_assert_eq!(self.from.id(), self.to.id());
58 self.from.id()
59 }
60
61 fn timing_function_output(&self, progress: f64) -> f64 {
63 let epsilon = 1. / (200. * self.duration);
64 self.timing_function
70 .calculate_output(progress, BeforeFlag::Unset, epsilon)
71 }
72
73 fn calculate_value(&self, progress: f64) -> AnimationValue {
75 let progress = self.timing_function_output(progress);
76 let procedure = Procedure::Interpolate { progress };
77 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
78 if progress < 0.5 {
80 self.from.clone()
81 } else {
82 self.to.clone()
83 }
84 })
85 }
86}
87
88#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
90pub enum AnimationState {
91 Pending,
94 Running,
96 Paused(f64),
99 Finished,
101 Canceled,
103}
104
105impl AnimationState {
106 fn needs_to_be_ticked(&self) -> bool {
108 *self == AnimationState::Running || *self == AnimationState::Pending
109 }
110}
111
112enum IgnoreTransitions {
113 Canceled,
114 CanceledAndFinished,
115}
116
117#[derive(Clone, Debug, MallocSizeOf)]
122pub enum KeyframesIterationState {
123 Infinite(f64),
125 Finite(f64, f64),
127}
128
129#[derive(Debug)]
134struct IntermediateComputedKeyframe {
135 declarations: PropertyDeclarationBlock,
136 timing_function: Option<TimingFunction>,
137 start_percentage: f32,
138}
139
140impl IntermediateComputedKeyframe {
141 fn new(start_percentage: f32) -> Self {
142 IntermediateComputedKeyframe {
143 declarations: PropertyDeclarationBlock::new(),
144 timing_function: None,
145 start_percentage,
146 }
147 }
148
149 fn generate_for_keyframes(
152 animation: &KeyframesAnimation,
153 context: &SharedStyleContext,
154 base_style: &ComputedValues,
155 ) -> Vec<Self> {
156 if animation.steps.is_empty() {
157 return vec![];
158 }
159
160 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
161 let mut current_step = IntermediateComputedKeyframe::new(0.);
162 for step in animation.steps.iter() {
163 let start_percentage = step.start_percentage.0;
164 if start_percentage != current_step.start_percentage {
165 let new_step = IntermediateComputedKeyframe::new(start_percentage);
166 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
167 }
168
169 current_step.update_from_step(step, context, base_style);
170 }
171 intermediate_steps.push(current_step);
172
173 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
176 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
177
178 intermediate_steps
179 }
180
181 fn update_from_step(
182 &mut self,
183 step: &KeyframesStep,
184 context: &SharedStyleContext,
185 base_style: &ComputedValues,
186 ) {
187 let guard = &context.guards.author;
190 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
191 self.timing_function = Some(timing_function.to_computed_value_without_context());
192 }
193
194 let block = match step.value {
195 KeyframesStepValue::ComputedValues => return,
196 KeyframesStepValue::Declarations { ref block } => block,
197 };
198
199 let guard = block.read_with(&guard);
202 for declaration in guard.normal_declaration_iter() {
203 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
204 if id == LonghandId::Display {
205 continue;
206 }
207
208 if !id.is_animatable() {
209 continue;
210 }
211 }
212
213 self.declarations.push(
214 declaration.to_physical(base_style.writing_mode),
215 Importance::Normal,
216 );
217 }
218 }
219
220 fn resolve_style<E>(
221 self,
222 element: E,
223 context: &SharedStyleContext,
224 base_style: &Arc<ComputedValues>,
225 resolver: &mut StyleResolverForElement<E>,
226 ) -> Arc<ComputedValues>
227 where
228 E: TElement,
229 {
230 if !self.declarations.any_normal() {
231 return base_style.clone();
232 }
233
234 let document = element.as_node().owner_doc();
235 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
236 let mut important_rules_changed = false;
237 let rule_node = base_style.rules().clone();
238 let new_node = context.stylist.rule_tree().update_rule_at_level(
239 CascadeLevel::new(CascadeOrigin::Animations),
240 LayerOrder::root(),
241 Some(locked_block.borrow_arc()),
242 &rule_node,
243 &context.guards,
244 &mut important_rules_changed,
245 );
246
247 if new_node.is_none() {
248 return base_style.clone();
249 }
250
251 let inputs = CascadeInputs {
252 rules: new_node,
253 visited_rules: base_style.visited_rules().cloned(),
254 flags: base_style.flags.for_cascade_inputs(),
255 included_cascade_flags: RuleCascadeFlags::empty(),
256 };
257 resolver
258 .cascade_style_and_visited_with_default_parents(inputs)
259 .0
260 }
261}
262
263#[derive(Clone, Debug, MallocSizeOf)]
264struct PropertyDeclarationOffsets {
265 preceding_declaration: usize,
268 following_declaration: usize,
271}
272
273#[derive(Clone, Debug, MallocSizeOf)]
274enum AnimationValueOrReference {
275 AnimationValue(AnimationValue),
277 NotDefinedHere(PropertyDeclarationOffsets),
279}
280
281#[derive(Clone, Debug, MallocSizeOf)]
283struct ComputedKeyframe {
284 timing_function: TimingFunction,
287
288 start_percentage: f32,
291
292 values: Box<[AnimationValueOrReference]>,
295}
296
297#[derive(Clone, Copy, Debug, Default)]
303struct KeyframeOffsetCacheForProperty {
304 last_keyframe_that_defined_property: usize,
310
311 next_keyframe_that_defines_property: Option<usize>,
317}
318
319struct KeyframeDataForProperty<'a> {
320 timing_function: &'a TimingFunction,
323
324 start_percentage: f32,
327
328 value: &'a AnimationValue,
329}
330
331#[derive(Clone, Copy, Debug)]
332enum Direction {
333 Forward,
334 Backward,
335}
336
337impl Direction {
338 fn relative_to_animation_direction(&self, reverse: bool) -> Self {
339 match self {
340 Self::Forward if reverse => Self::Backward,
341 Self::Backward if reverse => Self::Forward,
342 _ => *self,
343 }
344 }
345}
346
347impl Animation {
348 fn next_relevant_keyframe_for_property_in_direction(
353 &self,
354 property_index: usize,
355 keyframe_index: usize,
356 direction: Direction,
357 ) -> Option<KeyframeDataForProperty<'_>> {
358 let relevant_keyframe = &self.computed_steps[keyframe_index];
359 let parameters = match &relevant_keyframe.values[property_index] {
360 AnimationValueOrReference::AnimationValue(animation_value) => KeyframeDataForProperty {
361 timing_function: &relevant_keyframe.timing_function,
362 start_percentage: relevant_keyframe.start_percentage,
363 value: animation_value,
364 },
365 AnimationValueOrReference::NotDefinedHere(offsets) => {
366 let next_relevant_keyframe_index = match direction {
367 Direction::Forward => offsets.following_declaration,
368 Direction::Backward => offsets.preceding_declaration,
369 };
370 let next_relevant_keyframe = &self.computed_steps[next_relevant_keyframe_index];
371 let AnimationValueOrReference::AnimationValue(animation_value) =
372 &next_relevant_keyframe.values[property_index]
373 else {
374 panic!("Referenced keyframe does not set property");
375 };
376
377 KeyframeDataForProperty {
378 timing_function: &next_relevant_keyframe.timing_function,
379 start_percentage: next_relevant_keyframe.start_percentage,
380 value: &animation_value,
381 }
382 },
383 };
384
385 Some(parameters)
386 }
387}
388impl ComputedKeyframe {
389 fn generate_for_keyframes<E>(
390 element: E,
391 animation: &KeyframesAnimation,
392 context: &SharedStyleContext,
393 base_style: &Arc<ComputedValues>,
394 default_timing_function: TimingFunction,
395 resolver: &mut StyleResolverForElement<E>,
396 animating_properties: PropertyDeclarationIdSet,
397 number_of_animating_properties: usize,
398 ) -> Box<[Self]>
399 where
400 E: TElement,
401 {
402 let animation_values_from_style: Vec<AnimationValue> = animating_properties
403 .iter()
404 .map(|property| {
405 AnimationValue::from_computed_values(property, &**base_style)
406 .expect("Unexpected non-animatable property.")
407 })
408 .collect();
409
410 let intermediate_steps =
411 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
412
413 let mut keyframe_offset_caches: Vec<KeyframeOffsetCacheForProperty> =
417 vec![Default::default(); number_of_animating_properties];
418
419 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
420 let mut remaining_steps = intermediate_steps.into_iter();
421 let mut step_index = 0;
422 while let Some(step) = remaining_steps.next() {
423 let start_percentage = step.start_percentage;
424 let properties_changed_in_step = step.declarations.property_ids().clone();
425 let timing_function = step
426 .timing_function
427 .clone()
428 .unwrap_or_else(|| default_timing_function.clone());
429 let step_style = step.resolve_style(element, context, base_style, resolver);
430
431 let values: Box<[_]> = {
432 animating_properties
435 .iter()
436 .enumerate()
437 .map(|(property_index, property_declaration)| {
438 let keyframe_offset_cache = &mut keyframe_offset_caches[property_index];
439 if properties_changed_in_step.contains(property_declaration) {
440 keyframe_offset_cache.last_keyframe_that_defined_property = step_index;
441 let animation_value = AnimationValue::from_computed_values(
442 property_declaration,
443 &step_style,
444 )
445 .unwrap();
446 return AnimationValueOrReference::AnimationValue(animation_value);
447 }
448
449 if step_index == 0 || remaining_steps.as_slice().is_empty() {
455 return AnimationValueOrReference::AnimationValue(
456 animation_values_from_style[property_index].clone(),
457 );
458 }
459
460 let preceding_declaration =
467 keyframe_offset_cache.last_keyframe_that_defined_property;
468 let following_declaration = keyframe_offset_cache
469 .next_keyframe_that_defines_property
470 .filter(|offset| *offset > step_index)
471 .unwrap_or_else(|| {
472 let relative_offset = remaining_steps
473 .as_slice()
474 .iter()
475 .position(|step| {
476 step.declarations.contains(property_declaration)
477 })
478 .unwrap_or(remaining_steps.as_slice().len() - 1);
479 let absolute_offset = step_index + 1 + relative_offset;
480
481 keyframe_offset_cache.next_keyframe_that_defines_property =
482 Some(absolute_offset);
483 absolute_offset
484 });
485
486 AnimationValueOrReference::NotDefinedHere(PropertyDeclarationOffsets {
487 preceding_declaration,
488 following_declaration,
489 })
490 })
491 .collect()
492 };
493 debug_assert_eq!(values.len(), number_of_animating_properties);
494
495 computed_steps.push(ComputedKeyframe {
496 timing_function,
497 start_percentage,
498 values,
499 });
500
501 step_index += 1;
502 }
503
504 debug_assert!(computed_steps.first().is_none_or(|first_step| {
507 first_step
508 .values
509 .iter()
510 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
511 }));
512 debug_assert!(computed_steps.last().is_none_or(|first_step| {
513 first_step
514 .values
515 .iter()
516 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
517 }));
518
519 computed_steps.into_boxed_slice()
520 }
521}
522
523#[derive(Clone, MallocSizeOf)]
525pub struct Animation {
526 pub name: Atom,
528
529 properties_changed: PropertyDeclarationIdSet,
531
532 computed_steps: Box<[ComputedKeyframe]>,
534
535 pub started_at: f64,
538
539 pub duration: f64,
541
542 pub delay: f64,
544
545 pub fill_mode: AnimationFillMode,
547
548 pub iteration_state: KeyframesIterationState,
550
551 pub state: AnimationState,
553
554 pub direction: AnimationDirection,
556
557 pub current_direction: AnimationDirection,
559
560 pub number_of_animating_properties: usize,
562
563 pub is_new: bool,
566}
567
568impl Animation {
569 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
571 let new_ui = new_style.get_ui();
572 let index = new_ui
573 .animation_name_iter()
574 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
575 let index = match index {
576 Some(index) => index,
577 None => return true,
578 };
579
580 new_ui.animation_duration_mod(index).seconds() == 0.
581 }
582
583 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
587 if !self.iteration_over(time) {
588 return false;
589 }
590
591 if self.state != AnimationState::Running {
593 return false;
594 }
595
596 if self.on_last_iteration() {
597 return false;
598 }
599
600 self.iterate();
601 true
602 }
603
604 fn iterate(&mut self) {
605 debug_assert!(!self.on_last_iteration());
606
607 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
608 *current = (*current + 1.).min(max);
609 }
610
611 if let AnimationState::Paused(ref mut progress) = self.state {
612 debug_assert!(*progress > 1.);
613 *progress -= 1.;
614 }
615
616 self.started_at += self.duration;
618 match self.direction {
619 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
620 self.current_direction = match self.current_direction {
621 AnimationDirection::Normal => AnimationDirection::Reverse,
622 AnimationDirection::Reverse => AnimationDirection::Normal,
623 _ => unreachable!(),
624 };
625 },
626 _ => {},
627 }
628 }
629
630 pub fn current_iteration_end_progress(&self) -> f64 {
635 match self.iteration_state {
636 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
637 KeyframesIterationState::Infinite(_) => 1.,
638 }
639 }
640
641 pub fn current_iteration_duration(&self) -> f64 {
644 self.current_iteration_end_progress() * self.duration
645 }
646
647 fn iteration_over(&self, time: f64) -> bool {
650 time > (self.started_at + self.current_iteration_duration())
651 }
652
653 fn on_last_iteration(&self) -> bool {
655 match self.iteration_state {
656 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
657 KeyframesIterationState::Infinite(_) => false,
658 }
659 }
660
661 pub fn has_ended(&self, time: f64) -> bool {
665 if !self.on_last_iteration() {
666 return false;
667 }
668
669 let progress = match self.state {
670 AnimationState::Finished => return true,
671 AnimationState::Paused(progress) => progress,
672 AnimationState::Running => (time - self.started_at) / self.duration,
673 AnimationState::Pending | AnimationState::Canceled => return false,
674 };
675
676 progress >= self.current_iteration_end_progress()
677 }
678
679 pub fn update_from_other(&mut self, other: &Self, now: f64) {
687 use self::AnimationState::*;
688
689 debug!(
690 "KeyframesAnimationState::update_from_other({:?}, {:?})",
691 self, other
692 );
693
694 let old_started_at = self.started_at;
697 let old_duration = self.duration;
698 let old_direction = self.current_direction;
699 let old_state = self.state.clone();
700 let old_iteration_state = self.iteration_state.clone();
701
702 *self = other.clone();
703
704 self.started_at = old_started_at;
705 self.current_direction = old_direction;
706
707 match (&mut self.iteration_state, old_iteration_state) {
711 (
712 &mut KeyframesIterationState::Finite(ref mut iters, _),
713 KeyframesIterationState::Finite(old_iters, _),
714 ) => *iters = old_iters,
715 _ => {},
716 }
717
718 let new_state = std::mem::replace(&mut self.state, Running);
721 if old_state == Finished && self.has_ended(now) {
722 self.state = Finished;
723 } else {
724 self.state = new_state;
725 }
726
727 match (&mut self.state, &old_state) {
734 (&mut Pending, &Paused(progress)) => {
735 self.started_at = now - (self.duration * progress);
736 },
737 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
738 (&mut Paused(ref mut progress), &Running) => {
739 *progress = (now - old_started_at) / old_duration
740 },
741 _ => {},
742 }
743
744 if self.state == Pending && self.started_at <= now && old_state != Pending {
747 self.state = Running;
748 }
749 }
750
751 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
754 if self.computed_steps.is_empty() {
755 return;
757 }
758
759 let total_progress = match self.state {
760 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
761 (now - self.started_at) / self.duration
762 },
763 AnimationState::Paused(progress) => progress,
764 AnimationState::Canceled => return,
765 };
766
767 if total_progress < 0.
768 && self.fill_mode != AnimationFillMode::Backwards
769 && self.fill_mode != AnimationFillMode::Both
770 {
771 return;
772 }
773 if self.has_ended(now)
774 && self.fill_mode != AnimationFillMode::Forwards
775 && self.fill_mode != AnimationFillMode::Both
776 {
777 return;
778 }
779 let total_progress = total_progress
780 .min(self.current_iteration_end_progress())
781 .max(0.0);
782
783 let next_keyframe_index;
785 let prev_keyframe_index;
786 let num_steps = self.computed_steps.len();
787 match self.current_direction {
788 AnimationDirection::Normal => {
789 next_keyframe_index = self
790 .computed_steps
791 .iter()
792 .position(|step| total_progress as f32 <= step.start_percentage);
793 prev_keyframe_index = next_keyframe_index
794 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
795 .unwrap_or(0);
796 },
797 AnimationDirection::Reverse => {
798 next_keyframe_index = self
799 .computed_steps
800 .iter()
801 .rev()
802 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
803 .map(|pos| num_steps - pos - 1);
804 prev_keyframe_index = next_keyframe_index
805 .and_then(|pos| {
806 if pos != num_steps - 1 {
807 Some(pos + 1)
808 } else {
809 None
810 }
811 })
812 .unwrap_or(num_steps - 1)
813 },
814 _ => unreachable!(),
815 }
816
817 debug!(
818 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
819 prev_keyframe_index, next_keyframe_index
820 );
821
822 let Some(next_keyframe_index) = next_keyframe_index else {
823 return;
824 };
825
826 let mut add_declarations_to_map = |keyframe_index: usize| {
829 for value_or_reference in &self.computed_steps[keyframe_index].values {
830 let AnimationValueOrReference::AnimationValue(value) = value_or_reference else {
831 unreachable!("First or last keyframes define all properties");
832 };
833
834 map.insert(value.id().to_owned(), value.clone());
835 }
836 };
837
838 let reversed = self.current_direction != AnimationDirection::Normal;
839 if total_progress <= 0.0 {
840 if reversed {
841 add_declarations_to_map(self.computed_steps.len() - 1);
842 } else {
843 add_declarations_to_map(0);
844 }
845 return;
846 }
847 if total_progress >= 1.0 {
848 if reversed {
849 add_declarations_to_map(0);
850 } else {
851 add_declarations_to_map(self.computed_steps.len() - 1);
852 }
853 return;
854 }
855
856 for property_index in 0..self.number_of_animating_properties {
858 let Some(previous_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
859 property_index,
860 prev_keyframe_index,
861 Direction::Backward.relative_to_animation_direction(reversed),
862 ) else {
863 continue;
865 };
866
867 let Some(next_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
868 property_index,
869 next_keyframe_index,
870 Direction::Forward.relative_to_animation_direction(reversed),
871 ) else {
872 map.insert(
874 previous_keyframe.value.id().to_owned(),
875 previous_keyframe.value.clone(),
876 );
877 continue;
878 };
879
880 let percentage_between_keyframes =
881 (next_keyframe.start_percentage - previous_keyframe.start_percentage).abs() as f64;
882 let duration_between_keyframes = percentage_between_keyframes * self.duration;
883 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
884 AnimationDirection::Normal => previous_keyframe.start_percentage as f64,
885 AnimationDirection::Reverse => 1. - previous_keyframe.start_percentage as f64,
886 _ => unreachable!(),
887 };
888 let progress_between_keyframes = (total_progress
889 - direction_aware_prev_keyframe_start_percentage)
890 / percentage_between_keyframes;
891 let animation = PropertyAnimation {
892 from: previous_keyframe.value.clone(),
893 to: next_keyframe.value.clone(),
894 timing_function: previous_keyframe.timing_function.clone(),
895 duration: duration_between_keyframes as f64,
896 };
897
898 let value = animation.calculate_value(progress_between_keyframes);
899 map.insert(value.id().to_owned(), value);
900 }
901 }
902}
903
904impl fmt::Debug for Animation {
905 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
906 f.debug_struct("Animation")
907 .field("name", &self.name)
908 .field("started_at", &self.started_at)
909 .field("duration", &self.duration)
910 .field("delay", &self.delay)
911 .field("iteration_state", &self.iteration_state)
912 .field("state", &self.state)
913 .field("direction", &self.direction)
914 .field("current_direction", &self.current_direction)
915 .field("cascade_style", &())
916 .finish()
917 }
918}
919
920#[derive(Clone, Debug, MallocSizeOf)]
922pub struct Transition {
923 pub start_time: f64,
926
927 pub delay: f64,
929
930 pub property_animation: PropertyAnimation,
932
933 pub state: AnimationState,
935
936 pub is_new: bool,
939
940 pub reversing_adjusted_start_value: AnimationValue,
943
944 pub reversing_shortening_factor: f64,
947}
948
949impl Transition {
950 fn new(
951 start_time: f64,
952 delay: f64,
953 duration: f64,
954 from: AnimationValue,
955 to: AnimationValue,
956 timing_function: &TimingFunction,
957 ) -> Self {
958 let property_animation = PropertyAnimation {
959 from: from.clone(),
960 to,
961 timing_function: timing_function.clone(),
962 duration,
963 };
964 Self {
965 start_time,
966 delay,
967 property_animation,
968 state: AnimationState::Pending,
969 is_new: true,
970 reversing_adjusted_start_value: from,
971 reversing_shortening_factor: 1.0,
972 }
973 }
974
975 fn update_for_possibly_reversed_transition(
976 &mut self,
977 replaced_transition: &Transition,
978 delay: f64,
979 now: f64,
980 ) {
981 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
990 return;
991 }
992
993 let replaced_animation = &replaced_transition.property_animation;
995 self.reversing_adjusted_start_value = replaced_animation.to.clone();
996
997 let transition_progress = ((now - replaced_transition.start_time)
1004 / (replaced_transition.property_animation.duration))
1005 .min(1.0)
1006 .max(0.0);
1007 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
1008 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
1009 self.reversing_shortening_factor = ((timing_function_output
1010 * old_reversing_shortening_factor)
1011 + (1.0 - old_reversing_shortening_factor))
1012 .abs()
1013 .min(1.0)
1014 .max(0.0);
1015
1016 self.start_time = if delay >= 0. {
1022 now + delay
1023 } else {
1024 now + (self.reversing_shortening_factor * delay)
1025 };
1026
1027 self.property_animation.duration *= self.reversing_shortening_factor;
1030
1031 let procedure = Procedure::Interpolate {
1034 progress: timing_function_output,
1035 };
1036 match replaced_animation
1037 .from
1038 .animate(&replaced_animation.to, procedure)
1039 {
1040 Ok(new_start) => self.property_animation.from = new_start,
1041 Err(..) => {},
1042 }
1043 }
1044
1045 pub fn has_ended(&self, time: f64) -> bool {
1049 time >= self.start_time + (self.property_animation.duration)
1050 }
1051
1052 pub fn calculate_value(&self, time: f64) -> AnimationValue {
1054 let progress = (time - self.start_time) / (self.property_animation.duration);
1055 self.property_animation
1056 .calculate_value(progress.clamp(0.0, 1.0))
1057 }
1058}
1059
1060#[derive(Debug, Default, MallocSizeOf)]
1062pub struct ElementAnimationSet {
1063 pub animations: Vec<Animation>,
1065
1066 pub transitions: Vec<Transition>,
1068
1069 pub dirty: bool,
1072}
1073
1074impl ElementAnimationSet {
1075 pub fn cancel_all_animations(&mut self) {
1078 self.dirty = !self.animations.is_empty();
1079 for animation in self.animations.iter_mut() {
1080 animation.state = AnimationState::Canceled;
1081 }
1082 self.cancel_active_transitions();
1083 }
1084
1085 fn cancel_active_transitions(&mut self) {
1086 for transition in self.transitions.iter_mut() {
1087 if transition.state != AnimationState::Finished {
1088 self.dirty = true;
1089 transition.state = AnimationState::Canceled;
1090 }
1091 }
1092 }
1093
1094 pub fn apply_active_animations(
1096 &self,
1097 context: &SharedStyleContext,
1098 style: &mut Arc<ComputedValues>,
1099 ) {
1100 let now = context.current_time_for_animations;
1101 let mutable_style = Arc::make_mut(style);
1102 if let Some(map) = self.get_value_map_for_active_animations(now) {
1103 for value in map.values() {
1104 value.set_in_style_for_servo(mutable_style, context);
1105 }
1106 }
1107
1108 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
1109 for value in map.values() {
1110 value.set_in_style_for_servo(mutable_style, context);
1111 }
1112 }
1113 }
1114
1115 pub fn clear_canceled_animations(&mut self) {
1117 self.animations
1118 .retain(|animation| animation.state != AnimationState::Canceled);
1119 self.transitions
1120 .retain(|animation| animation.state != AnimationState::Canceled);
1121 }
1122
1123 pub fn is_empty(&self) -> bool {
1126 self.animations.is_empty() && self.transitions.is_empty()
1127 }
1128
1129 pub fn needs_animation_ticks(&self) -> bool {
1132 self.animations
1133 .iter()
1134 .any(|animation| animation.state.needs_to_be_ticked())
1135 || self
1136 .transitions
1137 .iter()
1138 .any(|transition| transition.state.needs_to_be_ticked())
1139 }
1140
1141 pub fn running_animation_and_transition_count(&self) -> usize {
1143 self.animations
1144 .iter()
1145 .filter(|animation| animation.state.needs_to_be_ticked())
1146 .count()
1147 + self
1148 .transitions
1149 .iter()
1150 .filter(|transition| transition.state.needs_to_be_ticked())
1151 .count()
1152 }
1153
1154 pub fn has_active_animation(&self) -> bool {
1156 self.animations
1157 .iter()
1158 .any(|animation| animation.state != AnimationState::Canceled)
1159 }
1160
1161 pub fn has_active_transition(&self) -> bool {
1163 self.transitions
1164 .iter()
1165 .any(|transition| transition.state != AnimationState::Canceled)
1166 }
1167
1168 pub fn update_animations_for_new_style<E>(
1171 &mut self,
1172 element: E,
1173 context: &SharedStyleContext,
1174 new_style: &Arc<ComputedValues>,
1175 resolver: &mut StyleResolverForElement<E>,
1176 ) where
1177 E: TElement,
1178 {
1179 for animation in self.animations.iter_mut() {
1180 if animation.is_cancelled_in_new_style(new_style) {
1181 animation.state = AnimationState::Canceled;
1182 }
1183 }
1184
1185 maybe_start_animations(element, &context, &new_style, self, resolver);
1186 }
1187
1188 pub fn update_transitions_for_new_style(
1191 &mut self,
1192 might_need_transitions_update: bool,
1193 context: &SharedStyleContext,
1194 old_style: Option<&Arc<ComputedValues>>,
1195 after_change_style: &Arc<ComputedValues>,
1196 ) {
1197 let mut before_change_style = match old_style {
1200 Some(old_style) => Arc::clone(old_style),
1201 None => return,
1202 };
1203
1204 if after_change_style.get_box().clone_display().is_none() {
1206 self.cancel_active_transitions();
1207 return;
1208 }
1209
1210 if !might_need_transitions_update {
1211 return;
1212 }
1213
1214 if self.has_active_transition() || self.has_active_animation() {
1216 self.apply_active_animations(context, &mut before_change_style);
1217 }
1218
1219 let transitioning_properties = start_transitions_if_applicable(
1220 context,
1221 &before_change_style,
1222 after_change_style,
1223 self,
1224 );
1225
1226 for transition in self.transitions.iter_mut() {
1239 if transition.state == AnimationState::Finished
1240 || transition.state == AnimationState::Canceled
1241 {
1242 continue;
1243 }
1244 if transitioning_properties.contains(transition.property_animation.property_id()) {
1245 continue;
1246 }
1247 transition.state = AnimationState::Canceled;
1248 self.dirty = true;
1249 }
1250 }
1251
1252 fn start_transition_if_applicable(
1253 &mut self,
1254 context: &SharedStyleContext,
1255 property_declaration_id: &PropertyDeclarationId,
1256 index: usize,
1257 old_style: &ComputedValues,
1258 new_style: &Arc<ComputedValues>,
1259 ) {
1260 let style = new_style.get_ui();
1261 let allow_discrete =
1262 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1263
1264 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1266 else {
1267 return;
1268 };
1269 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1270 else {
1271 return;
1272 };
1273
1274 let timing_function = style.transition_timing_function_mod(index);
1275 let duration = style.transition_duration_mod(index).seconds() as f64;
1276 let delay = style.transition_delay_mod(index).seconds() as f64;
1277 let now = context.current_time_for_animations;
1278 let transitionable = property_declaration_id.is_animatable()
1279 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1280 && (allow_discrete || from.interpolable_with(&to));
1281
1282 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1283 transition.property_animation.property_id() == *property_declaration_id
1284 });
1285
1286 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1301 transition.state != AnimationState::Finished
1302 && transition.state != AnimationState::Canceled
1303 });
1304 let no_completed_transition_or_end_values_differ =
1305 existing_transition.as_ref().is_none_or(|transition| {
1306 transition.state != AnimationState::Finished
1307 || transition.property_animation.to != to
1308 });
1309 if !has_running_transition
1310 && from != to
1311 && transitionable
1312 && no_completed_transition_or_end_values_differ
1313 && (duration + delay > 0.0)
1314 {
1315 self.transitions.push(Transition::new(
1326 now + delay, delay,
1328 duration,
1329 from,
1330 to,
1331 &timing_function,
1332 ));
1333 self.dirty = true;
1334 return;
1335 }
1336
1337 let Some(existing_transition) = existing_transition.as_mut() else {
1360 return;
1361 };
1362
1363 if has_running_transition && existing_transition.property_animation.to != to {
1368 let current_value = existing_transition.calculate_value(now);
1373 let transitionable_from_current_value =
1374 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1375 if current_value == to || !transitionable_from_current_value {
1376 existing_transition.state = AnimationState::Canceled;
1377 self.dirty = true;
1378 return;
1379 }
1380
1381 if duration + delay <= 0.0 {
1387 existing_transition.state = AnimationState::Canceled;
1388 self.dirty = true;
1389 return;
1390 }
1391
1392 if existing_transition.reversing_adjusted_start_value == to {
1398 existing_transition.state = AnimationState::Canceled;
1399
1400 let mut transition = Transition::new(
1401 now + delay, delay,
1403 duration,
1404 from,
1405 to,
1406 &timing_function,
1407 );
1408
1409 transition.update_for_possibly_reversed_transition(
1412 &existing_transition,
1413 delay,
1414 now,
1415 );
1416
1417 self.transitions.push(transition);
1418 self.dirty = true;
1419 return;
1420 }
1421
1422 existing_transition.state = AnimationState::Canceled;
1431 self.transitions.push(Transition::new(
1432 now + delay, delay,
1434 duration,
1435 current_value,
1436 to,
1437 &timing_function,
1438 ));
1439 self.dirty = true;
1440 }
1441 }
1442
1443 fn get_value_map_for_transitions(
1447 &self,
1448 now: f64,
1449 ignore_transitions: IgnoreTransitions,
1450 ) -> Option<AnimationValueMap> {
1451 if !self.has_active_transition() {
1452 return None;
1453 }
1454
1455 let mut map =
1456 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1457 for transition in &self.transitions {
1458 match ignore_transitions {
1459 IgnoreTransitions::Canceled => {
1460 if transition.state == AnimationState::Canceled {
1461 continue;
1462 }
1463 },
1464 IgnoreTransitions::CanceledAndFinished => {
1465 if transition.state == AnimationState::Canceled
1466 || transition.state == AnimationState::Finished
1467 {
1468 continue;
1469 }
1470 },
1471 }
1472
1473 let value = transition.calculate_value(now);
1474 map.insert(value.id().to_owned(), value);
1475 }
1476
1477 Some(map)
1478 }
1479
1480 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1483 if !self.has_active_animation() {
1484 return None;
1485 }
1486
1487 let mut map = Default::default();
1488 for animation in &self.animations {
1489 animation.get_property_declaration_at_time(now, &mut map);
1490 }
1491
1492 Some(map)
1493 }
1494}
1495
1496#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1497pub struct AnimationSetKey {
1499 pub node: OpaqueNode,
1501 pub pseudo_element: Option<PseudoElement>,
1504}
1505
1506impl AnimationSetKey {
1507 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1509 AnimationSetKey {
1510 node,
1511 pseudo_element,
1512 }
1513 }
1514
1515 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1517 AnimationSetKey {
1518 node,
1519 pseudo_element: None,
1520 }
1521 }
1522
1523 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1525 AnimationSetKey {
1526 node,
1527 pseudo_element: Some(pseudo_element),
1528 }
1529 }
1530}
1531
1532#[derive(Clone, Debug, Default, MallocSizeOf)]
1533pub struct DocumentAnimationSet {
1535 #[ignore_malloc_size_of = "Arc is hard"]
1537 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1538}
1539
1540impl DocumentAnimationSet {
1541 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1543 self.sets
1544 .read()
1545 .get(key)
1546 .map_or(false, |set| set.has_active_animation())
1547 }
1548
1549 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1551 self.sets
1552 .read()
1553 .get(key)
1554 .map_or(false, |set| set.has_active_transition())
1555 }
1556
1557 pub fn get_animation_declarations(
1560 &self,
1561 key: &AnimationSetKey,
1562 time: f64,
1563 shared_lock: &SharedRwLock,
1564 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1565 self.sets
1566 .read()
1567 .get(key)
1568 .and_then(|set| set.get_value_map_for_active_animations(time))
1569 .map(|map| {
1570 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1571 Arc::new(shared_lock.wrap(block))
1572 })
1573 }
1574
1575 pub fn get_transition_declarations(
1578 &self,
1579 key: &AnimationSetKey,
1580 time: f64,
1581 shared_lock: &SharedRwLock,
1582 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1583 self.sets
1584 .read()
1585 .get(key)
1586 .and_then(|set| {
1587 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1588 })
1589 .map(|map| {
1590 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1591 Arc::new(shared_lock.wrap(block))
1592 })
1593 }
1594
1595 pub fn get_all_declarations(
1598 &self,
1599 key: &AnimationSetKey,
1600 time: f64,
1601 shared_lock: &SharedRwLock,
1602 ) -> AnimationDeclarations {
1603 let sets = self.sets.read();
1604 let set = match sets.get(key) {
1605 Some(set) => set,
1606 None => return Default::default(),
1607 };
1608
1609 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1610 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1611 Arc::new(shared_lock.wrap(block))
1612 });
1613 let transitions = set
1614 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1615 .map(|map| {
1616 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1617 Arc::new(shared_lock.wrap(block))
1618 });
1619 AnimationDeclarations {
1620 animations,
1621 transitions,
1622 }
1623 }
1624
1625 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1627 if let Some(set) = self.sets.write().get_mut(key) {
1628 set.cancel_all_animations();
1629 }
1630 }
1631}
1632
1633pub fn start_transitions_if_applicable(
1636 context: &SharedStyleContext,
1637 old_style: &ComputedValues,
1638 new_style: &Arc<ComputedValues>,
1639 animation_state: &mut ElementAnimationSet,
1640) -> PropertyDeclarationIdSet {
1641 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1656 transition_properties.reverse();
1657
1658 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1659 for transition in transition_properties {
1660 let physical_property = transition
1661 .property
1662 .as_borrowed()
1663 .to_physical(new_style.writing_mode);
1664 if properties_that_transition.contains(physical_property) {
1665 continue;
1666 }
1667
1668 properties_that_transition.insert(physical_property);
1669 animation_state.start_transition_if_applicable(
1670 context,
1671 &physical_property,
1672 transition.index,
1673 old_style,
1674 new_style,
1675 );
1676 }
1677
1678 properties_that_transition
1679}
1680
1681pub fn maybe_start_animations<E>(
1684 element: E,
1685 context: &SharedStyleContext,
1686 new_style: &Arc<ComputedValues>,
1687 animation_state: &mut ElementAnimationSet,
1688 resolver: &mut StyleResolverForElement<E>,
1689) where
1690 E: TElement,
1691{
1692 let style = new_style.get_ui();
1693 for (i, name) in style.animation_name_iter().enumerate() {
1694 let name = match name.as_atom() {
1695 Some(atom) => atom,
1696 None => continue,
1697 };
1698
1699 debug!("maybe_start_animations: name={}", name);
1700 let duration = style.animation_duration_mod(i).seconds() as f64;
1701 if duration == 0. {
1702 continue;
1703 }
1704
1705 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1706 continue;
1707 };
1708
1709 debug!("maybe_start_animations: animation {} found", name);
1710
1711 let delay = style.animation_delay_mod(i).seconds();
1715
1716 let iteration_count = style.animation_iteration_count_mod(i);
1717 let iteration_state = if iteration_count.0.is_infinite() {
1718 KeyframesIterationState::Infinite(0.0)
1719 } else {
1720 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1721 };
1722
1723 let animation_direction = style.animation_direction_mod(i);
1724
1725 let initial_direction = match animation_direction {
1726 AnimationDirection::Normal | AnimationDirection::Alternate => {
1727 AnimationDirection::Normal
1728 },
1729 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1730 AnimationDirection::Reverse
1731 },
1732 };
1733
1734 let now = context.current_time_for_animations;
1735 let started_at = now + delay as f64;
1736 let mut starting_progress = (now - started_at) / duration;
1737 let state = match style.animation_play_state_mod(i) {
1738 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1739 AnimationPlayState::Running => AnimationState::Pending,
1740 };
1741
1742 let mut animating_properties = PropertyDeclarationIdSet::default();
1746 let mut number_of_animating_properties = 0;
1747 for property in keyframe_animation.properties_changed.iter() {
1748 debug_assert!(property.is_animatable());
1749
1750 if animating_properties.insert(property.to_physical(new_style.writing_mode)) {
1751 number_of_animating_properties += 1;
1752 }
1753 }
1754
1755 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1756 element,
1757 &keyframe_animation,
1758 context,
1759 new_style,
1760 style.animation_timing_function_mod(i),
1761 resolver,
1762 animating_properties,
1763 number_of_animating_properties,
1764 );
1765
1766 let mut new_animation = Animation {
1767 name: name.clone(),
1768 properties_changed: keyframe_animation.properties_changed.clone(),
1769 computed_steps,
1770 started_at,
1771 duration,
1772 fill_mode: style.animation_fill_mode_mod(i),
1773 delay: delay as f64,
1774 iteration_state,
1775 state,
1776 direction: animation_direction,
1777 current_direction: initial_direction,
1778 number_of_animating_properties,
1779 is_new: true,
1780 };
1781
1782 while starting_progress > 1. && !new_animation.on_last_iteration() {
1785 new_animation.iterate();
1786 starting_progress -= 1.;
1787 }
1788
1789 animation_state.dirty = true;
1790
1791 for existing_animation in animation_state.animations.iter_mut() {
1793 if existing_animation.state == AnimationState::Canceled {
1794 continue;
1795 }
1796
1797 if new_animation.name == existing_animation.name {
1798 existing_animation
1799 .update_from_other(&new_animation, context.current_time_for_animations);
1800 return;
1801 }
1802 }
1803
1804 animation_state.animations.push(new_animation);
1805 }
1806}