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 self.iterate_by(1.) == 1.
598 }
599
600 fn iterate_by(&mut self, n: f64) -> f64 {
604 let n = n.trunc().min(self.remaining_iterations().ceil() - 1.0);
605 if n < 1. {
606 return 0.;
607 }
608
609 match self.iteration_state {
610 KeyframesIterationState::Finite(ref mut current, max) => {
611 *current = (*current + n).min(max);
612 },
613 KeyframesIterationState::Infinite(ref mut current) => {
614 *current += n;
615 },
616 }
617
618 if let AnimationState::Paused(ref mut progress) = self.state {
619 debug_assert!(*progress >= n);
620 *progress -= n;
621 }
622
623 self.started_at += self.duration * n;
625 match self.direction {
626 AnimationDirection::Alternate | AnimationDirection::AlternateReverse
627 if n % 2. == 1.0 =>
628 {
629 self.current_direction = match self.current_direction {
630 AnimationDirection::Normal => AnimationDirection::Reverse,
631 AnimationDirection::Reverse => AnimationDirection::Normal,
632 _ => unreachable!(
633 "Current animation direction can only be `normal` or `reverse`."
634 ),
635 };
636 },
637 _ => {},
638 }
639
640 n
641 }
642
643 fn remaining_iterations(&self) -> f64 {
644 match self.iteration_state {
645 KeyframesIterationState::Finite(current, max) => max - current,
646 KeyframesIterationState::Infinite(_) => f64::INFINITY,
647 }
648 }
649
650 pub fn current_iteration_end_progress(&self) -> f64 {
655 self.remaining_iterations().min(1.)
656 }
657
658 pub fn current_iteration_duration(&self) -> f64 {
661 self.current_iteration_end_progress() * self.duration
662 }
663
664 fn iteration_over(&self, time: f64) -> bool {
667 time > (self.started_at + self.current_iteration_duration())
668 }
669
670 fn on_last_iteration(&self) -> bool {
672 self.remaining_iterations() <= 1.
673 }
674
675 pub fn has_ended(&self, time: f64) -> bool {
679 if !self.on_last_iteration() {
680 return false;
681 }
682
683 let progress = match self.state {
684 AnimationState::Finished => return true,
685 AnimationState::Paused(progress) => progress,
686 AnimationState::Running => (time - self.started_at) / self.duration,
687 AnimationState::Pending | AnimationState::Canceled => return false,
688 };
689
690 progress >= self.current_iteration_end_progress()
691 }
692
693 pub fn update_from_other(&mut self, other: &Self, now: f64) {
701 use self::AnimationState::*;
702
703 debug!(
704 "KeyframesAnimationState::update_from_other({:?}, {:?})",
705 self, other
706 );
707
708 let old_started_at = self.started_at;
711 let old_delay = self.delay;
712 let old_duration = self.duration;
713 let old_direction = self.current_direction;
714 let old_state = self.state.clone();
715 let old_iteration_state = self.iteration_state.clone();
716
717 *self = other.clone();
718 self.current_direction = old_direction;
719
720 if self.delay != old_delay {
721 self.started_at = old_started_at + (self.delay - old_delay);
724
725 match old_state {
726 Paused(old_progress) => {
727 let mut progress = old_progress + (old_delay - self.delay) / self.duration;
728 progress -= self.iterate_by(progress);
729 self.state = Paused(progress);
730 },
731 Finished => {
732 if self.has_ended(now) {
733 self.state = Finished;
734 } else if self.started_at <= now {
735 self.state = Running;
736 } else {
737 self.state = Pending;
738 }
739 },
740 Canceled | Pending | Running => {
741 let new_starting_progress = (now - self.started_at) / self.duration;
743 match self.iteration_state {
744 KeyframesIterationState::Finite(ref mut current, _) => *current = 0.0,
745 _ => {},
746 }
747 if let AnimationState::Paused(ref mut starting_progress) = &mut self.state {
748 *starting_progress = new_starting_progress;
749 }
750 self.iterate_by(new_starting_progress);
751 },
752 }
753
754 if self.state == Pending && self.started_at <= now {
756 self.state = Running;
757 }
758 } else {
759 self.started_at = old_started_at;
760
761 match (&mut self.iteration_state, old_iteration_state) {
765 (
766 &mut KeyframesIterationState::Finite(ref mut iters, _),
767 KeyframesIterationState::Finite(old_iters, _),
768 ) => *iters = old_iters,
769 _ => {},
770 }
771
772 let new_state = std::mem::replace(&mut self.state, Running);
775 if old_state == Finished && self.has_ended(now) {
776 self.state = Finished;
777 } else {
778 self.state = new_state;
779 }
780
781 match (&mut self.state, &old_state) {
788 (&mut Pending, &Paused(progress)) => {
789 self.started_at = now - (self.duration * progress);
790 },
791 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
792 (&mut Paused(ref mut progress), &Running) => {
793 *progress = (now - old_started_at) / old_duration
794 },
795 _ => {},
796 }
797
798 if self.state == Pending && self.started_at <= now && old_state != Pending {
801 self.state = Running;
802 }
803 }
804 }
805
806 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
809 if self.computed_steps.is_empty() {
810 return;
812 }
813
814 let progress = match self.state {
817 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
818 (now - self.started_at) / self.duration
819 },
820 AnimationState::Paused(progress) => progress,
821 AnimationState::Canceled => return,
822 };
823
824 if progress < 0.
825 && self.fill_mode != AnimationFillMode::Backwards
826 && self.fill_mode != AnimationFillMode::Both
827 {
828 return;
829 }
830 if self.has_ended(now)
831 && self.fill_mode != AnimationFillMode::Forwards
832 && self.fill_mode != AnimationFillMode::Both
833 {
834 return;
835 }
836
837 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
840 for value_or_reference in keyframe.values.iter() {
841 let AnimationValueOrReference::AnimationValue(value) = value_or_reference else {
842 unreachable!("First or last keyframes define all properties");
843 };
844 map.insert(value.id().to_owned(), value.clone());
845 }
846 };
847
848 if progress < 0.0 {
850 if let Some(keyframe) = match self.current_direction {
851 AnimationDirection::Normal => self.computed_steps.first(),
852 AnimationDirection::Reverse => self.computed_steps.last(),
853 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
854 } {
855 add_declarations_to_map(keyframe);
856 }
857 return;
858 }
859
860 let total_progress = progress.min(self.current_iteration_end_progress()).max(0.0);
862
863 if total_progress == 1.0 {
865 let keyframe = match self.current_direction {
866 AnimationDirection::Normal => self.computed_steps.last().unwrap(),
867 AnimationDirection::Reverse => self.computed_steps.first().unwrap(),
868 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
869 };
870 add_declarations_to_map(keyframe);
871 return;
872 }
873
874 let next_keyframe_index;
876 let prev_keyframe_index;
877 let num_steps = self.computed_steps.len();
878 match self.current_direction {
879 AnimationDirection::Normal => {
880 next_keyframe_index = self
881 .computed_steps
882 .iter()
883 .position(|step| total_progress < step.start_percentage);
884 prev_keyframe_index = next_keyframe_index
885 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
886 .unwrap_or(0);
887 },
888 AnimationDirection::Reverse => {
889 next_keyframe_index = self
890 .computed_steps
891 .iter()
892 .rev()
893 .position(|step| total_progress <= 1. - step.start_percentage)
894 .map(|pos| num_steps - pos - 1);
895 prev_keyframe_index = next_keyframe_index
896 .and_then(|pos| {
897 if pos != num_steps - 1 {
898 Some(pos + 1)
899 } else {
900 None
901 }
902 })
903 .unwrap_or(num_steps - 1)
904 },
905 _ => unreachable!(),
906 }
907
908 debug!(
909 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
910 prev_keyframe_index, next_keyframe_index
911 );
912
913 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
914 let Some(next_keyframe_index) = next_keyframe_index else {
915 unsafe {
916 debug_unreachable!(
917 "next_keyframe_index should always be Some: \
918 total_progress is in [0, 1) at this point. \
919 Normal direction: keyframe with start_percentage 1.0 always satisfies. \
920 Reverse direction: keyframe with start_percentage 0.0 always satisfies."
921 );
922 }
923 };
924
925 if prev_keyframe_index == next_keyframe_index {
928 add_declarations_to_map(&prev_keyframe);
929 return;
930 }
931
932 let reversed = self.current_direction != AnimationDirection::Normal;
934 for property_index in 0..self.number_of_animating_properties {
935 let Some(previous_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
936 property_index,
937 prev_keyframe_index,
938 Direction::Backward.relative_to_animation_direction(reversed),
939 ) else {
940 continue;
942 };
943
944 let Some(next_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
945 property_index,
946 next_keyframe_index,
947 Direction::Forward.relative_to_animation_direction(reversed),
948 ) else {
949 map.insert(
951 previous_keyframe.value.id().to_owned(),
952 previous_keyframe.value.clone(),
953 );
954 continue;
955 };
956
957 let percentage_between_keyframes =
958 (next_keyframe.start_percentage - previous_keyframe.start_percentage).abs();
959 let duration_between_keyframes = percentage_between_keyframes * self.duration;
960 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
961 AnimationDirection::Normal => previous_keyframe.start_percentage,
962 AnimationDirection::Reverse => 1. - previous_keyframe.start_percentage,
963 _ => unreachable!(),
964 };
965 let progress_between_keyframes = (total_progress
966 - direction_aware_prev_keyframe_start_percentage)
967 / percentage_between_keyframes;
968 let animation = PropertyAnimation {
969 from: previous_keyframe.value.clone(),
970 to: next_keyframe.value.clone(),
971 timing_function: previous_keyframe.timing_function.clone(),
972 duration: duration_between_keyframes,
973 };
974
975 let value = animation.calculate_value(progress_between_keyframes);
976 map.insert(value.id().to_owned(), value);
977 }
978 }
979}
980
981impl fmt::Debug for Animation {
982 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
983 f.debug_struct("Animation")
984 .field("name", &self.name)
985 .field("started_at", &self.started_at)
986 .field("duration", &self.duration)
987 .field("delay", &self.delay)
988 .field("iteration_state", &self.iteration_state)
989 .field("state", &self.state)
990 .field("direction", &self.direction)
991 .field("current_direction", &self.current_direction)
992 .field("cascade_style", &())
993 .finish()
994 }
995}
996
997#[derive(Clone, Debug, MallocSizeOf)]
999pub struct Transition {
1000 pub start_time: f64,
1003
1004 pub delay: f64,
1006
1007 pub property_animation: PropertyAnimation,
1009
1010 pub state: AnimationState,
1012
1013 pub is_new: bool,
1016
1017 pub reversing_adjusted_start_value: AnimationValue,
1020
1021 pub reversing_shortening_factor: f64,
1024}
1025
1026impl Transition {
1027 fn new(
1028 start_time: f64,
1029 delay: f64,
1030 duration: f64,
1031 from: AnimationValue,
1032 to: AnimationValue,
1033 timing_function: &TimingFunction,
1034 ) -> Self {
1035 let property_animation = PropertyAnimation {
1036 from: from.clone(),
1037 to,
1038 timing_function: timing_function.clone(),
1039 duration,
1040 };
1041 Self {
1042 start_time,
1043 delay,
1044 property_animation,
1045 state: AnimationState::Pending,
1046 is_new: true,
1047 reversing_adjusted_start_value: from,
1048 reversing_shortening_factor: 1.0,
1049 }
1050 }
1051
1052 fn update_for_possibly_reversed_transition(
1053 &mut self,
1054 replaced_transition: &Transition,
1055 delay: f64,
1056 now: f64,
1057 ) {
1058 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
1067 return;
1068 }
1069
1070 let replaced_animation = &replaced_transition.property_animation;
1072 self.reversing_adjusted_start_value = replaced_animation.to.clone();
1073
1074 let transition_progress = ((now - replaced_transition.start_time)
1081 / (replaced_transition.property_animation.duration))
1082 .min(1.0)
1083 .max(0.0);
1084 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
1085 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
1086 self.reversing_shortening_factor = ((timing_function_output
1087 * old_reversing_shortening_factor)
1088 + (1.0 - old_reversing_shortening_factor))
1089 .abs()
1090 .min(1.0)
1091 .max(0.0);
1092
1093 self.start_time = if delay >= 0. {
1099 now + delay
1100 } else {
1101 now + (self.reversing_shortening_factor * delay)
1102 };
1103
1104 self.property_animation.duration *= self.reversing_shortening_factor;
1107
1108 let procedure = Procedure::Interpolate {
1111 progress: timing_function_output,
1112 };
1113 match replaced_animation
1114 .from
1115 .animate(&replaced_animation.to, procedure)
1116 {
1117 Ok(new_start) => self.property_animation.from = new_start,
1118 Err(..) => {},
1119 }
1120 }
1121
1122 pub fn has_ended(&self, time: f64) -> bool {
1126 time >= self.start_time + (self.property_animation.duration)
1127 }
1128
1129 pub fn calculate_value(&self, time: f64) -> AnimationValue {
1131 let progress = if time < self.start_time {
1132 0.0
1133 } else if self.property_animation.duration == 0.0 {
1134 1.0
1135 } else {
1136 ((time - self.start_time) / self.property_animation.duration).clamp(0.0, 1.0)
1137 };
1138
1139 self.property_animation.calculate_value(progress)
1140 }
1141}
1142
1143#[derive(Debug, Default, MallocSizeOf)]
1145pub struct ElementAnimationSet {
1146 pub animations: Vec<Animation>,
1148
1149 pub transitions: Vec<Transition>,
1151
1152 pub dirty: bool,
1155}
1156
1157impl ElementAnimationSet {
1158 pub fn cancel_all_animations(&mut self) {
1161 self.dirty = !self.animations.is_empty();
1162 for animation in self.animations.iter_mut() {
1163 animation.state = AnimationState::Canceled;
1164 }
1165 self.cancel_active_transitions();
1166 }
1167
1168 fn cancel_active_transitions(&mut self) {
1169 for transition in self.transitions.iter_mut() {
1170 if transition.state != AnimationState::Finished {
1171 self.dirty = true;
1172 transition.state = AnimationState::Canceled;
1173 }
1174 }
1175 }
1176
1177 pub fn apply_active_animations(
1179 &self,
1180 context: &SharedStyleContext,
1181 style: &mut Arc<ComputedValues>,
1182 ) {
1183 let now = context.current_time_for_animations;
1184 let mutable_style = Arc::make_mut(style);
1185 if let Some(map) = self.get_value_map_for_active_animations(now) {
1186 for value in map.values() {
1187 value.set_in_style_for_servo(mutable_style, context);
1188 }
1189 }
1190
1191 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
1192 for value in map.values() {
1193 value.set_in_style_for_servo(mutable_style, context);
1194 }
1195 }
1196 }
1197
1198 pub fn clear_canceled_animations(&mut self) {
1200 self.animations
1201 .retain(|animation| animation.state != AnimationState::Canceled);
1202 self.transitions
1203 .retain(|animation| animation.state != AnimationState::Canceled);
1204 }
1205
1206 pub fn is_empty(&self) -> bool {
1209 self.animations.is_empty() && self.transitions.is_empty()
1210 }
1211
1212 pub fn needs_animation_ticks(&self) -> bool {
1215 self.animations
1216 .iter()
1217 .any(|animation| animation.state.needs_to_be_ticked())
1218 || self
1219 .transitions
1220 .iter()
1221 .any(|transition| transition.state.needs_to_be_ticked())
1222 }
1223
1224 pub fn running_animation_and_transition_count(&self) -> usize {
1226 self.animations
1227 .iter()
1228 .filter(|animation| animation.state.needs_to_be_ticked())
1229 .count()
1230 + self
1231 .transitions
1232 .iter()
1233 .filter(|transition| transition.state.needs_to_be_ticked())
1234 .count()
1235 }
1236
1237 pub fn has_active_animation(&self) -> bool {
1239 self.animations
1240 .iter()
1241 .any(|animation| animation.state != AnimationState::Canceled)
1242 }
1243
1244 pub fn has_active_transition(&self) -> bool {
1246 self.transitions
1247 .iter()
1248 .any(|transition| transition.state != AnimationState::Canceled)
1249 }
1250
1251 pub fn update_animations_for_new_style<E>(
1254 &mut self,
1255 element: E,
1256 context: &SharedStyleContext,
1257 new_style: &Arc<ComputedValues>,
1258 resolver: &mut StyleResolverForElement<E>,
1259 ) where
1260 E: TElement,
1261 {
1262 for animation in self.animations.iter_mut() {
1263 if animation.is_cancelled_in_new_style(new_style) {
1264 animation.state = AnimationState::Canceled;
1265 }
1266 }
1267
1268 maybe_start_animations(element, &context, &new_style, self, resolver);
1269 }
1270
1271 pub fn update_transitions_for_new_style(
1274 &mut self,
1275 might_need_transitions_update: bool,
1276 context: &SharedStyleContext,
1277 old_style: Option<&Arc<ComputedValues>>,
1278 after_change_style: &Arc<ComputedValues>,
1279 ) {
1280 let mut before_change_style = match old_style {
1283 Some(old_style) => Arc::clone(old_style),
1284 None => return,
1285 };
1286
1287 if after_change_style.get_box().clone_display().is_none() {
1289 self.cancel_active_transitions();
1290 return;
1291 }
1292
1293 if !might_need_transitions_update {
1294 return;
1295 }
1296
1297 if self.has_active_transition() || self.has_active_animation() {
1299 self.apply_active_animations(context, &mut before_change_style);
1300 }
1301
1302 let transitioning_properties = start_transitions_if_applicable(
1303 context,
1304 &before_change_style,
1305 after_change_style,
1306 self,
1307 );
1308
1309 for transition in self.transitions.iter_mut() {
1322 if transition.state == AnimationState::Finished
1323 || transition.state == AnimationState::Canceled
1324 {
1325 continue;
1326 }
1327 if transitioning_properties.contains(transition.property_animation.property_id()) {
1328 continue;
1329 }
1330 transition.state = AnimationState::Canceled;
1331 self.dirty = true;
1332 }
1333 }
1334
1335 fn start_transition_if_applicable(
1336 &mut self,
1337 context: &SharedStyleContext,
1338 property_declaration_id: &PropertyDeclarationId,
1339 index: usize,
1340 old_style: &ComputedValues,
1341 new_style: &Arc<ComputedValues>,
1342 ) {
1343 let style = new_style.get_ui();
1344 let allow_discrete =
1345 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1346
1347 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1349 else {
1350 return;
1351 };
1352 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1353 else {
1354 return;
1355 };
1356
1357 let timing_function = style.transition_timing_function_mod(index);
1358 let duration = style.transition_duration_mod(index).seconds() as f64;
1359 let delay = style.transition_delay_mod(index).seconds() as f64;
1360 let now = context.current_time_for_animations;
1361 let transitionable = property_declaration_id.is_animatable()
1362 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1363 && (allow_discrete || from.interpolable_with(&to));
1364
1365 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1366 transition.property_animation.property_id() == *property_declaration_id
1367 });
1368
1369 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1384 transition.state != AnimationState::Finished
1385 && transition.state != AnimationState::Canceled
1386 });
1387 let no_completed_transition_or_end_values_differ =
1388 existing_transition.as_ref().is_none_or(|transition| {
1389 transition.state != AnimationState::Finished
1390 || transition.property_animation.to != to
1391 });
1392 if !has_running_transition
1393 && from != to
1394 && transitionable
1395 && no_completed_transition_or_end_values_differ
1396 && (duration + delay > 0.0)
1397 {
1398 self.transitions.push(Transition::new(
1409 now + delay, delay,
1411 duration,
1412 from,
1413 to,
1414 &timing_function,
1415 ));
1416 self.dirty = true;
1417 return;
1418 }
1419
1420 let Some(existing_transition) = existing_transition.as_mut() else {
1443 return;
1444 };
1445
1446 if has_running_transition && existing_transition.property_animation.to != to {
1451 let current_value = existing_transition.calculate_value(now);
1456 let transitionable_from_current_value =
1457 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1458 if current_value == to || !transitionable_from_current_value {
1459 existing_transition.state = AnimationState::Canceled;
1460 self.dirty = true;
1461 return;
1462 }
1463
1464 if duration + delay <= 0.0 {
1470 existing_transition.state = AnimationState::Canceled;
1471 self.dirty = true;
1472 return;
1473 }
1474
1475 if existing_transition.reversing_adjusted_start_value == to {
1481 existing_transition.state = AnimationState::Canceled;
1482
1483 let mut transition = Transition::new(
1484 now + delay, delay,
1486 duration,
1487 from,
1488 to,
1489 &timing_function,
1490 );
1491
1492 transition.update_for_possibly_reversed_transition(
1495 &existing_transition,
1496 delay,
1497 now,
1498 );
1499
1500 self.transitions.push(transition);
1501 self.dirty = true;
1502 return;
1503 }
1504
1505 existing_transition.state = AnimationState::Canceled;
1514 self.transitions.push(Transition::new(
1515 now + delay, delay,
1517 duration,
1518 current_value,
1519 to,
1520 &timing_function,
1521 ));
1522 self.dirty = true;
1523 }
1524 }
1525
1526 fn get_value_map_for_transitions(
1530 &self,
1531 now: f64,
1532 ignore_transitions: IgnoreTransitions,
1533 ) -> Option<AnimationValueMap> {
1534 if !self.has_active_transition() {
1535 return None;
1536 }
1537
1538 let mut map =
1539 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1540 for transition in &self.transitions {
1541 match ignore_transitions {
1542 IgnoreTransitions::Canceled => {
1543 if transition.state == AnimationState::Canceled {
1544 continue;
1545 }
1546 },
1547 IgnoreTransitions::CanceledAndFinished => {
1548 if transition.state == AnimationState::Canceled
1549 || transition.state == AnimationState::Finished
1550 {
1551 continue;
1552 }
1553 },
1554 }
1555
1556 let value = transition.calculate_value(now);
1557 map.insert(value.id().to_owned(), value);
1558 }
1559
1560 Some(map)
1561 }
1562
1563 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1566 if !self.has_active_animation() {
1567 return None;
1568 }
1569
1570 let mut map = Default::default();
1571 for animation in &self.animations {
1572 animation.get_property_declaration_at_time(now, &mut map);
1573 }
1574
1575 Some(map)
1576 }
1577}
1578
1579#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1580pub struct AnimationSetKey {
1582 pub node: OpaqueNode,
1584 pub pseudo_element: Option<PseudoElement>,
1587}
1588
1589impl AnimationSetKey {
1590 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1592 AnimationSetKey {
1593 node,
1594 pseudo_element,
1595 }
1596 }
1597
1598 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1600 AnimationSetKey {
1601 node,
1602 pseudo_element: None,
1603 }
1604 }
1605
1606 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1608 AnimationSetKey {
1609 node,
1610 pseudo_element: Some(pseudo_element),
1611 }
1612 }
1613}
1614
1615#[derive(Clone, Debug, Default, MallocSizeOf)]
1616pub struct DocumentAnimationSet {
1618 #[ignore_malloc_size_of = "Arc is hard"]
1620 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1621}
1622
1623impl DocumentAnimationSet {
1624 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1626 self.sets
1627 .read()
1628 .get(key)
1629 .map_or(false, |set| set.has_active_animation())
1630 }
1631
1632 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1634 self.sets
1635 .read()
1636 .get(key)
1637 .map_or(false, |set| set.has_active_transition())
1638 }
1639
1640 pub fn get_animation_declarations(
1643 &self,
1644 key: &AnimationSetKey,
1645 time: f64,
1646 shared_lock: &SharedRwLock,
1647 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1648 self.sets
1649 .read()
1650 .get(key)
1651 .and_then(|set| set.get_value_map_for_active_animations(time))
1652 .map(|map| {
1653 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1654 Arc::new(shared_lock.wrap(block))
1655 })
1656 }
1657
1658 pub fn get_transition_declarations(
1661 &self,
1662 key: &AnimationSetKey,
1663 time: f64,
1664 shared_lock: &SharedRwLock,
1665 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1666 self.sets
1667 .read()
1668 .get(key)
1669 .and_then(|set| {
1670 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1671 })
1672 .map(|map| {
1673 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1674 Arc::new(shared_lock.wrap(block))
1675 })
1676 }
1677
1678 pub fn get_all_declarations(
1681 &self,
1682 key: &AnimationSetKey,
1683 time: f64,
1684 shared_lock: &SharedRwLock,
1685 ) -> AnimationDeclarations {
1686 let sets = self.sets.read();
1687 let set = match sets.get(key) {
1688 Some(set) => set,
1689 None => return Default::default(),
1690 };
1691
1692 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1693 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1694 Arc::new(shared_lock.wrap(block))
1695 });
1696 let transitions = set
1697 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1698 .map(|map| {
1699 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1700 Arc::new(shared_lock.wrap(block))
1701 });
1702 AnimationDeclarations {
1703 animations,
1704 transitions,
1705 }
1706 }
1707
1708 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1710 if let Some(set) = self.sets.write().get_mut(key) {
1711 set.cancel_all_animations();
1712 }
1713 }
1714}
1715
1716pub fn start_transitions_if_applicable(
1719 context: &SharedStyleContext,
1720 old_style: &ComputedValues,
1721 new_style: &Arc<ComputedValues>,
1722 animation_state: &mut ElementAnimationSet,
1723) -> PropertyDeclarationIdSet {
1724 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1739 transition_properties.reverse();
1740
1741 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1742 for transition in transition_properties {
1743 let physical_property = transition
1744 .property
1745 .as_borrowed()
1746 .to_physical(new_style.writing_mode);
1747 if properties_that_transition.contains(physical_property) {
1748 continue;
1749 }
1750
1751 properties_that_transition.insert(physical_property);
1752 animation_state.start_transition_if_applicable(
1753 context,
1754 &physical_property,
1755 transition.index,
1756 old_style,
1757 new_style,
1758 );
1759 }
1760
1761 properties_that_transition
1762}
1763
1764pub fn maybe_start_animations<E>(
1767 element: E,
1768 context: &SharedStyleContext,
1769 new_style: &Arc<ComputedValues>,
1770 animation_state: &mut ElementAnimationSet,
1771 resolver: &mut StyleResolverForElement<E>,
1772) where
1773 E: TElement,
1774{
1775 let style = new_style.get_ui();
1776 for (i, name) in style.animation_name_iter().enumerate() {
1777 let name = match name.as_atom() {
1778 Some(atom) => atom,
1779 None => continue,
1780 };
1781
1782 debug!("maybe_start_animations: name={}", name);
1783 let duration = style.animation_duration_mod(i).seconds() as f64;
1784 if duration == 0. {
1785 continue;
1786 }
1787
1788 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1789 continue;
1790 };
1791
1792 debug!("maybe_start_animations: animation {} found", name);
1793
1794 let delay = style.animation_delay_mod(i).seconds() as f64;
1798
1799 let iteration_count = style.animation_iteration_count_mod(i);
1800 let iteration_state = if iteration_count.0.is_infinite() {
1801 KeyframesIterationState::Infinite(0.0)
1802 } else {
1803 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1804 };
1805
1806 let animation_direction = style.animation_direction_mod(i);
1807
1808 let initial_direction = match animation_direction {
1809 AnimationDirection::Normal | AnimationDirection::Alternate => {
1810 AnimationDirection::Normal
1811 },
1812 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1813 AnimationDirection::Reverse
1814 },
1815 };
1816
1817 let now = context.current_time_for_animations;
1818 let started_at = now + delay;
1819 let starting_progress = (now - started_at) / duration;
1820 let state = match style.animation_play_state_mod(i) {
1821 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1822 AnimationPlayState::Running => AnimationState::Pending,
1823 };
1824
1825 let mut animating_properties = PropertyDeclarationIdSet::default();
1829 let mut number_of_animating_properties = 0;
1830 for property in keyframe_animation.properties_changed.iter() {
1831 debug_assert!(property.is_animatable());
1832
1833 if animating_properties.insert(property.to_physical(new_style.writing_mode)) {
1834 number_of_animating_properties += 1;
1835 }
1836 }
1837
1838 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1839 element,
1840 &keyframe_animation,
1841 context,
1842 new_style,
1843 style.animation_timing_function_mod(i),
1844 resolver,
1845 animating_properties,
1846 number_of_animating_properties,
1847 );
1848
1849 let mut new_animation = Animation {
1850 name: name.clone(),
1851 properties_changed: keyframe_animation.properties_changed.clone(),
1852 computed_steps,
1853 started_at,
1854 duration,
1855 fill_mode: style.animation_fill_mode_mod(i),
1856 delay,
1857 iteration_state,
1858 state,
1859 direction: animation_direction,
1860 current_direction: initial_direction,
1861 number_of_animating_properties,
1862 is_new: true,
1863 };
1864
1865 new_animation.iterate_by(starting_progress);
1868
1869 animation_state.dirty = true;
1870
1871 for existing_animation in animation_state.animations.iter_mut() {
1873 if existing_animation.state == AnimationState::Canceled {
1874 continue;
1875 }
1876
1877 if new_animation.name == existing_animation.name {
1878 existing_animation
1879 .update_from_other(&new_animation, context.current_time_for_animations);
1880 return;
1881 }
1882 }
1883
1884 animation_state.animations.push(new_animation);
1885 }
1886}