1use crate::context::{CascadeInputs, SharedStyleContext};
11use crate::derives::*;
12use crate::dom::{OpaqueNode, TDocument, TElement, TNode};
13use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
14use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
15use crate::properties::longhands::animation_fill_mode::computed_value::single_value::T as AnimationFillMode;
16use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
17use crate::properties::AnimationDeclarations;
18use crate::properties::{
19 ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
20 PropertyDeclarationIdSet,
21};
22use crate::rule_tree::{CascadeLevel, CascadeOrigin, RuleCascadeFlags};
23use crate::selector_parser::PseudoElement;
24use crate::shared_lock::{Locked, SharedRwLock};
25use crate::style_resolver::StyleResolverForElement;
26use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
27use crate::stylesheets::layer_rule::LayerOrder;
28use crate::values::animated::{Animate, Procedure};
29use crate::values::computed::TimingFunction;
30use crate::values::generics::easing::BeforeFlag;
31use crate::values::specified::TransitionBehavior;
32use crate::Atom;
33use parking_lot::RwLock;
34use rustc_hash::FxHashMap;
35use servo_arc::Arc;
36use std::fmt;
37
38#[derive(Clone, Debug, MallocSizeOf)]
40pub struct PropertyAnimation {
41 from: AnimationValue,
43
44 to: AnimationValue,
46
47 timing_function: TimingFunction,
49
50 pub duration: f64,
52}
53
54impl PropertyAnimation {
55 pub fn property_id(&self) -> PropertyDeclarationId<'_> {
57 debug_assert_eq!(self.from.id(), self.to.id());
58 self.from.id()
59 }
60
61 fn timing_function_output(&self, progress: f64) -> f64 {
63 let epsilon = 1. / (200. * self.duration);
64 self.timing_function
70 .calculate_output(progress, BeforeFlag::Unset, epsilon)
71 }
72
73 fn calculate_value(&self, progress: f64) -> AnimationValue {
75 let progress = self.timing_function_output(progress);
76 let procedure = Procedure::Interpolate { progress };
77 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
78 if progress < 0.5 {
80 self.from.clone()
81 } else {
82 self.to.clone()
83 }
84 })
85 }
86}
87
88#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
90pub enum AnimationState {
91 Pending,
94 Running,
96 Paused(f64),
99 Finished,
101 Canceled,
103}
104
105impl AnimationState {
106 fn needs_to_be_ticked(&self) -> bool {
108 *self == AnimationState::Running || *self == AnimationState::Pending
109 }
110}
111
112enum IgnoreTransitions {
113 Canceled,
114 CanceledAndFinished,
115}
116
117#[derive(Clone, Debug, MallocSizeOf)]
122pub enum KeyframesIterationState {
123 Infinite(f64),
125 Finite(f64, f64),
127}
128
129struct IntermediateComputedKeyframe {
134 declarations: PropertyDeclarationBlock,
135 timing_function: Option<TimingFunction>,
136 start_percentage: f32,
137}
138
139impl IntermediateComputedKeyframe {
140 fn new(start_percentage: f32) -> Self {
141 IntermediateComputedKeyframe {
142 declarations: PropertyDeclarationBlock::new(),
143 timing_function: None,
144 start_percentage,
145 }
146 }
147
148 fn generate_for_keyframes(
151 animation: &KeyframesAnimation,
152 context: &SharedStyleContext,
153 base_style: &ComputedValues,
154 ) -> Vec<Self> {
155 if animation.steps.is_empty() {
156 return vec![];
157 }
158
159 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
160 let mut current_step = IntermediateComputedKeyframe::new(0.);
161 for step in animation.steps.iter() {
162 let start_percentage = step.start_percentage.0;
163 if start_percentage != current_step.start_percentage {
164 let new_step = IntermediateComputedKeyframe::new(start_percentage);
165 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
166 }
167
168 current_step.update_from_step(step, context, base_style);
169 }
170 intermediate_steps.push(current_step);
171
172 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
175 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
176
177 intermediate_steps
178 }
179
180 fn update_from_step(
181 &mut self,
182 step: &KeyframesStep,
183 context: &SharedStyleContext,
184 base_style: &ComputedValues,
185 ) {
186 let guard = &context.guards.author;
189 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
190 self.timing_function = Some(timing_function.to_computed_value_without_context());
191 }
192
193 let block = match step.value {
194 KeyframesStepValue::ComputedValues => return,
195 KeyframesStepValue::Declarations { ref block } => block,
196 };
197
198 let guard = block.read_with(&guard);
201 for declaration in guard.normal_declaration_iter() {
202 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
203 if id == LonghandId::Display {
204 continue;
205 }
206
207 if !id.is_animatable() {
208 continue;
209 }
210 }
211
212 self.declarations.push(
213 declaration.to_physical(base_style.writing_mode),
214 Importance::Normal,
215 );
216 }
217 }
218
219 fn resolve_style<E>(
220 self,
221 element: E,
222 context: &SharedStyleContext,
223 base_style: &Arc<ComputedValues>,
224 resolver: &mut StyleResolverForElement<E>,
225 ) -> Arc<ComputedValues>
226 where
227 E: TElement,
228 {
229 if !self.declarations.any_normal() {
230 return base_style.clone();
231 }
232
233 let document = element.as_node().owner_doc();
234 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
235 let mut important_rules_changed = false;
236 let rule_node = base_style.rules().clone();
237 let new_node = context.stylist.rule_tree().update_rule_at_level(
238 CascadeLevel::new(CascadeOrigin::Animations),
239 LayerOrder::root(),
240 Some(locked_block.borrow_arc()),
241 &rule_node,
242 &context.guards,
243 &mut important_rules_changed,
244 );
245
246 if new_node.is_none() {
247 return base_style.clone();
248 }
249
250 let inputs = CascadeInputs {
251 rules: new_node,
252 visited_rules: base_style.visited_rules().cloned(),
253 flags: base_style.flags.for_cascade_inputs(),
254 included_cascade_flags: RuleCascadeFlags::empty(),
255 };
256 resolver
257 .cascade_style_and_visited_with_default_parents(inputs)
258 .0
259 }
260}
261
262#[derive(Clone, MallocSizeOf)]
264struct ComputedKeyframe {
265 timing_function: TimingFunction,
268
269 start_percentage: f32,
272
273 values: Box<[AnimationValue]>,
276}
277
278impl ComputedKeyframe {
279 fn generate_for_keyframes<E>(
280 element: E,
281 animation: &KeyframesAnimation,
282 context: &SharedStyleContext,
283 base_style: &Arc<ComputedValues>,
284 default_timing_function: TimingFunction,
285 resolver: &mut StyleResolverForElement<E>,
286 ) -> Box<[Self]>
287 where
288 E: TElement,
289 {
290 let mut animating_properties = PropertyDeclarationIdSet::default();
291 for property in animation.properties_changed.iter() {
292 debug_assert!(property.is_animatable());
293 animating_properties.insert(property.to_physical(base_style.writing_mode));
294 }
295
296 let animation_values_from_style: Vec<AnimationValue> = animating_properties
297 .iter()
298 .map(|property| {
299 AnimationValue::from_computed_values(property, &**base_style)
300 .expect("Unexpected non-animatable property.")
301 })
302 .collect();
303
304 let intermediate_steps =
305 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
306
307 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
308 for (step_index, step) in intermediate_steps.into_iter().enumerate() {
309 let start_percentage = step.start_percentage;
310 let properties_changed_in_step = step.declarations.property_ids().clone();
311 let step_timing_function = step.timing_function.clone();
312 let step_style = step.resolve_style(element, context, base_style, resolver);
313 let timing_function =
314 step_timing_function.unwrap_or_else(|| default_timing_function.clone());
315
316 let values = {
317 let default_values = if start_percentage == 0. || start_percentage == 1.0 {
324 animation_values_from_style.as_slice()
325 } else {
326 debug_assert!(step_index != 0);
327 &computed_steps[step_index - 1].values
328 };
329
330 animating_properties
334 .iter()
335 .zip(default_values.iter())
336 .map(|(property_declaration, default_value)| {
337 if properties_changed_in_step.contains(property_declaration) {
338 AnimationValue::from_computed_values(property_declaration, &step_style)
339 .unwrap_or_else(|| default_value.clone())
340 } else {
341 default_value.clone()
342 }
343 })
344 .collect()
345 };
346
347 computed_steps.push(ComputedKeyframe {
348 timing_function,
349 start_percentage,
350 values,
351 });
352 }
353 computed_steps.into_boxed_slice()
354 }
355}
356
357#[derive(Clone, MallocSizeOf)]
359pub struct Animation {
360 pub name: Atom,
362
363 properties_changed: PropertyDeclarationIdSet,
365
366 computed_steps: Box<[ComputedKeyframe]>,
368
369 pub started_at: f64,
372
373 pub duration: f64,
375
376 pub delay: f64,
378
379 pub fill_mode: AnimationFillMode,
381
382 pub iteration_state: KeyframesIterationState,
384
385 pub state: AnimationState,
387
388 pub direction: AnimationDirection,
390
391 pub current_direction: AnimationDirection,
393
394 #[ignore_malloc_size_of = "ComputedValues"]
397 pub cascade_style: Arc<ComputedValues>,
398
399 pub is_new: bool,
402}
403
404impl Animation {
405 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
407 let new_ui = new_style.get_ui();
408 let index = new_ui
409 .animation_name_iter()
410 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
411 let index = match index {
412 Some(index) => index,
413 None => return true,
414 };
415
416 new_ui.animation_duration_mod(index).seconds() == 0.
417 }
418
419 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
423 if !self.iteration_over(time) {
424 return false;
425 }
426
427 if self.state != AnimationState::Running {
429 return false;
430 }
431
432 if self.on_last_iteration() {
433 return false;
434 }
435
436 self.iterate();
437 true
438 }
439
440 fn iterate(&mut self) {
441 debug_assert!(!self.on_last_iteration());
442
443 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
444 *current = (*current + 1.).min(max);
445 }
446
447 if let AnimationState::Paused(ref mut progress) = self.state {
448 debug_assert!(*progress > 1.);
449 *progress -= 1.;
450 }
451
452 self.started_at += self.duration;
454 match self.direction {
455 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
456 self.current_direction = match self.current_direction {
457 AnimationDirection::Normal => AnimationDirection::Reverse,
458 AnimationDirection::Reverse => AnimationDirection::Normal,
459 _ => unreachable!(),
460 };
461 },
462 _ => {},
463 }
464 }
465
466 pub fn current_iteration_end_progress(&self) -> f64 {
471 match self.iteration_state {
472 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
473 KeyframesIterationState::Infinite(_) => 1.,
474 }
475 }
476
477 pub fn current_iteration_duration(&self) -> f64 {
480 self.current_iteration_end_progress() * self.duration
481 }
482
483 fn iteration_over(&self, time: f64) -> bool {
486 time > (self.started_at + self.current_iteration_duration())
487 }
488
489 fn on_last_iteration(&self) -> bool {
491 match self.iteration_state {
492 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
493 KeyframesIterationState::Infinite(_) => false,
494 }
495 }
496
497 pub fn has_ended(&self, time: f64) -> bool {
501 if !self.on_last_iteration() {
502 return false;
503 }
504
505 let progress = match self.state {
506 AnimationState::Finished => return true,
507 AnimationState::Paused(progress) => progress,
508 AnimationState::Running => (time - self.started_at) / self.duration,
509 AnimationState::Pending | AnimationState::Canceled => return false,
510 };
511
512 progress >= self.current_iteration_end_progress()
513 }
514
515 pub fn update_from_other(&mut self, other: &Self, now: f64) {
523 use self::AnimationState::*;
524
525 debug!(
526 "KeyframesAnimationState::update_from_other({:?}, {:?})",
527 self, other
528 );
529
530 let old_started_at = self.started_at;
533 let old_duration = self.duration;
534 let old_direction = self.current_direction;
535 let old_state = self.state.clone();
536 let old_iteration_state = self.iteration_state.clone();
537
538 *self = other.clone();
539
540 self.started_at = old_started_at;
541 self.current_direction = old_direction;
542
543 match (&mut self.iteration_state, old_iteration_state) {
547 (
548 &mut KeyframesIterationState::Finite(ref mut iters, _),
549 KeyframesIterationState::Finite(old_iters, _),
550 ) => *iters = old_iters,
551 _ => {},
552 }
553
554 let new_state = std::mem::replace(&mut self.state, Running);
557 if old_state == Finished && self.has_ended(now) {
558 self.state = Finished;
559 } else {
560 self.state = new_state;
561 }
562
563 match (&mut self.state, &old_state) {
570 (&mut Pending, &Paused(progress)) => {
571 self.started_at = now - (self.duration * progress);
572 },
573 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
574 (&mut Paused(ref mut progress), &Running) => {
575 *progress = (now - old_started_at) / old_duration
576 },
577 _ => {},
578 }
579
580 if self.state == Pending && self.started_at <= now && old_state != Pending {
583 self.state = Running;
584 }
585 }
586
587 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
590 if self.computed_steps.is_empty() {
591 return;
593 }
594
595 let total_progress = match self.state {
596 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
597 (now - self.started_at) / self.duration
598 },
599 AnimationState::Paused(progress) => progress,
600 AnimationState::Canceled => return,
601 };
602
603 if total_progress < 0.
604 && self.fill_mode != AnimationFillMode::Backwards
605 && self.fill_mode != AnimationFillMode::Both
606 {
607 return;
608 }
609 if self.has_ended(now)
610 && self.fill_mode != AnimationFillMode::Forwards
611 && self.fill_mode != AnimationFillMode::Both
612 {
613 return;
614 }
615 let total_progress = total_progress
616 .min(self.current_iteration_end_progress())
617 .max(0.0);
618
619 let next_keyframe_index;
621 let prev_keyframe_index;
622 let num_steps = self.computed_steps.len();
623 match self.current_direction {
624 AnimationDirection::Normal => {
625 next_keyframe_index = self
626 .computed_steps
627 .iter()
628 .position(|step| total_progress as f32 <= step.start_percentage);
629 prev_keyframe_index = next_keyframe_index
630 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
631 .unwrap_or(0);
632 },
633 AnimationDirection::Reverse => {
634 next_keyframe_index = self
635 .computed_steps
636 .iter()
637 .rev()
638 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
639 .map(|pos| num_steps - pos - 1);
640 prev_keyframe_index = next_keyframe_index
641 .and_then(|pos| {
642 if pos != num_steps - 1 {
643 Some(pos + 1)
644 } else {
645 None
646 }
647 })
648 .unwrap_or(num_steps - 1)
649 },
650 _ => unreachable!(),
651 }
652
653 debug!(
654 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
655 prev_keyframe_index, next_keyframe_index
656 );
657
658 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
659 let next_keyframe = match next_keyframe_index {
660 Some(index) => &self.computed_steps[index],
661 None => return,
662 };
663
664 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
667 for value in keyframe.values.iter() {
668 map.insert(value.id().to_owned(), value.clone());
669 }
670 };
671 if total_progress <= 0.0 {
672 add_declarations_to_map(&prev_keyframe);
673 return;
674 }
675 if total_progress >= 1.0 {
676 add_declarations_to_map(&next_keyframe);
677 return;
678 }
679
680 let percentage_between_keyframes =
681 (next_keyframe.start_percentage - prev_keyframe.start_percentage).abs() as f64;
682 let duration_between_keyframes = percentage_between_keyframes * self.duration;
683 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
684 AnimationDirection::Normal => prev_keyframe.start_percentage as f64,
685 AnimationDirection::Reverse => 1. - prev_keyframe.start_percentage as f64,
686 _ => unreachable!(),
687 };
688 let progress_between_keyframes = (total_progress
689 - direction_aware_prev_keyframe_start_percentage)
690 / percentage_between_keyframes;
691
692 for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) {
693 let animation = PropertyAnimation {
694 from: from.clone(),
695 to: to.clone(),
696 timing_function: prev_keyframe.timing_function.clone(),
697 duration: duration_between_keyframes as f64,
698 };
699
700 let value = animation.calculate_value(progress_between_keyframes);
701 map.insert(value.id().to_owned(), value);
702 }
703 }
704}
705
706impl fmt::Debug for Animation {
707 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
708 f.debug_struct("Animation")
709 .field("name", &self.name)
710 .field("started_at", &self.started_at)
711 .field("duration", &self.duration)
712 .field("delay", &self.delay)
713 .field("iteration_state", &self.iteration_state)
714 .field("state", &self.state)
715 .field("direction", &self.direction)
716 .field("current_direction", &self.current_direction)
717 .field("cascade_style", &())
718 .finish()
719 }
720}
721
722#[derive(Clone, Debug, MallocSizeOf)]
724pub struct Transition {
725 pub start_time: f64,
728
729 pub delay: f64,
731
732 pub property_animation: PropertyAnimation,
734
735 pub state: AnimationState,
737
738 pub is_new: bool,
741
742 pub reversing_adjusted_start_value: AnimationValue,
745
746 pub reversing_shortening_factor: f64,
749}
750
751impl Transition {
752 fn new(
753 start_time: f64,
754 delay: f64,
755 duration: f64,
756 from: AnimationValue,
757 to: AnimationValue,
758 timing_function: &TimingFunction,
759 ) -> Self {
760 let property_animation = PropertyAnimation {
761 from: from.clone(),
762 to,
763 timing_function: timing_function.clone(),
764 duration,
765 };
766 Self {
767 start_time,
768 delay,
769 property_animation,
770 state: AnimationState::Pending,
771 is_new: true,
772 reversing_adjusted_start_value: from,
773 reversing_shortening_factor: 1.0,
774 }
775 }
776
777 fn update_for_possibly_reversed_transition(
778 &mut self,
779 replaced_transition: &Transition,
780 delay: f64,
781 now: f64,
782 ) {
783 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
792 return;
793 }
794
795 let replaced_animation = &replaced_transition.property_animation;
797 self.reversing_adjusted_start_value = replaced_animation.to.clone();
798
799 let transition_progress = ((now - replaced_transition.start_time)
806 / (replaced_transition.property_animation.duration))
807 .min(1.0)
808 .max(0.0);
809 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
810 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
811 self.reversing_shortening_factor = ((timing_function_output
812 * old_reversing_shortening_factor)
813 + (1.0 - old_reversing_shortening_factor))
814 .abs()
815 .min(1.0)
816 .max(0.0);
817
818 self.start_time = if delay >= 0. {
824 now + delay
825 } else {
826 now + (self.reversing_shortening_factor * delay)
827 };
828
829 self.property_animation.duration *= self.reversing_shortening_factor;
832
833 let procedure = Procedure::Interpolate {
836 progress: timing_function_output,
837 };
838 match replaced_animation
839 .from
840 .animate(&replaced_animation.to, procedure)
841 {
842 Ok(new_start) => self.property_animation.from = new_start,
843 Err(..) => {},
844 }
845 }
846
847 pub fn has_ended(&self, time: f64) -> bool {
851 time >= self.start_time + (self.property_animation.duration)
852 }
853
854 pub fn calculate_value(&self, time: f64) -> AnimationValue {
856 let progress = (time - self.start_time) / (self.property_animation.duration);
857 self.property_animation
858 .calculate_value(progress.clamp(0.0, 1.0))
859 }
860}
861
862#[derive(Debug, Default, MallocSizeOf)]
864pub struct ElementAnimationSet {
865 pub animations: Vec<Animation>,
867
868 pub transitions: Vec<Transition>,
870
871 pub dirty: bool,
874}
875
876impl ElementAnimationSet {
877 pub fn cancel_all_animations(&mut self) {
880 self.dirty = !self.animations.is_empty();
881 for animation in self.animations.iter_mut() {
882 animation.state = AnimationState::Canceled;
883 }
884 self.cancel_active_transitions();
885 }
886
887 fn cancel_active_transitions(&mut self) {
888 for transition in self.transitions.iter_mut() {
889 if transition.state != AnimationState::Finished {
890 self.dirty = true;
891 transition.state = AnimationState::Canceled;
892 }
893 }
894 }
895
896 pub fn apply_active_animations(
898 &self,
899 context: &SharedStyleContext,
900 style: &mut Arc<ComputedValues>,
901 ) {
902 let now = context.current_time_for_animations;
903 let mutable_style = Arc::make_mut(style);
904 if let Some(map) = self.get_value_map_for_active_animations(now) {
905 for value in map.values() {
906 value.set_in_style_for_servo(mutable_style, context);
907 }
908 }
909
910 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
911 for value in map.values() {
912 value.set_in_style_for_servo(mutable_style, context);
913 }
914 }
915 }
916
917 pub fn clear_canceled_animations(&mut self) {
919 self.animations
920 .retain(|animation| animation.state != AnimationState::Canceled);
921 self.transitions
922 .retain(|animation| animation.state != AnimationState::Canceled);
923 }
924
925 pub fn is_empty(&self) -> bool {
928 self.animations.is_empty() && self.transitions.is_empty()
929 }
930
931 pub fn needs_animation_ticks(&self) -> bool {
934 self.animations
935 .iter()
936 .any(|animation| animation.state.needs_to_be_ticked())
937 || self
938 .transitions
939 .iter()
940 .any(|transition| transition.state.needs_to_be_ticked())
941 }
942
943 pub fn running_animation_and_transition_count(&self) -> usize {
945 self.animations
946 .iter()
947 .filter(|animation| animation.state.needs_to_be_ticked())
948 .count()
949 + self
950 .transitions
951 .iter()
952 .filter(|transition| transition.state.needs_to_be_ticked())
953 .count()
954 }
955
956 pub fn has_active_animation(&self) -> bool {
958 self.animations
959 .iter()
960 .any(|animation| animation.state != AnimationState::Canceled)
961 }
962
963 pub fn has_active_transition(&self) -> bool {
965 self.transitions
966 .iter()
967 .any(|transition| transition.state != AnimationState::Canceled)
968 }
969
970 pub fn update_animations_for_new_style<E>(
973 &mut self,
974 element: E,
975 context: &SharedStyleContext,
976 new_style: &Arc<ComputedValues>,
977 resolver: &mut StyleResolverForElement<E>,
978 ) where
979 E: TElement,
980 {
981 for animation in self.animations.iter_mut() {
982 if animation.is_cancelled_in_new_style(new_style) {
983 animation.state = AnimationState::Canceled;
984 }
985 }
986
987 maybe_start_animations(element, &context, &new_style, self, resolver);
988 }
989
990 pub fn update_transitions_for_new_style(
993 &mut self,
994 might_need_transitions_update: bool,
995 context: &SharedStyleContext,
996 old_style: Option<&Arc<ComputedValues>>,
997 after_change_style: &Arc<ComputedValues>,
998 ) {
999 let mut before_change_style = match old_style {
1002 Some(old_style) => Arc::clone(old_style),
1003 None => return,
1004 };
1005
1006 if after_change_style.get_box().clone_display().is_none() {
1008 self.cancel_active_transitions();
1009 return;
1010 }
1011
1012 if !might_need_transitions_update {
1013 return;
1014 }
1015
1016 if self.has_active_transition() || self.has_active_animation() {
1018 self.apply_active_animations(context, &mut before_change_style);
1019 }
1020
1021 let transitioning_properties = start_transitions_if_applicable(
1022 context,
1023 &before_change_style,
1024 after_change_style,
1025 self,
1026 );
1027
1028 for transition in self.transitions.iter_mut() {
1041 if transition.state == AnimationState::Finished
1042 || transition.state == AnimationState::Canceled
1043 {
1044 continue;
1045 }
1046 if transitioning_properties.contains(transition.property_animation.property_id()) {
1047 continue;
1048 }
1049 transition.state = AnimationState::Canceled;
1050 self.dirty = true;
1051 }
1052 }
1053
1054 fn start_transition_if_applicable(
1055 &mut self,
1056 context: &SharedStyleContext,
1057 property_declaration_id: &PropertyDeclarationId,
1058 index: usize,
1059 old_style: &ComputedValues,
1060 new_style: &Arc<ComputedValues>,
1061 ) {
1062 let style = new_style.get_ui();
1063 let allow_discrete =
1064 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1065
1066 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1068 else {
1069 return;
1070 };
1071 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1072 else {
1073 return;
1074 };
1075
1076 let timing_function = style.transition_timing_function_mod(index);
1077 let duration = style.transition_duration_mod(index).seconds() as f64;
1078 let delay = style.transition_delay_mod(index).seconds() as f64;
1079 let now = context.current_time_for_animations;
1080 let transitionable = property_declaration_id.is_animatable()
1081 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1082 && (allow_discrete || from.interpolable_with(&to));
1083
1084 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1085 transition.property_animation.property_id() == *property_declaration_id
1086 });
1087
1088 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1103 transition.state != AnimationState::Finished
1104 && transition.state != AnimationState::Canceled
1105 });
1106 let no_completed_transition_or_end_values_differ =
1107 existing_transition.as_ref().is_none_or(|transition| {
1108 transition.state != AnimationState::Finished
1109 || transition.property_animation.to != to
1110 });
1111 if !has_running_transition
1112 && from != to
1113 && transitionable
1114 && no_completed_transition_or_end_values_differ
1115 && (duration + delay > 0.0)
1116 {
1117 self.transitions.push(Transition::new(
1128 now + delay, delay,
1130 duration,
1131 from,
1132 to,
1133 &timing_function,
1134 ));
1135 self.dirty = true;
1136 return;
1137 }
1138
1139 let Some(existing_transition) = existing_transition.as_mut() else {
1162 return;
1163 };
1164
1165 if has_running_transition && existing_transition.property_animation.to != to {
1170 let current_value = existing_transition.calculate_value(now);
1175 let transitionable_from_current_value =
1176 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1177 if current_value == to || !transitionable_from_current_value {
1178 existing_transition.state = AnimationState::Canceled;
1179 self.dirty = true;
1180 return;
1181 }
1182
1183 if duration + delay <= 0.0 {
1189 existing_transition.state = AnimationState::Canceled;
1190 self.dirty = true;
1191 return;
1192 }
1193
1194 if existing_transition.reversing_adjusted_start_value == to {
1200 existing_transition.state = AnimationState::Canceled;
1201
1202 let mut transition = Transition::new(
1203 now + delay, delay,
1205 duration,
1206 from,
1207 to,
1208 &timing_function,
1209 );
1210
1211 transition.update_for_possibly_reversed_transition(
1214 &existing_transition,
1215 delay,
1216 now,
1217 );
1218
1219 self.transitions.push(transition);
1220 self.dirty = true;
1221 return;
1222 }
1223
1224 existing_transition.state = AnimationState::Canceled;
1233 self.transitions.push(Transition::new(
1234 now + delay, delay,
1236 duration,
1237 current_value,
1238 to,
1239 &timing_function,
1240 ));
1241 self.dirty = true;
1242 }
1243 }
1244
1245 fn get_value_map_for_transitions(
1249 &self,
1250 now: f64,
1251 ignore_transitions: IgnoreTransitions,
1252 ) -> Option<AnimationValueMap> {
1253 if !self.has_active_transition() {
1254 return None;
1255 }
1256
1257 let mut map =
1258 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1259 for transition in &self.transitions {
1260 match ignore_transitions {
1261 IgnoreTransitions::Canceled => {
1262 if transition.state == AnimationState::Canceled {
1263 continue;
1264 }
1265 },
1266 IgnoreTransitions::CanceledAndFinished => {
1267 if transition.state == AnimationState::Canceled
1268 || transition.state == AnimationState::Finished
1269 {
1270 continue;
1271 }
1272 },
1273 }
1274
1275 let value = transition.calculate_value(now);
1276 map.insert(value.id().to_owned(), value);
1277 }
1278
1279 Some(map)
1280 }
1281
1282 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1285 if !self.has_active_animation() {
1286 return None;
1287 }
1288
1289 let mut map = Default::default();
1290 for animation in &self.animations {
1291 animation.get_property_declaration_at_time(now, &mut map);
1292 }
1293
1294 Some(map)
1295 }
1296}
1297
1298#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1299pub struct AnimationSetKey {
1301 pub node: OpaqueNode,
1303 pub pseudo_element: Option<PseudoElement>,
1306}
1307
1308impl AnimationSetKey {
1309 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1311 AnimationSetKey {
1312 node,
1313 pseudo_element,
1314 }
1315 }
1316
1317 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1319 AnimationSetKey {
1320 node,
1321 pseudo_element: None,
1322 }
1323 }
1324
1325 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1327 AnimationSetKey {
1328 node,
1329 pseudo_element: Some(pseudo_element),
1330 }
1331 }
1332}
1333
1334#[derive(Clone, Debug, Default, MallocSizeOf)]
1335pub struct DocumentAnimationSet {
1337 #[ignore_malloc_size_of = "Arc is hard"]
1339 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1340}
1341
1342impl DocumentAnimationSet {
1343 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1345 self.sets
1346 .read()
1347 .get(key)
1348 .map_or(false, |set| set.has_active_animation())
1349 }
1350
1351 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1353 self.sets
1354 .read()
1355 .get(key)
1356 .map_or(false, |set| set.has_active_transition())
1357 }
1358
1359 pub fn get_animation_declarations(
1362 &self,
1363 key: &AnimationSetKey,
1364 time: f64,
1365 shared_lock: &SharedRwLock,
1366 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1367 self.sets
1368 .read()
1369 .get(key)
1370 .and_then(|set| set.get_value_map_for_active_animations(time))
1371 .map(|map| {
1372 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1373 Arc::new(shared_lock.wrap(block))
1374 })
1375 }
1376
1377 pub fn get_transition_declarations(
1380 &self,
1381 key: &AnimationSetKey,
1382 time: f64,
1383 shared_lock: &SharedRwLock,
1384 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1385 self.sets
1386 .read()
1387 .get(key)
1388 .and_then(|set| {
1389 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1390 })
1391 .map(|map| {
1392 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1393 Arc::new(shared_lock.wrap(block))
1394 })
1395 }
1396
1397 pub fn get_all_declarations(
1400 &self,
1401 key: &AnimationSetKey,
1402 time: f64,
1403 shared_lock: &SharedRwLock,
1404 ) -> AnimationDeclarations {
1405 let sets = self.sets.read();
1406 let set = match sets.get(key) {
1407 Some(set) => set,
1408 None => return Default::default(),
1409 };
1410
1411 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1412 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1413 Arc::new(shared_lock.wrap(block))
1414 });
1415 let transitions = set
1416 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1417 .map(|map| {
1418 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1419 Arc::new(shared_lock.wrap(block))
1420 });
1421 AnimationDeclarations {
1422 animations,
1423 transitions,
1424 }
1425 }
1426
1427 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1429 if let Some(set) = self.sets.write().get_mut(key) {
1430 set.cancel_all_animations();
1431 }
1432 }
1433}
1434
1435pub fn start_transitions_if_applicable(
1438 context: &SharedStyleContext,
1439 old_style: &ComputedValues,
1440 new_style: &Arc<ComputedValues>,
1441 animation_state: &mut ElementAnimationSet,
1442) -> PropertyDeclarationIdSet {
1443 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1458 transition_properties.reverse();
1459
1460 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1461 for transition in transition_properties {
1462 let physical_property = transition
1463 .property
1464 .as_borrowed()
1465 .to_physical(new_style.writing_mode);
1466 if properties_that_transition.contains(physical_property) {
1467 continue;
1468 }
1469
1470 properties_that_transition.insert(physical_property);
1471 animation_state.start_transition_if_applicable(
1472 context,
1473 &physical_property,
1474 transition.index,
1475 old_style,
1476 new_style,
1477 );
1478 }
1479
1480 properties_that_transition
1481}
1482
1483pub fn maybe_start_animations<E>(
1486 element: E,
1487 context: &SharedStyleContext,
1488 new_style: &Arc<ComputedValues>,
1489 animation_state: &mut ElementAnimationSet,
1490 resolver: &mut StyleResolverForElement<E>,
1491) where
1492 E: TElement,
1493{
1494 let style = new_style.get_ui();
1495 for (i, name) in style.animation_name_iter().enumerate() {
1496 let name = match name.as_atom() {
1497 Some(atom) => atom,
1498 None => continue,
1499 };
1500
1501 debug!("maybe_start_animations: name={}", name);
1502 let duration = style.animation_duration_mod(i).seconds() as f64;
1503 if duration == 0. {
1504 continue;
1505 }
1506
1507 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1508 continue;
1509 };
1510
1511 debug!("maybe_start_animations: animation {} found", name);
1512
1513 let delay = style.animation_delay_mod(i).seconds();
1517
1518 let iteration_count = style.animation_iteration_count_mod(i);
1519 let iteration_state = if iteration_count.0.is_infinite() {
1520 KeyframesIterationState::Infinite(0.0)
1521 } else {
1522 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1523 };
1524
1525 let animation_direction = style.animation_direction_mod(i);
1526
1527 let initial_direction = match animation_direction {
1528 AnimationDirection::Normal | AnimationDirection::Alternate => {
1529 AnimationDirection::Normal
1530 },
1531 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1532 AnimationDirection::Reverse
1533 },
1534 };
1535
1536 let now = context.current_time_for_animations;
1537 let started_at = now + delay as f64;
1538 let mut starting_progress = (now - started_at) / duration;
1539 let state = match style.animation_play_state_mod(i) {
1540 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1541 AnimationPlayState::Running => AnimationState::Pending,
1542 };
1543
1544 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1545 element,
1546 &keyframe_animation,
1547 context,
1548 new_style,
1549 style.animation_timing_function_mod(i),
1550 resolver,
1551 );
1552
1553 let mut new_animation = Animation {
1554 name: name.clone(),
1555 properties_changed: keyframe_animation.properties_changed.clone(),
1556 computed_steps,
1557 started_at,
1558 duration,
1559 fill_mode: style.animation_fill_mode_mod(i),
1560 delay: delay as f64,
1561 iteration_state,
1562 state,
1563 direction: animation_direction,
1564 current_direction: initial_direction,
1565 cascade_style: new_style.clone(),
1566 is_new: true,
1567 };
1568
1569 while starting_progress > 1. && !new_animation.on_last_iteration() {
1572 new_animation.iterate();
1573 starting_progress -= 1.;
1574 }
1575
1576 animation_state.dirty = true;
1577
1578 for existing_animation in animation_state.animations.iter_mut() {
1580 if existing_animation.state == AnimationState::Canceled {
1581 continue;
1582 }
1583
1584 if new_animation.name == existing_animation.name {
1585 existing_animation
1586 .update_from_other(&new_animation, context.current_time_for_animations);
1587 return;
1588 }
1589 }
1590
1591 animation_state.animations.push(new_animation);
1592 }
1593}