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;
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::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 };
255 resolver
256 .cascade_style_and_visited_with_default_parents(inputs)
257 .0
258 }
259}
260
261#[derive(Clone, MallocSizeOf)]
263struct ComputedKeyframe {
264 timing_function: TimingFunction,
267
268 start_percentage: f32,
271
272 values: Box<[AnimationValue]>,
275}
276
277impl ComputedKeyframe {
278 fn generate_for_keyframes<E>(
279 element: E,
280 animation: &KeyframesAnimation,
281 context: &SharedStyleContext,
282 base_style: &Arc<ComputedValues>,
283 default_timing_function: TimingFunction,
284 resolver: &mut StyleResolverForElement<E>,
285 ) -> Box<[Self]>
286 where
287 E: TElement,
288 {
289 let mut animating_properties = PropertyDeclarationIdSet::default();
290 for property in animation.properties_changed.iter() {
291 debug_assert!(property.is_animatable());
292 animating_properties.insert(property.to_physical(base_style.writing_mode));
293 }
294
295 let animation_values_from_style: Vec<AnimationValue> = animating_properties
296 .iter()
297 .map(|property| {
298 AnimationValue::from_computed_values(property, &**base_style)
299 .expect("Unexpected non-animatable property.")
300 })
301 .collect();
302
303 let intermediate_steps =
304 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
305
306 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
307 for (step_index, step) in intermediate_steps.into_iter().enumerate() {
308 let start_percentage = step.start_percentage;
309 let properties_changed_in_step = step.declarations.property_ids().clone();
310 let step_timing_function = step.timing_function.clone();
311 let step_style = step.resolve_style(element, context, base_style, resolver);
312 let timing_function =
313 step_timing_function.unwrap_or_else(|| default_timing_function.clone());
314
315 let values = {
316 let default_values = if start_percentage == 0. || start_percentage == 1.0 {
323 animation_values_from_style.as_slice()
324 } else {
325 debug_assert!(step_index != 0);
326 &computed_steps[step_index - 1].values
327 };
328
329 animating_properties
333 .iter()
334 .zip(default_values.iter())
335 .map(|(property_declaration, default_value)| {
336 if properties_changed_in_step.contains(property_declaration) {
337 AnimationValue::from_computed_values(property_declaration, &step_style)
338 .unwrap_or_else(|| default_value.clone())
339 } else {
340 default_value.clone()
341 }
342 })
343 .collect()
344 };
345
346 computed_steps.push(ComputedKeyframe {
347 timing_function,
348 start_percentage,
349 values,
350 });
351 }
352 computed_steps.into_boxed_slice()
353 }
354}
355
356#[derive(Clone, MallocSizeOf)]
358pub struct Animation {
359 pub name: Atom,
361
362 properties_changed: PropertyDeclarationIdSet,
364
365 computed_steps: Box<[ComputedKeyframe]>,
367
368 pub started_at: f64,
371
372 pub duration: f64,
374
375 pub delay: f64,
377
378 pub fill_mode: AnimationFillMode,
380
381 pub iteration_state: KeyframesIterationState,
383
384 pub state: AnimationState,
386
387 pub direction: AnimationDirection,
389
390 pub current_direction: AnimationDirection,
392
393 #[ignore_malloc_size_of = "ComputedValues"]
396 pub cascade_style: Arc<ComputedValues>,
397
398 pub is_new: bool,
401}
402
403impl Animation {
404 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
406 let new_ui = new_style.get_ui();
407 let index = new_ui
408 .animation_name_iter()
409 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
410 let index = match index {
411 Some(index) => index,
412 None => return true,
413 };
414
415 new_ui.animation_duration_mod(index).seconds() == 0.
416 }
417
418 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
422 if !self.iteration_over(time) {
423 return false;
424 }
425
426 if self.state != AnimationState::Running {
428 return false;
429 }
430
431 if self.on_last_iteration() {
432 return false;
433 }
434
435 self.iterate();
436 true
437 }
438
439 fn iterate(&mut self) {
440 debug_assert!(!self.on_last_iteration());
441
442 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
443 *current = (*current + 1.).min(max);
444 }
445
446 if let AnimationState::Paused(ref mut progress) = self.state {
447 debug_assert!(*progress > 1.);
448 *progress -= 1.;
449 }
450
451 self.started_at += self.duration;
453 match self.direction {
454 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
455 self.current_direction = match self.current_direction {
456 AnimationDirection::Normal => AnimationDirection::Reverse,
457 AnimationDirection::Reverse => AnimationDirection::Normal,
458 _ => unreachable!(),
459 };
460 },
461 _ => {},
462 }
463 }
464
465 pub fn current_iteration_end_progress(&self) -> f64 {
470 match self.iteration_state {
471 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
472 KeyframesIterationState::Infinite(_) => 1.,
473 }
474 }
475
476 pub fn current_iteration_duration(&self) -> f64 {
479 self.current_iteration_end_progress() * self.duration
480 }
481
482 fn iteration_over(&self, time: f64) -> bool {
485 time > (self.started_at + self.current_iteration_duration())
486 }
487
488 fn on_last_iteration(&self) -> bool {
490 match self.iteration_state {
491 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
492 KeyframesIterationState::Infinite(_) => false,
493 }
494 }
495
496 pub fn has_ended(&self, time: f64) -> bool {
500 if !self.on_last_iteration() {
501 return false;
502 }
503
504 let progress = match self.state {
505 AnimationState::Finished => return true,
506 AnimationState::Paused(progress) => progress,
507 AnimationState::Running => (time - self.started_at) / self.duration,
508 AnimationState::Pending | AnimationState::Canceled => return false,
509 };
510
511 progress >= self.current_iteration_end_progress()
512 }
513
514 pub fn update_from_other(&mut self, other: &Self, now: f64) {
522 use self::AnimationState::*;
523
524 debug!(
525 "KeyframesAnimationState::update_from_other({:?}, {:?})",
526 self, other
527 );
528
529 let old_started_at = self.started_at;
532 let old_duration = self.duration;
533 let old_direction = self.current_direction;
534 let old_state = self.state.clone();
535 let old_iteration_state = self.iteration_state.clone();
536
537 *self = other.clone();
538
539 self.started_at = old_started_at;
540 self.current_direction = old_direction;
541
542 match (&mut self.iteration_state, old_iteration_state) {
546 (
547 &mut KeyframesIterationState::Finite(ref mut iters, _),
548 KeyframesIterationState::Finite(old_iters, _),
549 ) => *iters = old_iters,
550 _ => {},
551 }
552
553 let new_state = std::mem::replace(&mut self.state, Running);
556 if old_state == Finished && self.has_ended(now) {
557 self.state = Finished;
558 } else {
559 self.state = new_state;
560 }
561
562 match (&mut self.state, &old_state) {
569 (&mut Pending, &Paused(progress)) => {
570 self.started_at = now - (self.duration * progress);
571 },
572 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
573 (&mut Paused(ref mut progress), &Running) => {
574 *progress = (now - old_started_at) / old_duration
575 },
576 _ => {},
577 }
578
579 if self.state == Pending && self.started_at <= now && old_state != Pending {
582 self.state = Running;
583 }
584 }
585
586 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
589 if self.computed_steps.is_empty() {
590 return;
592 }
593
594 let total_progress = match self.state {
595 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
596 (now - self.started_at) / self.duration
597 },
598 AnimationState::Paused(progress) => progress,
599 AnimationState::Canceled => return,
600 };
601
602 if total_progress < 0.
603 && self.fill_mode != AnimationFillMode::Backwards
604 && self.fill_mode != AnimationFillMode::Both
605 {
606 return;
607 }
608 if self.has_ended(now)
609 && self.fill_mode != AnimationFillMode::Forwards
610 && self.fill_mode != AnimationFillMode::Both
611 {
612 return;
613 }
614 let total_progress = total_progress
615 .min(self.current_iteration_end_progress())
616 .max(0.0);
617
618 let next_keyframe_index;
620 let prev_keyframe_index;
621 let num_steps = self.computed_steps.len();
622 match self.current_direction {
623 AnimationDirection::Normal => {
624 next_keyframe_index = self
625 .computed_steps
626 .iter()
627 .position(|step| total_progress as f32 <= step.start_percentage);
628 prev_keyframe_index = next_keyframe_index
629 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
630 .unwrap_or(0);
631 },
632 AnimationDirection::Reverse => {
633 next_keyframe_index = self
634 .computed_steps
635 .iter()
636 .rev()
637 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
638 .map(|pos| num_steps - pos - 1);
639 prev_keyframe_index = next_keyframe_index
640 .and_then(|pos| {
641 if pos != num_steps - 1 {
642 Some(pos + 1)
643 } else {
644 None
645 }
646 })
647 .unwrap_or(num_steps - 1)
648 },
649 _ => unreachable!(),
650 }
651
652 debug!(
653 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
654 prev_keyframe_index, next_keyframe_index
655 );
656
657 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
658 let next_keyframe = match next_keyframe_index {
659 Some(index) => &self.computed_steps[index],
660 None => return,
661 };
662
663 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
666 for value in keyframe.values.iter() {
667 map.insert(value.id().to_owned(), value.clone());
668 }
669 };
670 if total_progress <= 0.0 {
671 add_declarations_to_map(&prev_keyframe);
672 return;
673 }
674 if total_progress >= 1.0 {
675 add_declarations_to_map(&next_keyframe);
676 return;
677 }
678
679 let percentage_between_keyframes =
680 (next_keyframe.start_percentage - prev_keyframe.start_percentage).abs() as f64;
681 let duration_between_keyframes = percentage_between_keyframes * self.duration;
682 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
683 AnimationDirection::Normal => prev_keyframe.start_percentage as f64,
684 AnimationDirection::Reverse => 1. - prev_keyframe.start_percentage as f64,
685 _ => unreachable!(),
686 };
687 let progress_between_keyframes = (total_progress
688 - direction_aware_prev_keyframe_start_percentage)
689 / percentage_between_keyframes;
690
691 for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) {
692 let animation = PropertyAnimation {
693 from: from.clone(),
694 to: to.clone(),
695 timing_function: prev_keyframe.timing_function.clone(),
696 duration: duration_between_keyframes as f64,
697 };
698
699 let value = animation.calculate_value(progress_between_keyframes);
700 map.insert(value.id().to_owned(), value);
701 }
702 }
703}
704
705impl fmt::Debug for Animation {
706 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
707 f.debug_struct("Animation")
708 .field("name", &self.name)
709 .field("started_at", &self.started_at)
710 .field("duration", &self.duration)
711 .field("delay", &self.delay)
712 .field("iteration_state", &self.iteration_state)
713 .field("state", &self.state)
714 .field("direction", &self.direction)
715 .field("current_direction", &self.current_direction)
716 .field("cascade_style", &())
717 .finish()
718 }
719}
720
721#[derive(Clone, Debug, MallocSizeOf)]
723pub struct Transition {
724 pub start_time: f64,
727
728 pub delay: f64,
730
731 pub property_animation: PropertyAnimation,
733
734 pub state: AnimationState,
736
737 pub is_new: bool,
740
741 pub reversing_adjusted_start_value: AnimationValue,
744
745 pub reversing_shortening_factor: f64,
748}
749
750impl Transition {
751 fn new(
752 start_time: f64,
753 delay: f64,
754 duration: f64,
755 from: AnimationValue,
756 to: AnimationValue,
757 timing_function: &TimingFunction,
758 ) -> Self {
759 let property_animation = PropertyAnimation {
760 from: from.clone(),
761 to,
762 timing_function: timing_function.clone(),
763 duration,
764 };
765 Self {
766 start_time,
767 delay,
768 property_animation,
769 state: AnimationState::Pending,
770 is_new: true,
771 reversing_adjusted_start_value: from,
772 reversing_shortening_factor: 1.0,
773 }
774 }
775
776 fn update_for_possibly_reversed_transition(
777 &mut self,
778 replaced_transition: &Transition,
779 delay: f64,
780 now: f64,
781 ) {
782 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
791 return;
792 }
793
794 let replaced_animation = &replaced_transition.property_animation;
796 self.reversing_adjusted_start_value = replaced_animation.to.clone();
797
798 let transition_progress = ((now - replaced_transition.start_time)
805 / (replaced_transition.property_animation.duration))
806 .min(1.0)
807 .max(0.0);
808 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
809 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
810 self.reversing_shortening_factor = ((timing_function_output
811 * old_reversing_shortening_factor)
812 + (1.0 - old_reversing_shortening_factor))
813 .abs()
814 .min(1.0)
815 .max(0.0);
816
817 self.start_time = if delay >= 0. {
823 now + delay
824 } else {
825 now + (self.reversing_shortening_factor * delay)
826 };
827
828 self.property_animation.duration *= self.reversing_shortening_factor;
831
832 let procedure = Procedure::Interpolate {
835 progress: timing_function_output,
836 };
837 match replaced_animation
838 .from
839 .animate(&replaced_animation.to, procedure)
840 {
841 Ok(new_start) => self.property_animation.from = new_start,
842 Err(..) => {},
843 }
844 }
845
846 pub fn has_ended(&self, time: f64) -> bool {
850 time >= self.start_time + (self.property_animation.duration)
851 }
852
853 pub fn calculate_value(&self, time: f64) -> AnimationValue {
855 let progress = (time - self.start_time) / (self.property_animation.duration);
856 self.property_animation
857 .calculate_value(progress.clamp(0.0, 1.0))
858 }
859}
860
861#[derive(Debug, Default, MallocSizeOf)]
863pub struct ElementAnimationSet {
864 pub animations: Vec<Animation>,
866
867 pub transitions: Vec<Transition>,
869
870 pub dirty: bool,
873}
874
875impl ElementAnimationSet {
876 pub fn cancel_all_animations(&mut self) {
879 self.dirty = !self.animations.is_empty();
880 for animation in self.animations.iter_mut() {
881 animation.state = AnimationState::Canceled;
882 }
883 self.cancel_active_transitions();
884 }
885
886 fn cancel_active_transitions(&mut self) {
887 for transition in self.transitions.iter_mut() {
888 if transition.state != AnimationState::Finished {
889 self.dirty = true;
890 transition.state = AnimationState::Canceled;
891 }
892 }
893 }
894
895 pub fn apply_active_animations(
897 &self,
898 context: &SharedStyleContext,
899 style: &mut Arc<ComputedValues>,
900 ) {
901 let now = context.current_time_for_animations;
902 let mutable_style = Arc::make_mut(style);
903 if let Some(map) = self.get_value_map_for_active_animations(now) {
904 for value in map.values() {
905 value.set_in_style_for_servo(mutable_style, context);
906 }
907 }
908
909 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
910 for value in map.values() {
911 value.set_in_style_for_servo(mutable_style, context);
912 }
913 }
914 }
915
916 pub fn clear_canceled_animations(&mut self) {
918 self.animations
919 .retain(|animation| animation.state != AnimationState::Canceled);
920 self.transitions
921 .retain(|animation| animation.state != AnimationState::Canceled);
922 }
923
924 pub fn is_empty(&self) -> bool {
927 self.animations.is_empty() && self.transitions.is_empty()
928 }
929
930 pub fn needs_animation_ticks(&self) -> bool {
933 self.animations
934 .iter()
935 .any(|animation| animation.state.needs_to_be_ticked())
936 || self
937 .transitions
938 .iter()
939 .any(|transition| transition.state.needs_to_be_ticked())
940 }
941
942 pub fn running_animation_and_transition_count(&self) -> usize {
944 self.animations
945 .iter()
946 .filter(|animation| animation.state.needs_to_be_ticked())
947 .count()
948 + self
949 .transitions
950 .iter()
951 .filter(|transition| transition.state.needs_to_be_ticked())
952 .count()
953 }
954
955 pub fn has_active_animation(&self) -> bool {
957 self.animations
958 .iter()
959 .any(|animation| animation.state != AnimationState::Canceled)
960 }
961
962 pub fn has_active_transition(&self) -> bool {
964 self.transitions
965 .iter()
966 .any(|transition| transition.state != AnimationState::Canceled)
967 }
968
969 pub fn update_animations_for_new_style<E>(
972 &mut self,
973 element: E,
974 context: &SharedStyleContext,
975 new_style: &Arc<ComputedValues>,
976 resolver: &mut StyleResolverForElement<E>,
977 ) where
978 E: TElement,
979 {
980 for animation in self.animations.iter_mut() {
981 if animation.is_cancelled_in_new_style(new_style) {
982 animation.state = AnimationState::Canceled;
983 }
984 }
985
986 maybe_start_animations(element, &context, &new_style, self, resolver);
987 }
988
989 pub fn update_transitions_for_new_style(
992 &mut self,
993 might_need_transitions_update: bool,
994 context: &SharedStyleContext,
995 old_style: Option<&Arc<ComputedValues>>,
996 after_change_style: &Arc<ComputedValues>,
997 ) {
998 let mut before_change_style = match old_style {
1001 Some(old_style) => Arc::clone(old_style),
1002 None => return,
1003 };
1004
1005 if after_change_style.get_box().clone_display().is_none() {
1007 self.cancel_active_transitions();
1008 return;
1009 }
1010
1011 if !might_need_transitions_update {
1012 return;
1013 }
1014
1015 if self.has_active_transition() || self.has_active_animation() {
1017 self.apply_active_animations(context, &mut before_change_style);
1018 }
1019
1020 let transitioning_properties = start_transitions_if_applicable(
1021 context,
1022 &before_change_style,
1023 after_change_style,
1024 self,
1025 );
1026
1027 for transition in self.transitions.iter_mut() {
1040 if transition.state == AnimationState::Finished
1041 || transition.state == AnimationState::Canceled
1042 {
1043 continue;
1044 }
1045 if transitioning_properties.contains(transition.property_animation.property_id()) {
1046 continue;
1047 }
1048 transition.state = AnimationState::Canceled;
1049 self.dirty = true;
1050 }
1051 }
1052
1053 fn start_transition_if_applicable(
1054 &mut self,
1055 context: &SharedStyleContext,
1056 property_declaration_id: &PropertyDeclarationId,
1057 index: usize,
1058 old_style: &ComputedValues,
1059 new_style: &Arc<ComputedValues>,
1060 ) {
1061 let style = new_style.get_ui();
1062 let allow_discrete =
1063 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1064
1065 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1067 else {
1068 return;
1069 };
1070 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1071 else {
1072 return;
1073 };
1074
1075 let timing_function = style.transition_timing_function_mod(index);
1076 let duration = style.transition_duration_mod(index).seconds() as f64;
1077 let delay = style.transition_delay_mod(index).seconds() as f64;
1078 let now = context.current_time_for_animations;
1079 let transitionable = property_declaration_id.is_animatable()
1080 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1081 && (allow_discrete || from.interpolable_with(&to));
1082
1083 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1084 transition.property_animation.property_id() == *property_declaration_id
1085 });
1086
1087 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1102 transition.state != AnimationState::Finished
1103 && transition.state != AnimationState::Canceled
1104 });
1105 let no_completed_transition_or_end_values_differ =
1106 existing_transition.as_ref().is_none_or(|transition| {
1107 transition.state != AnimationState::Finished
1108 || transition.property_animation.to != to
1109 });
1110 if !has_running_transition
1111 && from != to
1112 && transitionable
1113 && no_completed_transition_or_end_values_differ
1114 && (duration + delay > 0.0)
1115 {
1116 self.transitions.push(Transition::new(
1127 now + delay, delay,
1129 duration,
1130 from,
1131 to,
1132 &timing_function,
1133 ));
1134 self.dirty = true;
1135 return;
1136 }
1137
1138 let Some(existing_transition) = existing_transition.as_mut() else {
1161 return;
1162 };
1163
1164 if has_running_transition && existing_transition.property_animation.to != to {
1169 let current_value = existing_transition.calculate_value(now);
1174 let transitionable_from_current_value =
1175 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1176 if current_value == to || !transitionable_from_current_value {
1177 existing_transition.state = AnimationState::Canceled;
1178 self.dirty = true;
1179 return;
1180 }
1181
1182 if duration + delay <= 0.0 {
1188 existing_transition.state = AnimationState::Canceled;
1189 self.dirty = true;
1190 return;
1191 }
1192
1193 if existing_transition.reversing_adjusted_start_value == to {
1199 existing_transition.state = AnimationState::Canceled;
1200
1201 let mut transition = Transition::new(
1202 now + delay, delay,
1204 duration,
1205 from,
1206 to,
1207 &timing_function,
1208 );
1209
1210 transition.update_for_possibly_reversed_transition(
1213 &existing_transition,
1214 delay,
1215 now,
1216 );
1217
1218 self.transitions.push(transition);
1219 self.dirty = true;
1220 return;
1221 }
1222
1223 existing_transition.state = AnimationState::Canceled;
1232 self.transitions.push(Transition::new(
1233 now + delay, delay,
1235 duration,
1236 current_value,
1237 to,
1238 &timing_function,
1239 ));
1240 self.dirty = true;
1241 }
1242 }
1243
1244 fn get_value_map_for_transitions(
1248 &self,
1249 now: f64,
1250 ignore_transitions: IgnoreTransitions,
1251 ) -> Option<AnimationValueMap> {
1252 if !self.has_active_transition() {
1253 return None;
1254 }
1255
1256 let mut map =
1257 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1258 for transition in &self.transitions {
1259 match ignore_transitions {
1260 IgnoreTransitions::Canceled => {
1261 if transition.state == AnimationState::Canceled {
1262 continue;
1263 }
1264 },
1265 IgnoreTransitions::CanceledAndFinished => {
1266 if transition.state == AnimationState::Canceled
1267 || transition.state == AnimationState::Finished
1268 {
1269 continue;
1270 }
1271 },
1272 }
1273
1274 let value = transition.calculate_value(now);
1275 map.insert(value.id().to_owned(), value);
1276 }
1277
1278 Some(map)
1279 }
1280
1281 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1284 if !self.has_active_animation() {
1285 return None;
1286 }
1287
1288 let mut map = Default::default();
1289 for animation in &self.animations {
1290 animation.get_property_declaration_at_time(now, &mut map);
1291 }
1292
1293 Some(map)
1294 }
1295}
1296
1297#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1298pub struct AnimationSetKey {
1300 pub node: OpaqueNode,
1302 pub pseudo_element: Option<PseudoElement>,
1305}
1306
1307impl AnimationSetKey {
1308 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1310 AnimationSetKey {
1311 node,
1312 pseudo_element,
1313 }
1314 }
1315
1316 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1318 AnimationSetKey {
1319 node,
1320 pseudo_element: None,
1321 }
1322 }
1323
1324 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1326 AnimationSetKey {
1327 node,
1328 pseudo_element: Some(pseudo_element),
1329 }
1330 }
1331}
1332
1333#[derive(Clone, Debug, Default, MallocSizeOf)]
1334pub struct DocumentAnimationSet {
1336 #[ignore_malloc_size_of = "Arc is hard"]
1338 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1339}
1340
1341impl DocumentAnimationSet {
1342 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1344 self.sets
1345 .read()
1346 .get(key)
1347 .map_or(false, |set| set.has_active_animation())
1348 }
1349
1350 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1352 self.sets
1353 .read()
1354 .get(key)
1355 .map_or(false, |set| set.has_active_transition())
1356 }
1357
1358 pub fn get_animation_declarations(
1361 &self,
1362 key: &AnimationSetKey,
1363 time: f64,
1364 shared_lock: &SharedRwLock,
1365 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1366 self.sets
1367 .read()
1368 .get(key)
1369 .and_then(|set| set.get_value_map_for_active_animations(time))
1370 .map(|map| {
1371 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1372 Arc::new(shared_lock.wrap(block))
1373 })
1374 }
1375
1376 pub fn get_transition_declarations(
1379 &self,
1380 key: &AnimationSetKey,
1381 time: f64,
1382 shared_lock: &SharedRwLock,
1383 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1384 self.sets
1385 .read()
1386 .get(key)
1387 .and_then(|set| {
1388 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1389 })
1390 .map(|map| {
1391 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1392 Arc::new(shared_lock.wrap(block))
1393 })
1394 }
1395
1396 pub fn get_all_declarations(
1399 &self,
1400 key: &AnimationSetKey,
1401 time: f64,
1402 shared_lock: &SharedRwLock,
1403 ) -> AnimationDeclarations {
1404 let sets = self.sets.read();
1405 let set = match sets.get(key) {
1406 Some(set) => set,
1407 None => return Default::default(),
1408 };
1409
1410 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1411 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1412 Arc::new(shared_lock.wrap(block))
1413 });
1414 let transitions = set
1415 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1416 .map(|map| {
1417 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1418 Arc::new(shared_lock.wrap(block))
1419 });
1420 AnimationDeclarations {
1421 animations,
1422 transitions,
1423 }
1424 }
1425
1426 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1428 if let Some(set) = self.sets.write().get_mut(key) {
1429 set.cancel_all_animations();
1430 }
1431 }
1432}
1433
1434pub fn start_transitions_if_applicable(
1437 context: &SharedStyleContext,
1438 old_style: &ComputedValues,
1439 new_style: &Arc<ComputedValues>,
1440 animation_state: &mut ElementAnimationSet,
1441) -> PropertyDeclarationIdSet {
1442 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1457 transition_properties.reverse();
1458
1459 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1460 for transition in transition_properties {
1461 let physical_property = transition
1462 .property
1463 .as_borrowed()
1464 .to_physical(new_style.writing_mode);
1465 if properties_that_transition.contains(physical_property) {
1466 continue;
1467 }
1468
1469 properties_that_transition.insert(physical_property);
1470 animation_state.start_transition_if_applicable(
1471 context,
1472 &physical_property,
1473 transition.index,
1474 old_style,
1475 new_style,
1476 );
1477 }
1478
1479 properties_that_transition
1480}
1481
1482pub fn maybe_start_animations<E>(
1485 element: E,
1486 context: &SharedStyleContext,
1487 new_style: &Arc<ComputedValues>,
1488 animation_state: &mut ElementAnimationSet,
1489 resolver: &mut StyleResolverForElement<E>,
1490) where
1491 E: TElement,
1492{
1493 let style = new_style.get_ui();
1494 for (i, name) in style.animation_name_iter().enumerate() {
1495 let name = match name.as_atom() {
1496 Some(atom) => atom,
1497 None => continue,
1498 };
1499
1500 debug!("maybe_start_animations: name={}", name);
1501 let duration = style.animation_duration_mod(i).seconds() as f64;
1502 if duration == 0. {
1503 continue;
1504 }
1505
1506 let Some(keyframe_animation) = context.stylist.lookup_keyframes(name, element) else {
1507 continue;
1508 };
1509
1510 debug!("maybe_start_animations: animation {} found", name);
1511
1512 let delay = style.animation_delay_mod(i).seconds();
1516
1517 let iteration_count = style.animation_iteration_count_mod(i);
1518 let iteration_state = if iteration_count.0.is_infinite() {
1519 KeyframesIterationState::Infinite(0.0)
1520 } else {
1521 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1522 };
1523
1524 let animation_direction = style.animation_direction_mod(i);
1525
1526 let initial_direction = match animation_direction {
1527 AnimationDirection::Normal | AnimationDirection::Alternate => {
1528 AnimationDirection::Normal
1529 },
1530 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1531 AnimationDirection::Reverse
1532 },
1533 };
1534
1535 let now = context.current_time_for_animations;
1536 let started_at = now + delay as f64;
1537 let mut starting_progress = (now - started_at) / duration;
1538 let state = match style.animation_play_state_mod(i) {
1539 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1540 AnimationPlayState::Running => AnimationState::Pending,
1541 };
1542
1543 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1544 element,
1545 &keyframe_animation,
1546 context,
1547 new_style,
1548 style.animation_timing_function_mod(i),
1549 resolver,
1550 );
1551
1552 let mut new_animation = Animation {
1553 name: name.clone(),
1554 properties_changed: keyframe_animation.properties_changed.clone(),
1555 computed_steps,
1556 started_at,
1557 duration,
1558 fill_mode: style.animation_fill_mode_mod(i),
1559 delay: delay as f64,
1560 iteration_state,
1561 state,
1562 direction: animation_direction,
1563 current_direction: initial_direction,
1564 cascade_style: new_style.clone(),
1565 is_new: true,
1566 };
1567
1568 while starting_progress > 1. && !new_animation.on_last_iteration() {
1571 new_animation.iterate();
1572 starting_progress -= 1.;
1573 }
1574
1575 animation_state.dirty = true;
1576
1577 for existing_animation in animation_state.animations.iter_mut() {
1579 if existing_animation.state == AnimationState::Canceled {
1580 continue;
1581 }
1582
1583 if new_animation.name == existing_animation.name {
1584 existing_animation
1585 .update_from_other(&new_animation, context.current_time_for_animations);
1586 return;
1587 }
1588 }
1589
1590 animation_state.animations.push(new_animation);
1591 }
1592}