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_composition::computed_value::single_value::T as AnimationComposition;
15use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
16use crate::properties::longhands::animation_fill_mode::computed_value::single_value::T as AnimationFillMode;
17use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
18use crate::properties::AnimationDeclarations;
19use crate::properties::{
20 ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
21 PropertyDeclarationIdSet,
22};
23use crate::rule_tree::{CascadeLevel, CascadeOrigin, RuleCascadeFlags};
24use crate::selector_parser::PseudoElement;
25use crate::shared_lock::{Locked, SharedRwLock};
26use crate::style_resolver::StyleResolverForElement;
27use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
28use crate::stylesheets::layer_rule::LayerOrder;
29use crate::values::animated::{Animate, Procedure};
30use crate::values::computed::TimingFunction;
31use crate::values::generics::easing::BeforeFlag;
32use crate::values::specified::TransitionBehavior;
33use crate::Atom;
34use debug_unreachable::debug_unreachable;
35use parking_lot::RwLock;
36use rustc_hash::FxHashMap;
37use servo_arc::Arc;
38use std::fmt;
39
40#[derive(Clone, Debug, MallocSizeOf)]
42pub struct PropertyAnimation {
43 from: AnimationValue,
45
46 to: AnimationValue,
48
49 timing_function: TimingFunction,
51
52 pub duration: f64,
54}
55
56impl PropertyAnimation {
57 pub fn property_id(&self) -> PropertyDeclarationId<'_> {
59 debug_assert_eq!(self.from.id(), self.to.id());
60 self.from.id()
61 }
62
63 fn timing_function_output(&self, progress: f64) -> f64 {
65 let epsilon = 1. / (200. * self.duration);
66 self.timing_function
72 .calculate_output(progress, BeforeFlag::Unset, epsilon)
73 }
74
75 fn calculate_value(&self, progress: f64) -> AnimationValue {
77 let progress = self.timing_function_output(progress);
78 let procedure = Procedure::Interpolate { progress };
79 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
80 if progress < 0.5 {
82 self.from.clone()
83 } else {
84 self.to.clone()
85 }
86 })
87 }
88}
89
90#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
92pub enum AnimationState {
93 Pending,
96 Running,
98 Paused(f64),
101 Finished,
103 Canceled,
105}
106
107impl AnimationState {
108 fn needs_to_be_ticked(&self) -> bool {
110 *self == AnimationState::Running || *self == AnimationState::Pending
111 }
112}
113
114enum IgnoreTransitions {
115 Canceled,
116 CanceledAndFinished,
117}
118
119#[derive(Clone, Debug, MallocSizeOf)]
124pub enum KeyframesIterationState {
125 Infinite(f64),
127 Finite(f64, f64),
129}
130
131#[derive(Debug)]
136struct IntermediateComputedKeyframe {
137 declarations: PropertyDeclarationBlock,
138 timing_function: Option<TimingFunction>,
139 composition: Option<AnimationComposition>,
140 start_percentage: f64,
141}
142
143impl IntermediateComputedKeyframe {
144 fn new(start_percentage: f64) -> Self {
145 IntermediateComputedKeyframe {
146 declarations: PropertyDeclarationBlock::new(),
147 timing_function: None,
148 composition: None,
149 start_percentage,
150 }
151 }
152
153 fn generate_for_keyframes(
156 animation: &KeyframesAnimation,
157 context: &SharedStyleContext,
158 base_style: &ComputedValues,
159 ) -> Vec<Self> {
160 if animation.steps.is_empty() {
161 return vec![];
162 }
163
164 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
165 let mut current_step = IntermediateComputedKeyframe::new(0.);
166 for step in animation.steps.iter() {
167 let start_percentage = step.start_offset.percentage.0 as f64;
168 if start_percentage != current_step.start_percentage {
169 let new_step = IntermediateComputedKeyframe::new(start_percentage);
170 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
171 }
172
173 current_step.update_from_step(step, context, base_style);
174 }
175 intermediate_steps.push(current_step);
176
177 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
180 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
181
182 intermediate_steps
183 }
184
185 fn update_from_step(
186 &mut self,
187 step: &KeyframesStep,
188 context: &SharedStyleContext,
189 base_style: &ComputedValues,
190 ) {
191 let guard = &context.guards.author;
194 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
195 self.timing_function = Some(timing_function.to_computed_value_without_context());
196 }
197
198 if let Some(composition) = step.get_animation_composition(&guard) {
201 self.composition = Some(composition);
202 }
203
204 let block = match step.value {
205 KeyframesStepValue::ComputedValues => return,
206 KeyframesStepValue::Declarations { ref block } => block,
207 };
208
209 let guard = block.read_with(&guard);
212 for declaration in guard.normal_declaration_iter() {
213 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
214 if id == LonghandId::Display {
215 continue;
216 }
217
218 if !id.is_animatable() {
219 continue;
220 }
221 }
222
223 self.declarations.push(
224 declaration.to_physical(base_style.writing_mode),
225 Importance::Normal,
226 );
227 }
228 }
229
230 fn resolve_style<E>(
231 self,
232 element: E,
233 context: &SharedStyleContext,
234 base_style: &Arc<ComputedValues>,
235 resolver: &mut StyleResolverForElement<E>,
236 ) -> Arc<ComputedValues>
237 where
238 E: TElement,
239 {
240 if !self.declarations.any_normal() {
241 return base_style.clone();
242 }
243
244 let document = element.as_node().owner_doc();
245 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
246 let mut important_rules_changed = false;
247 let rule_node = base_style.rules().clone();
248 let new_node = context.stylist.rule_tree().update_rule_at_level(
249 CascadeLevel::new(CascadeOrigin::Animations),
250 LayerOrder::root(),
251 Some(locked_block.borrow_arc()),
252 &rule_node,
253 &context.guards,
254 &mut important_rules_changed,
255 );
256
257 if new_node.is_none() {
258 return base_style.clone();
259 }
260
261 let inputs = CascadeInputs {
262 rules: new_node,
263 visited_rules: base_style.visited_rules().cloned(),
264 flags: base_style.flags.for_cascade_inputs(),
265 included_cascade_flags: RuleCascadeFlags::empty(),
266 };
267 resolver
268 .cascade_style_and_visited_with_default_parents(inputs)
269 .0
270 }
271}
272
273#[derive(Clone, Debug, MallocSizeOf)]
274struct PropertyDeclarationOffsets {
275 preceding_declaration: usize,
278 following_declaration: usize,
281}
282
283#[derive(Clone, Debug, MallocSizeOf)]
284enum AnimationValueOrReference {
285 AnimationValue(AnimationValue),
287 NotDefinedHere(PropertyDeclarationOffsets),
289}
290
291#[derive(Clone, Debug, MallocSizeOf)]
293struct ComputedKeyframe {
294 timing_function: TimingFunction,
297
298 start_percentage: f64,
301
302 values: Box<[AnimationValueOrReference]>,
305}
306
307fn composite_animation_value(
312 underlying_value: &AnimationValue,
313 keyframe_value: AnimationValue,
314 composition: AnimationComposition,
315) -> AnimationValue {
316 let procedure = match composition {
317 AnimationComposition::Replace => return keyframe_value,
318 AnimationComposition::Add => Procedure::Add,
319 AnimationComposition::Accumulate => Procedure::Accumulate { count: 1 },
320 };
321 underlying_value
322 .animate(&keyframe_value, procedure)
323 .unwrap_or(keyframe_value)
324}
325
326#[derive(Clone, Copy, Debug, Default)]
332struct KeyframeOffsetCacheForProperty {
333 last_keyframe_that_defined_property: usize,
339
340 next_keyframe_that_defines_property: Option<usize>,
346}
347
348struct KeyframeDataForProperty<'a> {
349 timing_function: &'a TimingFunction,
352
353 start_percentage: f64,
356
357 value: &'a AnimationValue,
358}
359
360#[derive(Clone, Copy, Debug)]
361enum Direction {
362 Forward,
363 Backward,
364}
365
366impl Direction {
367 fn relative_to_animation_direction(&self, reverse: bool) -> Self {
368 match self {
369 Self::Forward if reverse => Self::Backward,
370 Self::Backward if reverse => Self::Forward,
371 _ => *self,
372 }
373 }
374}
375
376impl Animation {
377 fn next_relevant_keyframe_for_property_in_direction(
382 &self,
383 property_index: usize,
384 keyframe_index: usize,
385 direction: Direction,
386 ) -> Option<KeyframeDataForProperty<'_>> {
387 let relevant_keyframe = &self.computed_steps[keyframe_index];
388 let parameters = match &relevant_keyframe.values[property_index] {
389 AnimationValueOrReference::AnimationValue(animation_value) => KeyframeDataForProperty {
390 timing_function: &relevant_keyframe.timing_function,
391 start_percentage: relevant_keyframe.start_percentage,
392 value: animation_value,
393 },
394 AnimationValueOrReference::NotDefinedHere(offsets) => {
395 let next_relevant_keyframe_index = match direction {
396 Direction::Forward => offsets.following_declaration,
397 Direction::Backward => offsets.preceding_declaration,
398 };
399 let next_relevant_keyframe = &self.computed_steps[next_relevant_keyframe_index];
400 let AnimationValueOrReference::AnimationValue(animation_value) =
401 &next_relevant_keyframe.values[property_index]
402 else {
403 panic!("Referenced keyframe does not set property");
404 };
405
406 KeyframeDataForProperty {
407 timing_function: &next_relevant_keyframe.timing_function,
408 start_percentage: next_relevant_keyframe.start_percentage,
409 value: &animation_value,
410 }
411 },
412 };
413
414 Some(parameters)
415 }
416}
417impl ComputedKeyframe {
418 fn generate_for_keyframes<E>(
419 element: E,
420 animation: &KeyframesAnimation,
421 context: &SharedStyleContext,
422 base_style: &Arc<ComputedValues>,
423 default_timing_function: TimingFunction,
424 default_composition: AnimationComposition,
425 resolver: &mut StyleResolverForElement<E>,
426 animating_properties: PropertyDeclarationIdSet,
427 number_of_animating_properties: usize,
428 ) -> Box<[Self]>
429 where
430 E: TElement,
431 {
432 let animation_values_from_style: Vec<AnimationValue> = animating_properties
433 .iter()
434 .map(|property| {
435 AnimationValue::from_computed_values(property, &**base_style)
436 .expect("Unexpected non-animatable property.")
437 })
438 .collect();
439
440 let intermediate_steps =
441 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
442
443 let mut keyframe_offset_caches: Vec<KeyframeOffsetCacheForProperty> =
447 vec![Default::default(); number_of_animating_properties];
448
449 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
450 let mut remaining_steps = intermediate_steps.into_iter();
451 let mut step_index = 0;
452 while let Some(step) = remaining_steps.next() {
453 let start_percentage = step.start_percentage;
454 let properties_changed_in_step = step.declarations.property_ids().clone();
455 let timing_function = step
456 .timing_function
457 .clone()
458 .unwrap_or_else(|| default_timing_function.clone());
459 let composition = step.composition.unwrap_or(default_composition);
460 let step_style = step.resolve_style(element, context, base_style, resolver);
461
462 let values: Box<[_]> = {
463 animating_properties
466 .iter()
467 .enumerate()
468 .map(|(property_index, property_declaration)| {
469 let keyframe_offset_cache = &mut keyframe_offset_caches[property_index];
470 if properties_changed_in_step.contains(property_declaration) {
471 keyframe_offset_cache.last_keyframe_that_defined_property = step_index;
472 let animation_value = AnimationValue::from_computed_values(
473 property_declaration,
474 &step_style,
475 )
476 .unwrap();
477 let animation_value = composite_animation_value(
478 &animation_values_from_style[property_index],
479 animation_value,
480 composition,
481 );
482 return AnimationValueOrReference::AnimationValue(animation_value);
483 }
484
485 if step_index == 0 || remaining_steps.as_slice().is_empty() {
491 return AnimationValueOrReference::AnimationValue(
492 animation_values_from_style[property_index].clone(),
493 );
494 }
495
496 let preceding_declaration =
503 keyframe_offset_cache.last_keyframe_that_defined_property;
504 let following_declaration = keyframe_offset_cache
505 .next_keyframe_that_defines_property
506 .filter(|offset| *offset > step_index)
507 .unwrap_or_else(|| {
508 let relative_offset = remaining_steps
509 .as_slice()
510 .iter()
511 .position(|step| {
512 step.declarations.contains(property_declaration)
513 })
514 .unwrap_or(remaining_steps.as_slice().len() - 1);
515 let absolute_offset = step_index + 1 + relative_offset;
516
517 keyframe_offset_cache.next_keyframe_that_defines_property =
518 Some(absolute_offset);
519 absolute_offset
520 });
521
522 AnimationValueOrReference::NotDefinedHere(PropertyDeclarationOffsets {
523 preceding_declaration,
524 following_declaration,
525 })
526 })
527 .collect()
528 };
529 debug_assert_eq!(values.len(), number_of_animating_properties);
530
531 computed_steps.push(ComputedKeyframe {
532 timing_function,
533 start_percentage,
534 values,
535 });
536
537 step_index += 1;
538 }
539
540 debug_assert!(computed_steps.first().is_none_or(|first_step| {
543 first_step
544 .values
545 .iter()
546 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
547 }));
548 debug_assert!(computed_steps.last().is_none_or(|first_step| {
549 first_step
550 .values
551 .iter()
552 .all(|value| matches!(value, AnimationValueOrReference::AnimationValue(_)))
553 }));
554
555 computed_steps.into_boxed_slice()
556 }
557}
558
559#[derive(Clone, MallocSizeOf)]
561pub struct Animation {
562 pub name: Atom,
564
565 properties_changed: PropertyDeclarationIdSet,
567
568 computed_steps: Box<[ComputedKeyframe]>,
570
571 pub started_at: f64,
574
575 pub duration: f64,
577
578 pub delay: f64,
580
581 pub fill_mode: AnimationFillMode,
583
584 pub iteration_state: KeyframesIterationState,
586
587 pub state: AnimationState,
589
590 pub direction: AnimationDirection,
592
593 pub current_direction: AnimationDirection,
595
596 pub number_of_animating_properties: usize,
598
599 pub is_new: bool,
602}
603
604impl Animation {
605 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
607 let new_ui = new_style.get_ui();
608 let index = new_ui
609 .animation_name_iter()
610 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
611 let index = match index {
612 Some(index) => index,
613 None => return true,
614 };
615
616 new_ui.animation_duration_mod(index).seconds() == 0.
617 }
618
619 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
623 if !self.iteration_over(time) {
624 return false;
625 }
626
627 if self.state != AnimationState::Running {
629 return false;
630 }
631
632 self.iterate_by(1.) == 1.
633 }
634
635 fn iterate_by(&mut self, n: f64) -> f64 {
639 let n = n.trunc().min(self.remaining_iterations().ceil() - 1.0);
640 if n < 1. {
641 return 0.;
642 }
643
644 match self.iteration_state {
645 KeyframesIterationState::Finite(ref mut current, max) => {
646 *current = (*current + n).min(max);
647 },
648 KeyframesIterationState::Infinite(ref mut current) => {
649 *current += n;
650 },
651 }
652
653 if let AnimationState::Paused(ref mut progress) = self.state {
654 debug_assert!(*progress >= n);
655 *progress -= n;
656 }
657
658 self.started_at += self.duration * n;
660 match self.direction {
661 AnimationDirection::Alternate | AnimationDirection::AlternateReverse
662 if n % 2. == 1.0 =>
663 {
664 self.current_direction = match self.current_direction {
665 AnimationDirection::Normal => AnimationDirection::Reverse,
666 AnimationDirection::Reverse => AnimationDirection::Normal,
667 _ => unreachable!(
668 "Current animation direction can only be `normal` or `reverse`."
669 ),
670 };
671 },
672 _ => {},
673 }
674
675 n
676 }
677
678 fn remaining_iterations(&self) -> f64 {
679 match self.iteration_state {
680 KeyframesIterationState::Finite(current, max) => max - current,
681 KeyframesIterationState::Infinite(_) => f64::INFINITY,
682 }
683 }
684
685 pub fn current_iteration_end_progress(&self) -> f64 {
690 self.remaining_iterations().min(1.)
691 }
692
693 pub fn current_iteration_duration(&self) -> f64 {
696 self.current_iteration_end_progress() * self.duration
697 }
698
699 fn iteration_over(&self, time: f64) -> bool {
702 time > (self.started_at + self.current_iteration_duration())
703 }
704
705 fn on_last_iteration(&self) -> bool {
707 self.remaining_iterations() <= 1.
708 }
709
710 pub fn has_ended(&self, time: f64) -> bool {
714 if !self.on_last_iteration() {
715 return false;
716 }
717
718 let progress = match self.state {
719 AnimationState::Finished => return true,
720 AnimationState::Paused(progress) => progress,
721 AnimationState::Running => (time - self.started_at) / self.duration,
722 AnimationState::Pending | AnimationState::Canceled => return false,
723 };
724
725 progress >= self.current_iteration_end_progress()
726 }
727
728 pub fn update_from_other(&mut self, other: &Self, now: f64) {
736 use self::AnimationState::*;
737
738 debug!(
739 "KeyframesAnimationState::update_from_other({:?}, {:?})",
740 self, other
741 );
742
743 let old_started_at = self.started_at;
746 let old_delay = self.delay;
747 let old_duration = self.duration;
748 let old_direction = self.current_direction;
749 let old_state = self.state.clone();
750 let old_iteration_state = self.iteration_state.clone();
751
752 *self = other.clone();
753 self.current_direction = old_direction;
754
755 if self.delay != old_delay {
756 self.started_at = old_started_at + (self.delay - old_delay);
759
760 match old_state {
761 Paused(old_progress) => {
762 let mut progress = old_progress + (old_delay - self.delay) / self.duration;
763 progress -= self.iterate_by(progress);
764 self.state = Paused(progress);
765 },
766 Finished => {
767 if self.has_ended(now) {
768 self.state = Finished;
769 } else if self.started_at <= now {
770 self.state = Running;
771 } else {
772 self.state = Pending;
773 }
774 },
775 Canceled | Pending | Running => {
776 let new_starting_progress = (now - self.started_at) / self.duration;
778 match self.iteration_state {
779 KeyframesIterationState::Finite(ref mut current, _) => *current = 0.0,
780 _ => {},
781 }
782 if let AnimationState::Paused(starting_progress) = &mut self.state {
783 *starting_progress = new_starting_progress;
784 }
785 self.iterate_by(new_starting_progress);
786 },
787 }
788
789 if self.state == Pending && self.started_at <= now {
791 self.state = Running;
792 }
793 } else {
794 self.started_at = old_started_at;
795
796 match (&mut self.iteration_state, old_iteration_state) {
800 (
801 &mut KeyframesIterationState::Finite(ref mut iters, _),
802 KeyframesIterationState::Finite(old_iters, _),
803 ) => *iters = old_iters,
804 _ => {},
805 }
806
807 let new_state = std::mem::replace(&mut self.state, Running);
810 if old_state == Finished && self.has_ended(now) {
811 self.state = Finished;
812 } else {
813 self.state = new_state;
814 }
815
816 match (&mut self.state, &old_state) {
823 (&mut Pending, &Paused(progress)) => {
824 self.started_at = now - (self.duration * progress);
825 },
826 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
827 (&mut Paused(ref mut progress), &Running) => {
828 *progress = (now - old_started_at) / old_duration
829 },
830 _ => {},
831 }
832
833 if self.state == Pending && self.started_at <= now && old_state != Pending {
836 self.state = Running;
837 }
838 }
839 }
840
841 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
844 if self.computed_steps.is_empty() {
845 return;
847 }
848
849 let progress = match self.state {
852 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
853 (now - self.started_at) / self.duration
854 },
855 AnimationState::Paused(progress) => progress,
856 AnimationState::Canceled => return,
857 };
858
859 if progress < 0.
860 && self.fill_mode != AnimationFillMode::Backwards
861 && self.fill_mode != AnimationFillMode::Both
862 {
863 return;
864 }
865 if self.has_ended(now)
866 && self.fill_mode != AnimationFillMode::Forwards
867 && self.fill_mode != AnimationFillMode::Both
868 {
869 return;
870 }
871
872 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
875 for value_or_reference in keyframe.values.iter() {
876 let AnimationValueOrReference::AnimationValue(value) = value_or_reference else {
877 unreachable!("First or last keyframes define all properties");
878 };
879 map.insert(value.id().to_owned(), value.clone());
880 }
881 };
882
883 if progress < 0.0 {
885 if let Some(keyframe) = match self.current_direction {
886 AnimationDirection::Normal => self.computed_steps.first(),
887 AnimationDirection::Reverse => self.computed_steps.last(),
888 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
889 } {
890 add_declarations_to_map(keyframe);
891 }
892 return;
893 }
894
895 let total_progress = progress.min(self.current_iteration_end_progress()).max(0.0);
897
898 if total_progress == 1.0 {
900 let keyframe = match self.current_direction {
901 AnimationDirection::Normal => self.computed_steps.last().unwrap(),
902 AnimationDirection::Reverse => self.computed_steps.first().unwrap(),
903 _ => unreachable!("Current animation direction can only be `normal` or `reverse`."),
904 };
905 add_declarations_to_map(keyframe);
906 return;
907 }
908
909 let next_keyframe_index;
911 let prev_keyframe_index;
912 let num_steps = self.computed_steps.len();
913 match self.current_direction {
914 AnimationDirection::Normal => {
915 next_keyframe_index = self
916 .computed_steps
917 .iter()
918 .position(|step| total_progress < step.start_percentage);
919 prev_keyframe_index = next_keyframe_index
920 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
921 .unwrap_or(0);
922 },
923 AnimationDirection::Reverse => {
924 next_keyframe_index = self
925 .computed_steps
926 .iter()
927 .rev()
928 .position(|step| total_progress <= 1. - step.start_percentage)
929 .map(|pos| num_steps - pos - 1);
930 prev_keyframe_index = next_keyframe_index
931 .and_then(|pos| {
932 if pos != num_steps - 1 {
933 Some(pos + 1)
934 } else {
935 None
936 }
937 })
938 .unwrap_or(num_steps - 1)
939 },
940 _ => unreachable!(),
941 }
942
943 debug!(
944 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
945 prev_keyframe_index, next_keyframe_index
946 );
947
948 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
949 let Some(next_keyframe_index) = next_keyframe_index else {
950 unsafe {
951 debug_unreachable!(
952 "next_keyframe_index should always be Some: \
953 total_progress is in [0, 1) at this point. \
954 Normal direction: keyframe with start_percentage 1.0 always satisfies. \
955 Reverse direction: keyframe with start_percentage 0.0 always satisfies."
956 );
957 }
958 };
959
960 if prev_keyframe_index == next_keyframe_index {
963 add_declarations_to_map(&prev_keyframe);
964 return;
965 }
966
967 let reversed = self.current_direction != AnimationDirection::Normal;
969 for property_index in 0..self.number_of_animating_properties {
970 let Some(previous_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
971 property_index,
972 prev_keyframe_index,
973 Direction::Backward.relative_to_animation_direction(reversed),
974 ) else {
975 continue;
977 };
978
979 let Some(next_keyframe) = self.next_relevant_keyframe_for_property_in_direction(
980 property_index,
981 next_keyframe_index,
982 Direction::Forward.relative_to_animation_direction(reversed),
983 ) else {
984 map.insert(
986 previous_keyframe.value.id().to_owned(),
987 previous_keyframe.value.clone(),
988 );
989 continue;
990 };
991
992 let percentage_between_keyframes =
993 (next_keyframe.start_percentage - previous_keyframe.start_percentage).abs();
994 let duration_between_keyframes = percentage_between_keyframes * self.duration;
995 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
996 AnimationDirection::Normal => previous_keyframe.start_percentage,
997 AnimationDirection::Reverse => 1. - previous_keyframe.start_percentage,
998 _ => unreachable!(),
999 };
1000 let progress_between_keyframes = (total_progress
1001 - direction_aware_prev_keyframe_start_percentage)
1002 / percentage_between_keyframes;
1003 let animation = PropertyAnimation {
1004 from: previous_keyframe.value.clone(),
1005 to: next_keyframe.value.clone(),
1006 timing_function: previous_keyframe.timing_function.clone(),
1007 duration: duration_between_keyframes,
1008 };
1009
1010 let value = animation.calculate_value(progress_between_keyframes);
1011 map.insert(value.id().to_owned(), value);
1012 }
1013 }
1014}
1015
1016impl fmt::Debug for Animation {
1017 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1018 f.debug_struct("Animation")
1019 .field("name", &self.name)
1020 .field("started_at", &self.started_at)
1021 .field("duration", &self.duration)
1022 .field("delay", &self.delay)
1023 .field("iteration_state", &self.iteration_state)
1024 .field("state", &self.state)
1025 .field("direction", &self.direction)
1026 .field("current_direction", &self.current_direction)
1027 .field("cascade_style", &())
1028 .finish()
1029 }
1030}
1031
1032#[derive(Clone, Debug, MallocSizeOf)]
1034pub struct Transition {
1035 pub start_time: f64,
1038
1039 pub delay: f64,
1041
1042 pub property_animation: PropertyAnimation,
1044
1045 pub state: AnimationState,
1047
1048 pub is_new: bool,
1051
1052 pub reversing_adjusted_start_value: AnimationValue,
1055
1056 pub reversing_shortening_factor: f64,
1059}
1060
1061impl Transition {
1062 fn new(
1063 start_time: f64,
1064 delay: f64,
1065 duration: f64,
1066 from: AnimationValue,
1067 to: AnimationValue,
1068 timing_function: &TimingFunction,
1069 ) -> Self {
1070 let property_animation = PropertyAnimation {
1071 from: from.clone(),
1072 to,
1073 timing_function: timing_function.clone(),
1074 duration,
1075 };
1076 Self {
1077 start_time,
1078 delay,
1079 property_animation,
1080 state: AnimationState::Pending,
1081 is_new: true,
1082 reversing_adjusted_start_value: from,
1083 reversing_shortening_factor: 1.0,
1084 }
1085 }
1086
1087 fn update_for_possibly_reversed_transition(
1088 &mut self,
1089 replaced_transition: &Transition,
1090 delay: f64,
1091 now: f64,
1092 ) {
1093 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
1102 return;
1103 }
1104
1105 let replaced_animation = &replaced_transition.property_animation;
1107 self.reversing_adjusted_start_value = replaced_animation.to.clone();
1108
1109 let transition_progress = ((now - replaced_transition.start_time)
1116 / (replaced_transition.property_animation.duration))
1117 .min(1.0)
1118 .max(0.0);
1119 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
1120 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
1121 self.reversing_shortening_factor = ((timing_function_output
1122 * old_reversing_shortening_factor)
1123 + (1.0 - old_reversing_shortening_factor))
1124 .abs()
1125 .min(1.0)
1126 .max(0.0);
1127
1128 self.start_time = if delay >= 0. {
1134 now + delay
1135 } else {
1136 now + (self.reversing_shortening_factor * delay)
1137 };
1138
1139 self.property_animation.duration *= self.reversing_shortening_factor;
1142
1143 let procedure = Procedure::Interpolate {
1146 progress: timing_function_output,
1147 };
1148 match replaced_animation
1149 .from
1150 .animate(&replaced_animation.to, procedure)
1151 {
1152 Ok(new_start) => self.property_animation.from = new_start,
1153 Err(..) => {},
1154 }
1155 }
1156
1157 pub fn has_ended(&self, time: f64) -> bool {
1161 time >= self.start_time + (self.property_animation.duration)
1162 }
1163
1164 pub fn calculate_value(&self, time: f64) -> AnimationValue {
1166 let progress = if time < self.start_time {
1167 0.0
1168 } else if self.property_animation.duration == 0.0 {
1169 1.0
1170 } else {
1171 ((time - self.start_time) / self.property_animation.duration).clamp(0.0, 1.0)
1172 };
1173
1174 self.property_animation.calculate_value(progress)
1175 }
1176}
1177
1178#[derive(Debug, Default, MallocSizeOf)]
1180pub struct ElementAnimationSet {
1181 pub animations: Vec<Animation>,
1183
1184 pub transitions: Vec<Transition>,
1186
1187 pub dirty: bool,
1190}
1191
1192impl ElementAnimationSet {
1193 pub fn cancel_all_animations(&mut self) {
1196 self.dirty = !self.animations.is_empty();
1197 for animation in self.animations.iter_mut() {
1198 animation.state = AnimationState::Canceled;
1199 }
1200 self.cancel_active_transitions();
1201 }
1202
1203 fn cancel_active_transitions(&mut self) {
1204 for transition in self.transitions.iter_mut() {
1205 if transition.state != AnimationState::Finished {
1206 self.dirty = true;
1207 transition.state = AnimationState::Canceled;
1208 }
1209 }
1210 }
1211
1212 pub fn apply_active_animations(
1214 &self,
1215 context: &SharedStyleContext,
1216 style: &mut Arc<ComputedValues>,
1217 ) {
1218 let now = context.current_time_for_animations;
1219 let mutable_style = Arc::make_mut(style);
1220 if let Some(map) = self.get_value_map_for_active_animations(now) {
1221 for value in map.values() {
1222 value.set_in_style_for_servo(mutable_style, context);
1223 }
1224 }
1225
1226 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
1227 for value in map.values() {
1228 value.set_in_style_for_servo(mutable_style, context);
1229 }
1230 }
1231 }
1232
1233 pub fn clear_canceled_animations(&mut self) {
1235 self.animations
1236 .retain(|animation| animation.state != AnimationState::Canceled);
1237 self.transitions
1238 .retain(|animation| animation.state != AnimationState::Canceled);
1239 }
1240
1241 pub fn is_empty(&self) -> bool {
1244 self.animations.is_empty() && self.transitions.is_empty()
1245 }
1246
1247 pub fn needs_animation_ticks(&self) -> bool {
1250 self.animations
1251 .iter()
1252 .any(|animation| animation.state.needs_to_be_ticked())
1253 || self
1254 .transitions
1255 .iter()
1256 .any(|transition| transition.state.needs_to_be_ticked())
1257 }
1258
1259 pub fn running_animation_and_transition_count(&self) -> usize {
1261 self.animations
1262 .iter()
1263 .filter(|animation| animation.state.needs_to_be_ticked())
1264 .count()
1265 + self
1266 .transitions
1267 .iter()
1268 .filter(|transition| transition.state.needs_to_be_ticked())
1269 .count()
1270 }
1271
1272 pub fn has_active_animation(&self) -> bool {
1274 self.animations
1275 .iter()
1276 .any(|animation| animation.state != AnimationState::Canceled)
1277 }
1278
1279 pub fn has_active_transition(&self) -> bool {
1281 self.transitions
1282 .iter()
1283 .any(|transition| transition.state != AnimationState::Canceled)
1284 }
1285
1286 pub fn update_animations_for_new_style<E>(
1289 &mut self,
1290 element: E,
1291 context: &SharedStyleContext,
1292 new_style: &Arc<ComputedValues>,
1293 resolver: &mut StyleResolverForElement<E>,
1294 ) where
1295 E: TElement,
1296 {
1297 for animation in self.animations.iter_mut() {
1298 if animation.is_cancelled_in_new_style(new_style) {
1299 animation.state = AnimationState::Canceled;
1300 }
1301 }
1302
1303 maybe_start_animations(element, &context, &new_style, self, resolver);
1304 }
1305
1306 pub fn update_transitions_for_new_style(
1309 &mut self,
1310 might_need_transitions_update: bool,
1311 context: &SharedStyleContext,
1312 old_style: Option<&Arc<ComputedValues>>,
1313 after_change_style: &Arc<ComputedValues>,
1314 ) {
1315 let mut before_change_style = match old_style {
1318 Some(old_style) => Arc::clone(old_style),
1319 None => return,
1320 };
1321
1322 if after_change_style.get_box().clone_display().is_none() {
1324 self.cancel_active_transitions();
1325 return;
1326 }
1327
1328 if !might_need_transitions_update {
1329 return;
1330 }
1331
1332 if self.has_active_transition() || self.has_active_animation() {
1334 self.apply_active_animations(context, &mut before_change_style);
1335 }
1336
1337 let transitioning_properties = start_transitions_if_applicable(
1338 context,
1339 &before_change_style,
1340 after_change_style,
1341 self,
1342 );
1343
1344 for transition in self.transitions.iter_mut() {
1357 if transition.state == AnimationState::Finished
1358 || transition.state == AnimationState::Canceled
1359 {
1360 continue;
1361 }
1362 if transitioning_properties.contains(transition.property_animation.property_id()) {
1363 continue;
1364 }
1365 transition.state = AnimationState::Canceled;
1366 self.dirty = true;
1367 }
1368 }
1369
1370 fn start_transition_if_applicable(
1371 &mut self,
1372 context: &SharedStyleContext,
1373 property_declaration_id: &PropertyDeclarationId,
1374 index: usize,
1375 old_style: &ComputedValues,
1376 new_style: &Arc<ComputedValues>,
1377 ) {
1378 let style = new_style.get_ui();
1379 let allow_discrete =
1380 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1381
1382 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1384 else {
1385 return;
1386 };
1387 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1388 else {
1389 return;
1390 };
1391
1392 let timing_function = style.transition_timing_function_mod(index);
1393 let duration = style.transition_duration_mod(index).seconds() as f64;
1394 let delay = style.transition_delay_mod(index).seconds() as f64;
1395 let now = context.current_time_for_animations;
1396 let transitionable = property_declaration_id.is_animatable()
1397 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1398 && (allow_discrete || from.interpolable_with(&to));
1399
1400 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1401 transition.property_animation.property_id() == *property_declaration_id
1402 });
1403
1404 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1419 transition.state != AnimationState::Finished
1420 && transition.state != AnimationState::Canceled
1421 });
1422 let no_completed_transition_or_end_values_differ =
1423 existing_transition.as_ref().is_none_or(|transition| {
1424 transition.state != AnimationState::Finished
1425 || transition.property_animation.to != to
1426 });
1427 if !has_running_transition
1428 && from != to
1429 && transitionable
1430 && no_completed_transition_or_end_values_differ
1431 && (duration + delay > 0.0)
1432 {
1433 self.transitions.push(Transition::new(
1444 now + delay, delay,
1446 duration,
1447 from,
1448 to,
1449 &timing_function,
1450 ));
1451 self.dirty = true;
1452 return;
1453 }
1454
1455 let Some(existing_transition) = existing_transition.as_mut() else {
1478 return;
1479 };
1480
1481 if has_running_transition && existing_transition.property_animation.to != to {
1486 let current_value = existing_transition.calculate_value(now);
1491 let transitionable_from_current_value =
1492 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1493 if current_value == to || !transitionable_from_current_value {
1494 existing_transition.state = AnimationState::Canceled;
1495 self.dirty = true;
1496 return;
1497 }
1498
1499 if duration + delay <= 0.0 {
1505 existing_transition.state = AnimationState::Canceled;
1506 self.dirty = true;
1507 return;
1508 }
1509
1510 if existing_transition.reversing_adjusted_start_value == to {
1516 existing_transition.state = AnimationState::Canceled;
1517
1518 let mut transition = Transition::new(
1519 now + delay, delay,
1521 duration,
1522 from,
1523 to,
1524 &timing_function,
1525 );
1526
1527 transition.update_for_possibly_reversed_transition(
1530 &existing_transition,
1531 delay,
1532 now,
1533 );
1534
1535 self.transitions.push(transition);
1536 self.dirty = true;
1537 return;
1538 }
1539
1540 existing_transition.state = AnimationState::Canceled;
1549 self.transitions.push(Transition::new(
1550 now + delay, delay,
1552 duration,
1553 current_value,
1554 to,
1555 &timing_function,
1556 ));
1557 self.dirty = true;
1558 }
1559 }
1560
1561 fn get_value_map_for_transitions(
1565 &self,
1566 now: f64,
1567 ignore_transitions: IgnoreTransitions,
1568 ) -> Option<AnimationValueMap> {
1569 if !self.has_active_transition() {
1570 return None;
1571 }
1572
1573 let mut map =
1574 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1575 for transition in &self.transitions {
1576 match ignore_transitions {
1577 IgnoreTransitions::Canceled => {
1578 if transition.state == AnimationState::Canceled {
1579 continue;
1580 }
1581 },
1582 IgnoreTransitions::CanceledAndFinished => {
1583 if transition.state == AnimationState::Canceled
1584 || transition.state == AnimationState::Finished
1585 {
1586 continue;
1587 }
1588 },
1589 }
1590
1591 let value = transition.calculate_value(now);
1592 map.insert(value.id().to_owned(), value);
1593 }
1594
1595 Some(map)
1596 }
1597
1598 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1601 if !self.has_active_animation() {
1602 return None;
1603 }
1604
1605 let mut map = Default::default();
1606 for animation in &self.animations {
1607 animation.get_property_declaration_at_time(now, &mut map);
1608 }
1609
1610 Some(map)
1611 }
1612}
1613
1614#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1615pub struct AnimationSetKey {
1617 pub node: OpaqueNode,
1619 pub pseudo_element: Option<PseudoElement>,
1622}
1623
1624impl AnimationSetKey {
1625 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1627 AnimationSetKey {
1628 node,
1629 pseudo_element,
1630 }
1631 }
1632
1633 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1635 AnimationSetKey {
1636 node,
1637 pseudo_element: None,
1638 }
1639 }
1640
1641 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1643 AnimationSetKey {
1644 node,
1645 pseudo_element: Some(pseudo_element),
1646 }
1647 }
1648}
1649
1650#[derive(Clone, Debug, Default, MallocSizeOf)]
1651pub struct DocumentAnimationSet {
1653 #[ignore_malloc_size_of = "Arc is hard"]
1655 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1656}
1657
1658impl DocumentAnimationSet {
1659 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1661 self.sets
1662 .read()
1663 .get(key)
1664 .map_or(false, |set| set.has_active_animation())
1665 }
1666
1667 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1669 self.sets
1670 .read()
1671 .get(key)
1672 .map_or(false, |set| set.has_active_transition())
1673 }
1674
1675 pub fn get_animation_declarations(
1678 &self,
1679 key: &AnimationSetKey,
1680 time: f64,
1681 shared_lock: &SharedRwLock,
1682 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1683 self.sets
1684 .read()
1685 .get(key)
1686 .and_then(|set| set.get_value_map_for_active_animations(time))
1687 .map(|map| {
1688 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1689 Arc::new(shared_lock.wrap(block))
1690 })
1691 }
1692
1693 pub fn get_transition_declarations(
1696 &self,
1697 key: &AnimationSetKey,
1698 time: f64,
1699 shared_lock: &SharedRwLock,
1700 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1701 self.sets
1702 .read()
1703 .get(key)
1704 .and_then(|set| {
1705 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1706 })
1707 .map(|map| {
1708 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1709 Arc::new(shared_lock.wrap(block))
1710 })
1711 }
1712
1713 pub fn get_all_declarations(
1716 &self,
1717 key: &AnimationSetKey,
1718 time: f64,
1719 shared_lock: &SharedRwLock,
1720 ) -> AnimationDeclarations {
1721 let sets = self.sets.read();
1722 let set = match sets.get(key) {
1723 Some(set) => set,
1724 None => return Default::default(),
1725 };
1726
1727 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1728 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1729 Arc::new(shared_lock.wrap(block))
1730 });
1731 let transitions = set
1732 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1733 .map(|map| {
1734 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1735 Arc::new(shared_lock.wrap(block))
1736 });
1737 AnimationDeclarations {
1738 animations,
1739 transitions,
1740 }
1741 }
1742
1743 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1745 if let Some(set) = self.sets.write().get_mut(key) {
1746 set.cancel_all_animations();
1747 }
1748 }
1749}
1750
1751pub fn start_transitions_if_applicable(
1754 context: &SharedStyleContext,
1755 old_style: &ComputedValues,
1756 new_style: &Arc<ComputedValues>,
1757 animation_state: &mut ElementAnimationSet,
1758) -> PropertyDeclarationIdSet {
1759 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1774 transition_properties.reverse();
1775
1776 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1777 for transition in transition_properties {
1778 let physical_property = transition
1779 .property
1780 .as_borrowed()
1781 .to_physical(new_style.writing_mode);
1782 if properties_that_transition.contains(physical_property) {
1783 continue;
1784 }
1785
1786 properties_that_transition.insert(physical_property);
1787 animation_state.start_transition_if_applicable(
1788 context,
1789 &physical_property,
1790 transition.index,
1791 old_style,
1792 new_style,
1793 );
1794 }
1795
1796 properties_that_transition
1797}
1798
1799pub fn maybe_start_animations<E>(
1802 element: E,
1803 context: &SharedStyleContext,
1804 new_style: &Arc<ComputedValues>,
1805 animation_state: &mut ElementAnimationSet,
1806 resolver: &mut StyleResolverForElement<E>,
1807) where
1808 E: TElement,
1809{
1810 let style = new_style.get_ui();
1811 for (i, name) in style.animation_name_iter().enumerate() {
1812 let name = match name.as_atom() {
1813 Some(atom) => atom,
1814 None => continue,
1815 };
1816
1817 debug!("maybe_start_animations: name={}", name);
1818 let duration = style.animation_duration_mod(i).seconds() as f64;
1819 if duration == 0. {
1820 continue;
1821 }
1822
1823 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1824 continue;
1825 };
1826
1827 debug!("maybe_start_animations: animation {} found", name);
1828
1829 let delay = style.animation_delay_mod(i).seconds() as f64;
1833
1834 let iteration_count = style.animation_iteration_count_mod(i);
1835 let iteration_state = if iteration_count.0.is_infinite() {
1836 KeyframesIterationState::Infinite(0.0)
1837 } else {
1838 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1839 };
1840
1841 let animation_direction = style.animation_direction_mod(i);
1842
1843 let initial_direction = match animation_direction {
1844 AnimationDirection::Normal | AnimationDirection::Alternate => {
1845 AnimationDirection::Normal
1846 },
1847 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1848 AnimationDirection::Reverse
1849 },
1850 };
1851
1852 let now = context.current_time_for_animations;
1853 let started_at = now + delay;
1854 let starting_progress = (now - started_at) / duration;
1855 let state = match style.animation_play_state_mod(i) {
1856 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1857 AnimationPlayState::Running => AnimationState::Pending,
1858 };
1859
1860 let mut animating_properties = PropertyDeclarationIdSet::default();
1864 let mut number_of_animating_properties = 0;
1865 for property in keyframe_animation.properties_changed.iter() {
1866 debug_assert!(property.is_animatable());
1867
1868 if animating_properties.insert(property.to_physical(new_style.writing_mode)) {
1869 number_of_animating_properties += 1;
1870 }
1871 }
1872
1873 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1874 element,
1875 &keyframe_animation,
1876 context,
1877 new_style,
1878 style.animation_timing_function_mod(i),
1879 style.animation_composition_mod(i),
1880 resolver,
1881 animating_properties,
1882 number_of_animating_properties,
1883 );
1884
1885 let mut new_animation = Animation {
1886 name: name.clone(),
1887 properties_changed: keyframe_animation.properties_changed.clone(),
1888 computed_steps,
1889 started_at,
1890 duration,
1891 fill_mode: style.animation_fill_mode_mod(i),
1892 delay,
1893 iteration_state,
1894 state,
1895 direction: animation_direction,
1896 current_direction: initial_direction,
1897 number_of_animating_properties,
1898 is_new: true,
1899 };
1900
1901 new_animation.iterate_by(starting_progress);
1904
1905 animation_state.dirty = true;
1906
1907 for existing_animation in animation_state.animations.iter_mut() {
1909 if existing_animation.state == AnimationState::Canceled {
1910 continue;
1911 }
1912
1913 if new_animation.name == existing_animation.name {
1914 existing_animation
1915 .update_from_other(&new_animation, context.current_time_for_animations);
1916 return;
1917 }
1918 }
1919
1920 animation_state.animations.push(new_animation);
1921 }
1922}