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 debug_unreachable::debug_unreachable;
34use parking_lot::RwLock;
35use rustc_hash::FxHashMap;
36use servo_arc::Arc;
37use std::fmt;
38
39#[derive(Clone, Debug, MallocSizeOf)]
41pub struct PropertyAnimation {
42 from: AnimationValue,
44
45 to: AnimationValue,
47
48 timing_function: TimingFunction,
50
51 pub duration: f64,
53}
54
55impl PropertyAnimation {
56 pub fn property_id(&self) -> PropertyDeclarationId<'_> {
58 debug_assert_eq!(self.from.id(), self.to.id());
59 self.from.id()
60 }
61
62 fn timing_function_output(&self, progress: f64) -> f64 {
64 let epsilon = 1. / (200. * self.duration);
65 self.timing_function
71 .calculate_output(progress, BeforeFlag::Unset, epsilon)
72 }
73
74 fn calculate_value(&self, progress: f64) -> AnimationValue {
76 let progress = self.timing_function_output(progress);
77 let procedure = Procedure::Interpolate { progress };
78 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
79 if progress < 0.5 {
81 self.from.clone()
82 } else {
83 self.to.clone()
84 }
85 })
86 }
87}
88
89#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
91pub enum AnimationState {
92 Pending,
95 Running,
97 Paused(f64),
100 Finished,
102 Canceled,
104}
105
106impl AnimationState {
107 fn needs_to_be_ticked(&self) -> bool {
109 *self == AnimationState::Running || *self == AnimationState::Pending
110 }
111}
112
113enum IgnoreTransitions {
114 Canceled,
115 CanceledAndFinished,
116}
117
118#[derive(Clone, Debug, MallocSizeOf)]
123pub enum KeyframesIterationState {
124 Infinite(f64),
126 Finite(f64, f64),
128}
129
130#[derive(Debug)]
135struct IntermediateComputedKeyframe {
136 declarations: PropertyDeclarationBlock,
137 timing_function: Option<TimingFunction>,
138 start_percentage: f64,
139}
140
141impl IntermediateComputedKeyframe {
142 fn new(start_percentage: f64) -> Self {
143 IntermediateComputedKeyframe {
144 declarations: PropertyDeclarationBlock::new(),
145 timing_function: None,
146 start_percentage,
147 }
148 }
149
150 fn generate_for_keyframes(
153 animation: &KeyframesAnimation,
154 context: &SharedStyleContext,
155 base_style: &ComputedValues,
156 ) -> Vec<Self> {
157 if animation.steps.is_empty() {
158 return vec![];
159 }
160
161 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
162 let mut current_step = IntermediateComputedKeyframe::new(0.);
163 for step in animation.steps.iter() {
164 let start_percentage = step.start_offset.percentage.0 as f64;
165 if start_percentage != current_step.start_percentage {
166 let new_step = IntermediateComputedKeyframe::new(start_percentage);
167 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
168 }
169
170 current_step.update_from_step(step, context, base_style);
171 }
172 intermediate_steps.push(current_step);
173
174 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
177 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
178
179 intermediate_steps
180 }
181
182 fn update_from_step(
183 &mut self,
184 step: &KeyframesStep,
185 context: &SharedStyleContext,
186 base_style: &ComputedValues,
187 ) {
188 let guard = &context.guards.author;
191 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
192 self.timing_function = Some(timing_function.to_computed_value_without_context());
193 }
194
195 let block = match step.value {
196 KeyframesStepValue::ComputedValues => return,
197 KeyframesStepValue::Declarations { ref block } => block,
198 };
199
200 let guard = block.read_with(&guard);
203 for declaration in guard.normal_declaration_iter() {
204 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
205 if id == LonghandId::Display {
206 continue;
207 }
208
209 if !id.is_animatable() {
210 continue;
211 }
212 }
213
214 self.declarations.push(
215 declaration.to_physical(base_style.writing_mode),
216 Importance::Normal,
217 );
218 }
219 }
220
221 fn resolve_style<E>(
222 self,
223 element: E,
224 context: &SharedStyleContext,
225 base_style: &Arc<ComputedValues>,
226 resolver: &mut StyleResolverForElement<E>,
227 ) -> Arc<ComputedValues>
228 where
229 E: TElement,
230 {
231 if !self.declarations.any_normal() {
232 return base_style.clone();
233 }
234
235 let document = element.as_node().owner_doc();
236 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
237 let mut important_rules_changed = false;
238 let rule_node = base_style.rules().clone();
239 let new_node = context.stylist.rule_tree().update_rule_at_level(
240 CascadeLevel::new(CascadeOrigin::Animations),
241 LayerOrder::root(),
242 Some(locked_block.borrow_arc()),
243 &rule_node,
244 &context.guards,
245 &mut important_rules_changed,
246 );
247
248 if new_node.is_none() {
249 return base_style.clone();
250 }
251
252 let inputs = CascadeInputs {
253 rules: new_node,
254 visited_rules: base_style.visited_rules().cloned(),
255 flags: base_style.flags.for_cascade_inputs(),
256 included_cascade_flags: RuleCascadeFlags::empty(),
257 };
258 resolver
259 .cascade_style_and_visited_with_default_parents(inputs)
260 .0
261 }
262}
263
264#[derive(Clone, Debug, MallocSizeOf)]
265struct PropertyDeclarationOffsets {
266 preceding_declaration: usize,
269 following_declaration: usize,
272}
273
274#[derive(Clone, Debug, MallocSizeOf)]
275enum AnimationValueOrReference {
276 AnimationValue(AnimationValue),
278 NotDefinedHere(PropertyDeclarationOffsets),
280}
281
282#[derive(Clone, Debug, MallocSizeOf)]
284struct ComputedKeyframe {
285 timing_function: TimingFunction,
288
289 start_percentage: f64,
292
293 values: Box<[AnimationValueOrReference]>,
296}
297
298#[derive(Clone, Copy, Debug, Default)]
304struct KeyframeOffsetCacheForProperty {
305 last_keyframe_that_defined_property: usize,
311
312 next_keyframe_that_defines_property: Option<usize>,
318}
319
320struct KeyframeDataForProperty<'a> {
321 timing_function: &'a TimingFunction,
324
325 start_percentage: f64,
328
329 value: &'a AnimationValue,
330}
331
332#[derive(Clone, Copy, Debug)]
333enum Direction {
334 Forward,
335 Backward,
336}
337
338impl Direction {
339 fn relative_to_animation_direction(&self, reverse: bool) -> Self {
340 match self {
341 Self::Forward if reverse => Self::Backward,
342 Self::Backward if reverse => Self::Forward,
343 _ => *self,
344 }
345 }
346}
347
348impl Animation {
349 fn next_relevant_keyframe_for_property_in_direction(
354 &self,
355 property_index: usize,
356 keyframe_index: usize,
357 direction: Direction,
358 ) -> Option<KeyframeDataForProperty<'_>> {
359 let relevant_keyframe = &self.computed_steps[keyframe_index];
360 let parameters = match &relevant_keyframe.values[property_index] {
361 AnimationValueOrReference::AnimationValue(animation_value) => KeyframeDataForProperty {
362 timing_function: &relevant_keyframe.timing_function,
363 start_percentage: relevant_keyframe.start_percentage,
364 value: animation_value,
365 },
366 AnimationValueOrReference::NotDefinedHere(offsets) => {
367 let next_relevant_keyframe_index = match direction {
368 Direction::Forward => offsets.following_declaration,
369 Direction::Backward => offsets.preceding_declaration,
370 };
371 let next_relevant_keyframe = &self.computed_steps[next_relevant_keyframe_index];
372 let AnimationValueOrReference::AnimationValue(animation_value) =
373 &next_relevant_keyframe.values[property_index]
374 else {
375 panic!("Referenced keyframe does not set property");
376 };
377
378 KeyframeDataForProperty {
379 timing_function: &next_relevant_keyframe.timing_function,
380 start_percentage: next_relevant_keyframe.start_percentage,
381 value: &animation_value,
382 }
383 },
384 };
385
386 Some(parameters)
387 }
388}
389impl ComputedKeyframe {
390 fn generate_for_keyframes<E>(
391 element: E,
392 animation: &KeyframesAnimation,
393 context: &SharedStyleContext,
394 base_style: &Arc<ComputedValues>,
395 default_timing_function: TimingFunction,
396 resolver: &mut StyleResolverForElement<E>,
397 animating_properties: PropertyDeclarationIdSet,
398 number_of_animating_properties: usize,
399 ) -> Box<[Self]>
400 where
401 E: TElement,
402 {
403 let animation_values_from_style: Vec<AnimationValue> = animating_properties
404 .iter()
405 .map(|property| {
406 AnimationValue::from_computed_values(property, &**base_style)
407 .expect("Unexpected non-animatable property.")
408 })
409 .collect();
410
411 let intermediate_steps =
412 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
413
414 let mut keyframe_offset_caches: Vec<KeyframeOffsetCacheForProperty> =
418 vec![Default::default(); number_of_animating_properties];
419
420 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
421 let mut remaining_steps = intermediate_steps.into_iter();
422 let mut step_index = 0;
423 while let Some(step) = remaining_steps.next() {
424 let start_percentage = step.start_percentage;
425 let properties_changed_in_step = step.declarations.property_ids().clone();
426 let timing_function = step
427 .timing_function
428 .clone()
429 .unwrap_or_else(|| default_timing_function.clone());
430 let step_style = step.resolve_style(element, context, base_style, resolver);
431
432 let values: Box<[_]> = {
433 animating_properties
436 .iter()
437 .enumerate()
438 .map(|(property_index, property_declaration)| {
439 let keyframe_offset_cache = &mut keyframe_offset_caches[property_index];
440 if properties_changed_in_step.contains(property_declaration) {
441 keyframe_offset_cache.last_keyframe_that_defined_property = step_index;
442 let animation_value = AnimationValue::from_computed_values(
443 property_declaration,
444 &step_style,
445 )
446 .unwrap();
447 return AnimationValueOrReference::AnimationValue(animation_value);
448 }
449
450 if step_index == 0 || remaining_steps.as_slice().is_empty() {
456 return AnimationValueOrReference::AnimationValue(
457 animation_values_from_style[property_index].clone(),
458 );
459 }
460
461 let preceding_declaration =
468 keyframe_offset_cache.last_keyframe_that_defined_property;
469 let following_declaration = keyframe_offset_cache
470 .next_keyframe_that_defines_property
471 .filter(|offset| *offset > step_index)
472 .unwrap_or_else(|| {
473 let relative_offset = remaining_steps
474 .as_slice()
475 .iter()
476 .position(|step| {
477 step.declarations.contains(property_declaration)
478 })
479 .unwrap_or(remaining_steps.as_slice().len() - 1);
480 let absolute_offset = step_index + 1 + relative_offset;
481
482 keyframe_offset_cache.next_keyframe_that_defines_property =
483 Some(absolute_offset);
484 absolute_offset
485 });
486
487 AnimationValueOrReference::NotDefinedHere(PropertyDeclarationOffsets {
488 preceding_declaration,
489 following_declaration,
490 })
491 })
492 .collect()
493 };
494 debug_assert_eq!(values.len(), number_of_animating_properties);
495
496 computed_steps.push(ComputedKeyframe {
497 timing_function,
498 start_percentage,
499 values,
500 });
501
502 step_index += 1;
503 }
504
505 debug_assert!(computed_steps.first().is_none_or(|first_step| {
508 first_step
509 .values
510 .iter()
511 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
512 }));
513 debug_assert!(computed_steps.last().is_none_or(|first_step| {
514 first_step
515 .values
516 .iter()
517 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
518 }));
519
520 computed_steps.into_boxed_slice()
521 }
522}
523
524#[derive(Clone, MallocSizeOf)]
526pub struct Animation {
527 pub name: Atom,
529
530 properties_changed: PropertyDeclarationIdSet,
532
533 computed_steps: Box<[ComputedKeyframe]>,
535
536 pub started_at: f64,
539
540 pub duration: f64,
542
543 pub delay: f64,
545
546 pub fill_mode: AnimationFillMode,
548
549 pub iteration_state: KeyframesIterationState,
551
552 pub state: AnimationState,
554
555 pub direction: AnimationDirection,
557
558 pub current_direction: AnimationDirection,
560
561 pub number_of_animating_properties: usize,
563
564 pub is_new: bool,
567}
568
569impl Animation {
570 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
572 let new_ui = new_style.get_ui();
573 let index = new_ui
574 .animation_name_iter()
575 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
576 let index = match index {
577 Some(index) => index,
578 None => return true,
579 };
580
581 new_ui.animation_duration_mod(index).seconds() == 0.
582 }
583
584 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
588 if !self.iteration_over(time) {
589 return false;
590 }
591
592 if self.state != AnimationState::Running {
594 return false;
595 }
596
597 if self.on_last_iteration() {
598 return false;
599 }
600
601 self.iterate();
602 true
603 }
604
605 fn iterate(&mut self) {
606 debug_assert!(!self.on_last_iteration());
607
608 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
609 *current = (*current + 1.).min(max);
610 }
611
612 if let AnimationState::Paused(ref mut progress) = self.state {
613 debug_assert!(*progress > 1.);
614 *progress -= 1.;
615 }
616
617 self.started_at += self.duration;
619 match self.direction {
620 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
621 self.current_direction = match self.current_direction {
622 AnimationDirection::Normal => AnimationDirection::Reverse,
623 AnimationDirection::Reverse => AnimationDirection::Normal,
624 _ => unreachable!(
625 "Current animation direction can only be `normal` or `reverse`."
626 ),
627 };
628 },
629 _ => {},
630 }
631 }
632
633 pub fn current_iteration_end_progress(&self) -> f64 {
638 match self.iteration_state {
639 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
640 KeyframesIterationState::Infinite(_) => 1.,
641 }
642 }
643
644 pub fn current_iteration_duration(&self) -> f64 {
647 self.current_iteration_end_progress() * self.duration
648 }
649
650 fn iteration_over(&self, time: f64) -> bool {
653 time > (self.started_at + self.current_iteration_duration())
654 }
655
656 fn on_last_iteration(&self) -> bool {
658 match self.iteration_state {
659 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
660 KeyframesIterationState::Infinite(_) => false,
661 }
662 }
663
664 pub fn has_ended(&self, time: f64) -> bool {
668 if !self.on_last_iteration() {
669 return false;
670 }
671
672 let progress = match self.state {
673 AnimationState::Finished => return true,
674 AnimationState::Paused(progress) => progress,
675 AnimationState::Running => (time - self.started_at) / self.duration,
676 AnimationState::Pending | AnimationState::Canceled => return false,
677 };
678
679 progress >= self.current_iteration_end_progress()
680 }
681
682 pub fn update_from_other(&mut self, other: &Self, now: f64) {
690 use self::AnimationState::*;
691
692 debug!(
693 "KeyframesAnimationState::update_from_other({:?}, {:?})",
694 self, other
695 );
696
697 let old_started_at = self.started_at;
700 let old_delay = self.delay;
701 let old_duration = self.duration;
702 let old_direction = self.current_direction;
703 let old_state = self.state.clone();
704 let old_iteration_state = self.iteration_state.clone();
705
706 *self = other.clone();
707 self.current_direction = old_direction;
708
709 if self.delay != old_delay {
710 self.started_at = old_started_at + (self.delay - old_delay);
713
714 match old_state {
715 Paused(old_progress) => {
716 let mut progress = old_progress + (old_delay - self.delay) / self.duration;
717 while progress > 1. && !self.on_last_iteration() {
718 self.iterate();
719 progress -= 1.;
720 }
721 self.state = Paused(progress);
722 },
723 Finished => {
724 if self.has_ended(now) {
725 self.state = Finished;
726 } else if self.started_at <= now {
727 self.state = Running;
728 } else {
729 self.state = Pending;
730 }
731 },
732 _ => {
733 let mut starting_progress = (now - self.started_at) / self.duration;
736 match self.iteration_state {
737 KeyframesIterationState::Finite(ref mut current, _) => *current = 0.0,
738 _ => {},
739 }
740 while starting_progress > 1. && !self.on_last_iteration() {
741 self.iterate();
742 starting_progress -= 1.;
743 }
744 },
745 }
746
747 if self.state == Pending && self.started_at <= now {
749 self.state = Running;
750 }
751 } else {
752 self.started_at = old_started_at;
753
754 match (&mut self.iteration_state, old_iteration_state) {
758 (
759 &mut KeyframesIterationState::Finite(ref mut iters, _),
760 KeyframesIterationState::Finite(old_iters, _),
761 ) => *iters = old_iters,
762 _ => {},
763 }
764
765 let new_state = std::mem::replace(&mut self.state, Running);
768 if old_state == Finished && self.has_ended(now) {
769 self.state = Finished;
770 } else {
771 self.state = new_state;
772 }
773
774 match (&mut self.state, &old_state) {
781 (&mut Pending, &Paused(progress)) => {
782 self.started_at = now - (self.duration * progress);
783 },
784 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
785 (&mut Paused(ref mut progress), &Running) => {
786 *progress = (now - old_started_at) / old_duration
787 },
788 _ => {},
789 }
790
791 if self.state == Pending && self.started_at <= now && old_state != Pending {
794 self.state = Running;
795 }
796 }
797 }
798
799 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
802 if self.computed_steps.is_empty() {
803 return;
805 }
806
807 let progress = match self.state {
810 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
811 (now - self.started_at) / self.duration
812 },
813 AnimationState::Paused(progress) => progress,
814 AnimationState::Canceled => return,
815 };
816
817 if progress < 0.
818 && self.fill_mode != AnimationFillMode::Backwards
819 && self.fill_mode != AnimationFillMode::Both
820 {
821 return;
822 }
823 if self.has_ended(now)
824 && self.fill_mode != AnimationFillMode::Forwards
825 && self.fill_mode != AnimationFillMode::Both
826 {
827 return;
828 }
829
830 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
833 for value_or_reference in keyframe.values.iter() {
834 let AnimationValueOrReference::AnimationValue(value) = value_or_reference else {
835 unreachable!("First or last keyframes define all properties");
836 };
837 map.insert(value.id().to_owned(), value.clone());
838 }
839 };
840
841 if progress < 0.0 {
843 if let Some(keyframe) = match self.current_direction {
844 AnimationDirection::Normal => self.computed_steps.first(),
845 AnimationDirection::Reverse => self.computed_steps.last(),
846 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
847 } {
848 add_declarations_to_map(keyframe);
849 }
850 return;
851 }
852
853 let total_progress = progress.min(self.current_iteration_end_progress()).max(0.0);
855
856 if total_progress == 1.0 {
858 let keyframe = match self.current_direction {
859 AnimationDirection::Normal => self.computed_steps.last().unwrap(),
860 AnimationDirection::Reverse => self.computed_steps.first().unwrap(),
861 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
862 };
863 add_declarations_to_map(keyframe);
864 return;
865 }
866
867 let next_keyframe_index;
869 let prev_keyframe_index;
870 let num_steps = self.computed_steps.len();
871 match self.current_direction {
872 AnimationDirection::Normal => {
873 next_keyframe_index = self
874 .computed_steps
875 .iter()
876 .position(|step| total_progress < step.start_percentage);
877 prev_keyframe_index = next_keyframe_index
878 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
879 .unwrap_or(0);
880 },
881 AnimationDirection::Reverse => {
882 next_keyframe_index = self
883 .computed_steps
884 .iter()
885 .rev()
886 .position(|step| total_progress <= 1. - step.start_percentage)
887 .map(|pos| num_steps - pos - 1);
888 prev_keyframe_index = next_keyframe_index
889 .and_then(|pos| {
890 if pos != num_steps - 1 {
891 Some(pos + 1)
892 } else {
893 None
894 }
895 })
896 .unwrap_or(num_steps - 1)
897 },
898 _ => unreachable!(),
899 }
900
901 debug!(
902 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
903 prev_keyframe_index, next_keyframe_index
904 );
905
906 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
907 let Some(next_keyframe_index) = next_keyframe_index else {
908 unsafe {
909 debug_unreachable!(
910 "next_keyframe_index should always be Some: \
911 total_progress is in [0, 1) at this point. \
912 Normal direction: keyframe with start_percentage 1.0 always satisfies. \
913 Reverse direction: keyframe with start_percentage 0.0 always satisfies."
914 );
915 }
916 };
917
918 if prev_keyframe_index == next_keyframe_index {
921 add_declarations_to_map(&prev_keyframe);
922 return;
923 }
924
925 let reversed = self.current_direction != AnimationDirection::Normal;
927 for property_index in 0..self.number_of_animating_properties {
928 let Some(previous_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
929 property_index,
930 prev_keyframe_index,
931 Direction::Backward.relative_to_animation_direction(reversed),
932 ) else {
933 continue;
935 };
936
937 let Some(next_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
938 property_index,
939 next_keyframe_index,
940 Direction::Forward.relative_to_animation_direction(reversed),
941 ) else {
942 map.insert(
944 previous_keyframe.value.id().to_owned(),
945 previous_keyframe.value.clone(),
946 );
947 continue;
948 };
949
950 let percentage_between_keyframes =
951 (next_keyframe.start_percentage - previous_keyframe.start_percentage).abs();
952 let duration_between_keyframes = percentage_between_keyframes * self.duration;
953 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
954 AnimationDirection::Normal => previous_keyframe.start_percentage,
955 AnimationDirection::Reverse => 1. - previous_keyframe.start_percentage,
956 _ => unreachable!(),
957 };
958 let progress_between_keyframes = (total_progress
959 - direction_aware_prev_keyframe_start_percentage)
960 / percentage_between_keyframes;
961 let animation = PropertyAnimation {
962 from: previous_keyframe.value.clone(),
963 to: next_keyframe.value.clone(),
964 timing_function: previous_keyframe.timing_function.clone(),
965 duration: duration_between_keyframes,
966 };
967
968 let value = animation.calculate_value(progress_between_keyframes);
969 map.insert(value.id().to_owned(), value);
970 }
971 }
972}
973
974impl fmt::Debug for Animation {
975 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
976 f.debug_struct("Animation")
977 .field("name", &self.name)
978 .field("started_at", &self.started_at)
979 .field("duration", &self.duration)
980 .field("delay", &self.delay)
981 .field("iteration_state", &self.iteration_state)
982 .field("state", &self.state)
983 .field("direction", &self.direction)
984 .field("current_direction", &self.current_direction)
985 .field("cascade_style", &())
986 .finish()
987 }
988}
989
990#[derive(Clone, Debug, MallocSizeOf)]
992pub struct Transition {
993 pub start_time: f64,
996
997 pub delay: f64,
999
1000 pub property_animation: PropertyAnimation,
1002
1003 pub state: AnimationState,
1005
1006 pub is_new: bool,
1009
1010 pub reversing_adjusted_start_value: AnimationValue,
1013
1014 pub reversing_shortening_factor: f64,
1017}
1018
1019impl Transition {
1020 fn new(
1021 start_time: f64,
1022 delay: f64,
1023 duration: f64,
1024 from: AnimationValue,
1025 to: AnimationValue,
1026 timing_function: &TimingFunction,
1027 ) -> Self {
1028 let property_animation = PropertyAnimation {
1029 from: from.clone(),
1030 to,
1031 timing_function: timing_function.clone(),
1032 duration,
1033 };
1034 Self {
1035 start_time,
1036 delay,
1037 property_animation,
1038 state: AnimationState::Pending,
1039 is_new: true,
1040 reversing_adjusted_start_value: from,
1041 reversing_shortening_factor: 1.0,
1042 }
1043 }
1044
1045 fn update_for_possibly_reversed_transition(
1046 &mut self,
1047 replaced_transition: &Transition,
1048 delay: f64,
1049 now: f64,
1050 ) {
1051 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
1060 return;
1061 }
1062
1063 let replaced_animation = &replaced_transition.property_animation;
1065 self.reversing_adjusted_start_value = replaced_animation.to.clone();
1066
1067 let transition_progress = ((now - replaced_transition.start_time)
1074 / (replaced_transition.property_animation.duration))
1075 .min(1.0)
1076 .max(0.0);
1077 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
1078 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
1079 self.reversing_shortening_factor = ((timing_function_output
1080 * old_reversing_shortening_factor)
1081 + (1.0 - old_reversing_shortening_factor))
1082 .abs()
1083 .min(1.0)
1084 .max(0.0);
1085
1086 self.start_time = if delay >= 0. {
1092 now + delay
1093 } else {
1094 now + (self.reversing_shortening_factor * delay)
1095 };
1096
1097 self.property_animation.duration *= self.reversing_shortening_factor;
1100
1101 let procedure = Procedure::Interpolate {
1104 progress: timing_function_output,
1105 };
1106 match replaced_animation
1107 .from
1108 .animate(&replaced_animation.to, procedure)
1109 {
1110 Ok(new_start) => self.property_animation.from = new_start,
1111 Err(..) => {},
1112 }
1113 }
1114
1115 pub fn has_ended(&self, time: f64) -> bool {
1119 time >= self.start_time + (self.property_animation.duration)
1120 }
1121
1122 pub fn calculate_value(&self, time: f64) -> AnimationValue {
1124 let progress = (time - self.start_time) / (self.property_animation.duration);
1125 self.property_animation
1126 .calculate_value(progress.clamp(0.0, 1.0))
1127 }
1128}
1129
1130#[derive(Debug, Default, MallocSizeOf)]
1132pub struct ElementAnimationSet {
1133 pub animations: Vec<Animation>,
1135
1136 pub transitions: Vec<Transition>,
1138
1139 pub dirty: bool,
1142}
1143
1144impl ElementAnimationSet {
1145 pub fn cancel_all_animations(&mut self) {
1148 self.dirty = !self.animations.is_empty();
1149 for animation in self.animations.iter_mut() {
1150 animation.state = AnimationState::Canceled;
1151 }
1152 self.cancel_active_transitions();
1153 }
1154
1155 fn cancel_active_transitions(&mut self) {
1156 for transition in self.transitions.iter_mut() {
1157 if transition.state != AnimationState::Finished {
1158 self.dirty = true;
1159 transition.state = AnimationState::Canceled;
1160 }
1161 }
1162 }
1163
1164 pub fn apply_active_animations(
1166 &self,
1167 context: &SharedStyleContext,
1168 style: &mut Arc<ComputedValues>,
1169 ) {
1170 let now = context.current_time_for_animations;
1171 let mutable_style = Arc::make_mut(style);
1172 if let Some(map) = self.get_value_map_for_active_animations(now) {
1173 for value in map.values() {
1174 value.set_in_style_for_servo(mutable_style, context);
1175 }
1176 }
1177
1178 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
1179 for value in map.values() {
1180 value.set_in_style_for_servo(mutable_style, context);
1181 }
1182 }
1183 }
1184
1185 pub fn clear_canceled_animations(&mut self) {
1187 self.animations
1188 .retain(|animation| animation.state != AnimationState::Canceled);
1189 self.transitions
1190 .retain(|animation| animation.state != AnimationState::Canceled);
1191 }
1192
1193 pub fn is_empty(&self) -> bool {
1196 self.animations.is_empty() && self.transitions.is_empty()
1197 }
1198
1199 pub fn needs_animation_ticks(&self) -> bool {
1202 self.animations
1203 .iter()
1204 .any(|animation| animation.state.needs_to_be_ticked())
1205 || self
1206 .transitions
1207 .iter()
1208 .any(|transition| transition.state.needs_to_be_ticked())
1209 }
1210
1211 pub fn running_animation_and_transition_count(&self) -> usize {
1213 self.animations
1214 .iter()
1215 .filter(|animation| animation.state.needs_to_be_ticked())
1216 .count()
1217 + self
1218 .transitions
1219 .iter()
1220 .filter(|transition| transition.state.needs_to_be_ticked())
1221 .count()
1222 }
1223
1224 pub fn has_active_animation(&self) -> bool {
1226 self.animations
1227 .iter()
1228 .any(|animation| animation.state != AnimationState::Canceled)
1229 }
1230
1231 pub fn has_active_transition(&self) -> bool {
1233 self.transitions
1234 .iter()
1235 .any(|transition| transition.state != AnimationState::Canceled)
1236 }
1237
1238 pub fn update_animations_for_new_style<E>(
1241 &mut self,
1242 element: E,
1243 context: &SharedStyleContext,
1244 new_style: &Arc<ComputedValues>,
1245 resolver: &mut StyleResolverForElement<E>,
1246 ) where
1247 E: TElement,
1248 {
1249 for animation in self.animations.iter_mut() {
1250 if animation.is_cancelled_in_new_style(new_style) {
1251 animation.state = AnimationState::Canceled;
1252 }
1253 }
1254
1255 maybe_start_animations(element, &context, &new_style, self, resolver);
1256 }
1257
1258 pub fn update_transitions_for_new_style(
1261 &mut self,
1262 might_need_transitions_update: bool,
1263 context: &SharedStyleContext,
1264 old_style: Option<&Arc<ComputedValues>>,
1265 after_change_style: &Arc<ComputedValues>,
1266 ) {
1267 let mut before_change_style = match old_style {
1270 Some(old_style) => Arc::clone(old_style),
1271 None => return,
1272 };
1273
1274 if after_change_style.get_box().clone_display().is_none() {
1276 self.cancel_active_transitions();
1277 return;
1278 }
1279
1280 if !might_need_transitions_update {
1281 return;
1282 }
1283
1284 if self.has_active_transition() || self.has_active_animation() {
1286 self.apply_active_animations(context, &mut before_change_style);
1287 }
1288
1289 let transitioning_properties = start_transitions_if_applicable(
1290 context,
1291 &before_change_style,
1292 after_change_style,
1293 self,
1294 );
1295
1296 for transition in self.transitions.iter_mut() {
1309 if transition.state == AnimationState::Finished
1310 || transition.state == AnimationState::Canceled
1311 {
1312 continue;
1313 }
1314 if transitioning_properties.contains(transition.property_animation.property_id()) {
1315 continue;
1316 }
1317 transition.state = AnimationState::Canceled;
1318 self.dirty = true;
1319 }
1320 }
1321
1322 fn start_transition_if_applicable(
1323 &mut self,
1324 context: &SharedStyleContext,
1325 property_declaration_id: &PropertyDeclarationId,
1326 index: usize,
1327 old_style: &ComputedValues,
1328 new_style: &Arc<ComputedValues>,
1329 ) {
1330 let style = new_style.get_ui();
1331 let allow_discrete =
1332 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1333
1334 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1336 else {
1337 return;
1338 };
1339 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1340 else {
1341 return;
1342 };
1343
1344 let timing_function = style.transition_timing_function_mod(index);
1345 let duration = style.transition_duration_mod(index).seconds() as f64;
1346 let delay = style.transition_delay_mod(index).seconds() as f64;
1347 let now = context.current_time_for_animations;
1348 let transitionable = property_declaration_id.is_animatable()
1349 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1350 && (allow_discrete || from.interpolable_with(&to));
1351
1352 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1353 transition.property_animation.property_id() == *property_declaration_id
1354 });
1355
1356 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1371 transition.state != AnimationState::Finished
1372 && transition.state != AnimationState::Canceled
1373 });
1374 let no_completed_transition_or_end_values_differ =
1375 existing_transition.as_ref().is_none_or(|transition| {
1376 transition.state != AnimationState::Finished
1377 || transition.property_animation.to != to
1378 });
1379 if !has_running_transition
1380 && from != to
1381 && transitionable
1382 && no_completed_transition_or_end_values_differ
1383 && (duration + delay > 0.0)
1384 {
1385 self.transitions.push(Transition::new(
1396 now + delay, delay,
1398 duration,
1399 from,
1400 to,
1401 &timing_function,
1402 ));
1403 self.dirty = true;
1404 return;
1405 }
1406
1407 let Some(existing_transition) = existing_transition.as_mut() else {
1430 return;
1431 };
1432
1433 if has_running_transition && existing_transition.property_animation.to != to {
1438 let current_value = existing_transition.calculate_value(now);
1443 let transitionable_from_current_value =
1444 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1445 if current_value == to || !transitionable_from_current_value {
1446 existing_transition.state = AnimationState::Canceled;
1447 self.dirty = true;
1448 return;
1449 }
1450
1451 if duration + delay <= 0.0 {
1457 existing_transition.state = AnimationState::Canceled;
1458 self.dirty = true;
1459 return;
1460 }
1461
1462 if existing_transition.reversing_adjusted_start_value == to {
1468 existing_transition.state = AnimationState::Canceled;
1469
1470 let mut transition = Transition::new(
1471 now + delay, delay,
1473 duration,
1474 from,
1475 to,
1476 &timing_function,
1477 );
1478
1479 transition.update_for_possibly_reversed_transition(
1482 &existing_transition,
1483 delay,
1484 now,
1485 );
1486
1487 self.transitions.push(transition);
1488 self.dirty = true;
1489 return;
1490 }
1491
1492 existing_transition.state = AnimationState::Canceled;
1501 self.transitions.push(Transition::new(
1502 now + delay, delay,
1504 duration,
1505 current_value,
1506 to,
1507 &timing_function,
1508 ));
1509 self.dirty = true;
1510 }
1511 }
1512
1513 fn get_value_map_for_transitions(
1517 &self,
1518 now: f64,
1519 ignore_transitions: IgnoreTransitions,
1520 ) -> Option<AnimationValueMap> {
1521 if !self.has_active_transition() {
1522 return None;
1523 }
1524
1525 let mut map =
1526 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1527 for transition in &self.transitions {
1528 match ignore_transitions {
1529 IgnoreTransitions::Canceled => {
1530 if transition.state == AnimationState::Canceled {
1531 continue;
1532 }
1533 },
1534 IgnoreTransitions::CanceledAndFinished => {
1535 if transition.state == AnimationState::Canceled
1536 || transition.state == AnimationState::Finished
1537 {
1538 continue;
1539 }
1540 },
1541 }
1542
1543 let value = transition.calculate_value(now);
1544 map.insert(value.id().to_owned(), value);
1545 }
1546
1547 Some(map)
1548 }
1549
1550 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1553 if !self.has_active_animation() {
1554 return None;
1555 }
1556
1557 let mut map = Default::default();
1558 for animation in &self.animations {
1559 animation.get_property_declaration_at_time(now, &mut map);
1560 }
1561
1562 Some(map)
1563 }
1564}
1565
1566#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1567pub struct AnimationSetKey {
1569 pub node: OpaqueNode,
1571 pub pseudo_element: Option<PseudoElement>,
1574}
1575
1576impl AnimationSetKey {
1577 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1579 AnimationSetKey {
1580 node,
1581 pseudo_element,
1582 }
1583 }
1584
1585 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1587 AnimationSetKey {
1588 node,
1589 pseudo_element: None,
1590 }
1591 }
1592
1593 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1595 AnimationSetKey {
1596 node,
1597 pseudo_element: Some(pseudo_element),
1598 }
1599 }
1600}
1601
1602#[derive(Clone, Debug, Default, MallocSizeOf)]
1603pub struct DocumentAnimationSet {
1605 #[ignore_malloc_size_of = "Arc is hard"]
1607 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1608}
1609
1610impl DocumentAnimationSet {
1611 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1613 self.sets
1614 .read()
1615 .get(key)
1616 .map_or(false, |set| set.has_active_animation())
1617 }
1618
1619 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1621 self.sets
1622 .read()
1623 .get(key)
1624 .map_or(false, |set| set.has_active_transition())
1625 }
1626
1627 pub fn get_animation_declarations(
1630 &self,
1631 key: &AnimationSetKey,
1632 time: f64,
1633 shared_lock: &SharedRwLock,
1634 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1635 self.sets
1636 .read()
1637 .get(key)
1638 .and_then(|set| set.get_value_map_for_active_animations(time))
1639 .map(|map| {
1640 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1641 Arc::new(shared_lock.wrap(block))
1642 })
1643 }
1644
1645 pub fn get_transition_declarations(
1648 &self,
1649 key: &AnimationSetKey,
1650 time: f64,
1651 shared_lock: &SharedRwLock,
1652 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1653 self.sets
1654 .read()
1655 .get(key)
1656 .and_then(|set| {
1657 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1658 })
1659 .map(|map| {
1660 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1661 Arc::new(shared_lock.wrap(block))
1662 })
1663 }
1664
1665 pub fn get_all_declarations(
1668 &self,
1669 key: &AnimationSetKey,
1670 time: f64,
1671 shared_lock: &SharedRwLock,
1672 ) -> AnimationDeclarations {
1673 let sets = self.sets.read();
1674 let set = match sets.get(key) {
1675 Some(set) => set,
1676 None => return Default::default(),
1677 };
1678
1679 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1680 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1681 Arc::new(shared_lock.wrap(block))
1682 });
1683 let transitions = set
1684 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1685 .map(|map| {
1686 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1687 Arc::new(shared_lock.wrap(block))
1688 });
1689 AnimationDeclarations {
1690 animations,
1691 transitions,
1692 }
1693 }
1694
1695 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1697 if let Some(set) = self.sets.write().get_mut(key) {
1698 set.cancel_all_animations();
1699 }
1700 }
1701}
1702
1703pub fn start_transitions_if_applicable(
1706 context: &SharedStyleContext,
1707 old_style: &ComputedValues,
1708 new_style: &Arc<ComputedValues>,
1709 animation_state: &mut ElementAnimationSet,
1710) -> PropertyDeclarationIdSet {
1711 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1726 transition_properties.reverse();
1727
1728 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1729 for transition in transition_properties {
1730 let physical_property = transition
1731 .property
1732 .as_borrowed()
1733 .to_physical(new_style.writing_mode);
1734 if properties_that_transition.contains(physical_property) {
1735 continue;
1736 }
1737
1738 properties_that_transition.insert(physical_property);
1739 animation_state.start_transition_if_applicable(
1740 context,
1741 &physical_property,
1742 transition.index,
1743 old_style,
1744 new_style,
1745 );
1746 }
1747
1748 properties_that_transition
1749}
1750
1751pub fn maybe_start_animations<E>(
1754 element: E,
1755 context: &SharedStyleContext,
1756 new_style: &Arc<ComputedValues>,
1757 animation_state: &mut ElementAnimationSet,
1758 resolver: &mut StyleResolverForElement<E>,
1759) where
1760 E: TElement,
1761{
1762 let style = new_style.get_ui();
1763 for (i, name) in style.animation_name_iter().enumerate() {
1764 let name = match name.as_atom() {
1765 Some(atom) => atom,
1766 None => continue,
1767 };
1768
1769 debug!("maybe_start_animations: name={}", name);
1770 let duration = style.animation_duration_mod(i).seconds() as f64;
1771 if duration == 0. {
1772 continue;
1773 }
1774
1775 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1776 continue;
1777 };
1778
1779 debug!("maybe_start_animations: animation {} found", name);
1780
1781 let delay = style.animation_delay_mod(i).seconds() as f64;
1785
1786 let iteration_count = style.animation_iteration_count_mod(i);
1787 let iteration_state = if iteration_count.0.is_infinite() {
1788 KeyframesIterationState::Infinite(0.0)
1789 } else {
1790 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1791 };
1792
1793 let animation_direction = style.animation_direction_mod(i);
1794
1795 let initial_direction = match animation_direction {
1796 AnimationDirection::Normal | AnimationDirection::Alternate => {
1797 AnimationDirection::Normal
1798 },
1799 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1800 AnimationDirection::Reverse
1801 },
1802 };
1803
1804 let now = context.current_time_for_animations;
1805 let started_at = now + delay;
1806 let mut starting_progress = (now - started_at) / duration;
1807 let state = match style.animation_play_state_mod(i) {
1808 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1809 AnimationPlayState::Running => AnimationState::Pending,
1810 };
1811
1812 let mut animating_properties = PropertyDeclarationIdSet::default();
1816 let mut number_of_animating_properties = 0;
1817 for property in keyframe_animation.properties_changed.iter() {
1818 debug_assert!(property.is_animatable());
1819
1820 if animating_properties.insert(property.to_physical(new_style.writing_mode)) {
1821 number_of_animating_properties += 1;
1822 }
1823 }
1824
1825 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1826 element,
1827 &keyframe_animation,
1828 context,
1829 new_style,
1830 style.animation_timing_function_mod(i),
1831 resolver,
1832 animating_properties,
1833 number_of_animating_properties,
1834 );
1835
1836 let mut new_animation = Animation {
1837 name: name.clone(),
1838 properties_changed: keyframe_animation.properties_changed.clone(),
1839 computed_steps,
1840 started_at,
1841 duration,
1842 fill_mode: style.animation_fill_mode_mod(i),
1843 delay,
1844 iteration_state,
1845 state,
1846 direction: animation_direction,
1847 current_direction: initial_direction,
1848 number_of_animating_properties,
1849 is_new: true,
1850 };
1851
1852 while starting_progress > 1. && !new_animation.on_last_iteration() {
1855 new_animation.iterate();
1856 starting_progress -= 1.;
1857 }
1858
1859 animation_state.dirty = true;
1860
1861 for existing_animation in animation_state.animations.iter_mut() {
1863 if existing_animation.state == AnimationState::Canceled {
1864 continue;
1865 }
1866
1867 if new_animation.name == existing_animation.name {
1868 existing_animation
1869 .update_from_other(&new_animation, context.current_time_for_animations);
1870 return;
1871 }
1872 }
1873
1874 animation_state.animations.push(new_animation);
1875 }
1876}