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 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
156 let mut current_step = IntermediateComputedKeyframe::new(0.);
157 for step in animation.steps.iter() {
158 let start_percentage = step.start_percentage.0;
159 if start_percentage != current_step.start_percentage {
160 let new_step = IntermediateComputedKeyframe::new(start_percentage);
161 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
162 }
163
164 current_step.update_from_step(step, context, base_style);
165 }
166 intermediate_steps.push(current_step);
167
168 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
171 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
172
173 intermediate_steps
174 }
175
176 fn update_from_step(
177 &mut self,
178 step: &KeyframesStep,
179 context: &SharedStyleContext,
180 base_style: &ComputedValues,
181 ) {
182 let guard = &context.guards.author;
185 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
186 self.timing_function = Some(timing_function.to_computed_value_without_context());
187 }
188
189 let block = match step.value {
190 KeyframesStepValue::ComputedValues => return,
191 KeyframesStepValue::Declarations { ref block } => block,
192 };
193
194 let guard = block.read_with(&guard);
197 for declaration in guard.normal_declaration_iter() {
198 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
199 if id == LonghandId::Display {
200 continue;
201 }
202
203 if !id.is_animatable() {
204 continue;
205 }
206 }
207
208 self.declarations.push(
209 declaration.to_physical(base_style.writing_mode),
210 Importance::Normal,
211 );
212 }
213 }
214
215 fn resolve_style<E>(
216 self,
217 element: E,
218 context: &SharedStyleContext,
219 base_style: &Arc<ComputedValues>,
220 resolver: &mut StyleResolverForElement<E>,
221 ) -> Arc<ComputedValues>
222 where
223 E: TElement,
224 {
225 if !self.declarations.any_normal() {
226 return base_style.clone();
227 }
228
229 let document = element.as_node().owner_doc();
230 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
231 let mut important_rules_changed = false;
232 let rule_node = base_style.rules().clone();
233 let new_node = context.stylist.rule_tree().update_rule_at_level(
234 CascadeLevel::Animations,
235 LayerOrder::root(),
236 Some(locked_block.borrow_arc()),
237 &rule_node,
238 &context.guards,
239 &mut important_rules_changed,
240 );
241
242 if new_node.is_none() {
243 return base_style.clone();
244 }
245
246 let inputs = CascadeInputs {
247 rules: new_node,
248 visited_rules: base_style.visited_rules().cloned(),
249 flags: base_style.flags.for_cascade_inputs(),
250 };
251 resolver
252 .cascade_style_and_visited_with_default_parents(inputs)
253 .0
254 }
255}
256
257#[derive(Clone, MallocSizeOf)]
259struct ComputedKeyframe {
260 timing_function: TimingFunction,
263
264 start_percentage: f32,
267
268 values: Box<[AnimationValue]>,
271}
272
273impl ComputedKeyframe {
274 fn generate_for_keyframes<E>(
275 element: E,
276 animation: &KeyframesAnimation,
277 context: &SharedStyleContext,
278 base_style: &Arc<ComputedValues>,
279 default_timing_function: TimingFunction,
280 resolver: &mut StyleResolverForElement<E>,
281 ) -> Box<[Self]>
282 where
283 E: TElement,
284 {
285 let mut animating_properties = PropertyDeclarationIdSet::default();
286 for property in animation.properties_changed.iter() {
287 debug_assert!(property.is_animatable());
288 animating_properties.insert(property.to_physical(base_style.writing_mode));
289 }
290
291 let animation_values_from_style: Vec<AnimationValue> = animating_properties
292 .iter()
293 .map(|property| {
294 AnimationValue::from_computed_values(property, &**base_style)
295 .expect("Unexpected non-animatable property.")
296 })
297 .collect();
298
299 let intermediate_steps =
300 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
301
302 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
303 for (step_index, step) in intermediate_steps.into_iter().enumerate() {
304 let start_percentage = step.start_percentage;
305 let properties_changed_in_step = step.declarations.property_ids().clone();
306 let step_timing_function = step.timing_function.clone();
307 let step_style = step.resolve_style(element, context, base_style, resolver);
308 let timing_function =
309 step_timing_function.unwrap_or_else(|| default_timing_function.clone());
310
311 let values = {
312 let default_values = if start_percentage == 0. || start_percentage == 1.0 {
319 animation_values_from_style.as_slice()
320 } else {
321 debug_assert!(step_index != 0);
322 &computed_steps[step_index - 1].values
323 };
324
325 animating_properties
329 .iter()
330 .zip(default_values.iter())
331 .map(|(property_declaration, default_value)| {
332 if properties_changed_in_step.contains(property_declaration) {
333 AnimationValue::from_computed_values(property_declaration, &step_style)
334 .unwrap_or_else(|| default_value.clone())
335 } else {
336 default_value.clone()
337 }
338 })
339 .collect()
340 };
341
342 computed_steps.push(ComputedKeyframe {
343 timing_function,
344 start_percentage,
345 values,
346 });
347 }
348 computed_steps.into_boxed_slice()
349 }
350}
351
352#[derive(Clone, MallocSizeOf)]
354pub struct Animation {
355 pub name: Atom,
357
358 properties_changed: PropertyDeclarationIdSet,
360
361 computed_steps: Box<[ComputedKeyframe]>,
363
364 pub started_at: f64,
367
368 pub duration: f64,
370
371 pub delay: f64,
373
374 pub fill_mode: AnimationFillMode,
376
377 pub iteration_state: KeyframesIterationState,
379
380 pub state: AnimationState,
382
383 pub direction: AnimationDirection,
385
386 pub current_direction: AnimationDirection,
388
389 #[ignore_malloc_size_of = "ComputedValues"]
392 pub cascade_style: Arc<ComputedValues>,
393
394 pub is_new: bool,
397}
398
399impl Animation {
400 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
402 let new_ui = new_style.get_ui();
403 let index = new_ui
404 .animation_name_iter()
405 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
406 let index = match index {
407 Some(index) => index,
408 None => return true,
409 };
410
411 new_ui.animation_duration_mod(index).seconds() == 0.
412 }
413
414 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
418 if !self.iteration_over(time) {
419 return false;
420 }
421
422 if self.state != AnimationState::Running {
424 return false;
425 }
426
427 if self.on_last_iteration() {
428 return false;
429 }
430
431 self.iterate();
432 true
433 }
434
435 fn iterate(&mut self) {
436 debug_assert!(!self.on_last_iteration());
437
438 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
439 *current = (*current + 1.).min(max);
440 }
441
442 if let AnimationState::Paused(ref mut progress) = self.state {
443 debug_assert!(*progress > 1.);
444 *progress -= 1.;
445 }
446
447 self.started_at += self.duration;
449 match self.direction {
450 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
451 self.current_direction = match self.current_direction {
452 AnimationDirection::Normal => AnimationDirection::Reverse,
453 AnimationDirection::Reverse => AnimationDirection::Normal,
454 _ => unreachable!(),
455 };
456 },
457 _ => {},
458 }
459 }
460
461 pub fn current_iteration_end_progress(&self) -> f64 {
466 match self.iteration_state {
467 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
468 KeyframesIterationState::Infinite(_) => 1.,
469 }
470 }
471
472 pub fn current_iteration_duration(&self) -> f64 {
475 self.current_iteration_end_progress() * self.duration
476 }
477
478 fn iteration_over(&self, time: f64) -> bool {
481 time > (self.started_at + self.current_iteration_duration())
482 }
483
484 fn on_last_iteration(&self) -> bool {
486 match self.iteration_state {
487 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
488 KeyframesIterationState::Infinite(_) => false,
489 }
490 }
491
492 pub fn has_ended(&self, time: f64) -> bool {
496 if !self.on_last_iteration() {
497 return false;
498 }
499
500 let progress = match self.state {
501 AnimationState::Finished => return true,
502 AnimationState::Paused(progress) => progress,
503 AnimationState::Running => (time - self.started_at) / self.duration,
504 AnimationState::Pending | AnimationState::Canceled => return false,
505 };
506
507 progress >= self.current_iteration_end_progress()
508 }
509
510 pub fn update_from_other(&mut self, other: &Self, now: f64) {
518 use self::AnimationState::*;
519
520 debug!(
521 "KeyframesAnimationState::update_from_other({:?}, {:?})",
522 self, other
523 );
524
525 let old_started_at = self.started_at;
528 let old_duration = self.duration;
529 let old_direction = self.current_direction;
530 let old_state = self.state.clone();
531 let old_iteration_state = self.iteration_state.clone();
532
533 *self = other.clone();
534
535 self.started_at = old_started_at;
536 self.current_direction = old_direction;
537
538 match (&mut self.iteration_state, old_iteration_state) {
542 (
543 &mut KeyframesIterationState::Finite(ref mut iters, _),
544 KeyframesIterationState::Finite(old_iters, _),
545 ) => *iters = old_iters,
546 _ => {},
547 }
548
549 let new_state = std::mem::replace(&mut self.state, Running);
552 if old_state == Finished && self.has_ended(now) {
553 self.state = Finished;
554 } else {
555 self.state = new_state;
556 }
557
558 match (&mut self.state, &old_state) {
565 (&mut Pending, &Paused(progress)) => {
566 self.started_at = now - (self.duration * progress);
567 },
568 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
569 (&mut Paused(ref mut progress), &Running) => {
570 *progress = (now - old_started_at) / old_duration
571 },
572 _ => {},
573 }
574
575 if self.state == Pending && self.started_at <= now && old_state != Pending {
578 self.state = Running;
579 }
580 }
581
582 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
585 debug_assert!(!self.computed_steps.is_empty());
586
587 let total_progress = match self.state {
588 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
589 (now - self.started_at) / self.duration
590 },
591 AnimationState::Paused(progress) => progress,
592 AnimationState::Canceled => return,
593 };
594
595 if total_progress < 0.
596 && self.fill_mode != AnimationFillMode::Backwards
597 && self.fill_mode != AnimationFillMode::Both
598 {
599 return;
600 }
601 if self.has_ended(now)
602 && self.fill_mode != AnimationFillMode::Forwards
603 && self.fill_mode != AnimationFillMode::Both
604 {
605 return;
606 }
607 let total_progress = total_progress
608 .min(self.current_iteration_end_progress())
609 .max(0.0);
610
611 let next_keyframe_index;
613 let prev_keyframe_index;
614 let num_steps = self.computed_steps.len();
615 match self.current_direction {
616 AnimationDirection::Normal => {
617 next_keyframe_index = self
618 .computed_steps
619 .iter()
620 .position(|step| total_progress as f32 <= step.start_percentage);
621 prev_keyframe_index = next_keyframe_index
622 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
623 .unwrap_or(0);
624 },
625 AnimationDirection::Reverse => {
626 next_keyframe_index = self
627 .computed_steps
628 .iter()
629 .rev()
630 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
631 .map(|pos| num_steps - pos - 1);
632 prev_keyframe_index = next_keyframe_index
633 .and_then(|pos| {
634 if pos != num_steps - 1 {
635 Some(pos + 1)
636 } else {
637 None
638 }
639 })
640 .unwrap_or(num_steps - 1)
641 },
642 _ => unreachable!(),
643 }
644
645 debug!(
646 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
647 prev_keyframe_index, next_keyframe_index
648 );
649
650 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
651 let next_keyframe = match next_keyframe_index {
652 Some(index) => &self.computed_steps[index],
653 None => return,
654 };
655
656 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
659 for value in keyframe.values.iter() {
660 map.insert(value.id().to_owned(), value.clone());
661 }
662 };
663 if total_progress <= 0.0 {
664 add_declarations_to_map(&prev_keyframe);
665 return;
666 }
667 if total_progress >= 1.0 {
668 add_declarations_to_map(&next_keyframe);
669 return;
670 }
671
672 let percentage_between_keyframes =
673 (next_keyframe.start_percentage - prev_keyframe.start_percentage).abs() as f64;
674 let duration_between_keyframes = percentage_between_keyframes * self.duration;
675 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
676 AnimationDirection::Normal => prev_keyframe.start_percentage as f64,
677 AnimationDirection::Reverse => 1. - prev_keyframe.start_percentage as f64,
678 _ => unreachable!(),
679 };
680 let progress_between_keyframes = (total_progress
681 - direction_aware_prev_keyframe_start_percentage)
682 / percentage_between_keyframes;
683
684 for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) {
685 let animation = PropertyAnimation {
686 from: from.clone(),
687 to: to.clone(),
688 timing_function: prev_keyframe.timing_function.clone(),
689 duration: duration_between_keyframes as f64,
690 };
691
692 let value = animation.calculate_value(progress_between_keyframes);
693 map.insert(value.id().to_owned(), value);
694 }
695 }
696}
697
698impl fmt::Debug for Animation {
699 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
700 f.debug_struct("Animation")
701 .field("name", &self.name)
702 .field("started_at", &self.started_at)
703 .field("duration", &self.duration)
704 .field("delay", &self.delay)
705 .field("iteration_state", &self.iteration_state)
706 .field("state", &self.state)
707 .field("direction", &self.direction)
708 .field("current_direction", &self.current_direction)
709 .field("cascade_style", &())
710 .finish()
711 }
712}
713
714#[derive(Clone, Debug, MallocSizeOf)]
716pub struct Transition {
717 pub start_time: f64,
720
721 pub delay: f64,
723
724 pub property_animation: PropertyAnimation,
726
727 pub state: AnimationState,
729
730 pub is_new: bool,
733
734 pub reversing_adjusted_start_value: AnimationValue,
737
738 pub reversing_shortening_factor: f64,
741}
742
743impl Transition {
744 fn new(
745 start_time: f64,
746 delay: f64,
747 duration: f64,
748 from: AnimationValue,
749 to: AnimationValue,
750 timing_function: &TimingFunction,
751 ) -> Self {
752 let property_animation = PropertyAnimation {
753 from: from.clone(),
754 to,
755 timing_function: timing_function.clone(),
756 duration,
757 };
758 Self {
759 start_time,
760 delay,
761 property_animation,
762 state: AnimationState::Pending,
763 is_new: true,
764 reversing_adjusted_start_value: from,
765 reversing_shortening_factor: 1.0,
766 }
767 }
768
769 fn update_for_possibly_reversed_transition(
770 &mut self,
771 replaced_transition: &Transition,
772 delay: f64,
773 now: f64,
774 ) {
775 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
784 return;
785 }
786
787 let replaced_animation = &replaced_transition.property_animation;
789 self.reversing_adjusted_start_value = replaced_animation.to.clone();
790
791 let transition_progress = ((now - replaced_transition.start_time)
798 / (replaced_transition.property_animation.duration))
799 .min(1.0)
800 .max(0.0);
801 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
802 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
803 self.reversing_shortening_factor = ((timing_function_output
804 * old_reversing_shortening_factor)
805 + (1.0 - old_reversing_shortening_factor))
806 .abs()
807 .min(1.0)
808 .max(0.0);
809
810 self.start_time = if delay >= 0. {
816 now + delay
817 } else {
818 now + (self.reversing_shortening_factor * delay)
819 };
820
821 self.property_animation.duration *= self.reversing_shortening_factor;
824
825 let procedure = Procedure::Interpolate {
828 progress: timing_function_output,
829 };
830 match replaced_animation
831 .from
832 .animate(&replaced_animation.to, procedure)
833 {
834 Ok(new_start) => self.property_animation.from = new_start,
835 Err(..) => {},
836 }
837 }
838
839 pub fn has_ended(&self, time: f64) -> bool {
843 time >= self.start_time + (self.property_animation.duration)
844 }
845
846 pub fn calculate_value(&self, time: f64) -> AnimationValue {
848 let progress = (time - self.start_time) / (self.property_animation.duration);
849 self.property_animation
850 .calculate_value(progress.clamp(0.0, 1.0))
851 }
852}
853
854#[derive(Debug, Default, MallocSizeOf)]
856pub struct ElementAnimationSet {
857 pub animations: Vec<Animation>,
859
860 pub transitions: Vec<Transition>,
862
863 pub dirty: bool,
866}
867
868impl ElementAnimationSet {
869 pub fn cancel_all_animations(&mut self) {
872 self.dirty = !self.animations.is_empty();
873 for animation in self.animations.iter_mut() {
874 animation.state = AnimationState::Canceled;
875 }
876 self.cancel_active_transitions();
877 }
878
879 fn cancel_active_transitions(&mut self) {
880 for transition in self.transitions.iter_mut() {
881 if transition.state != AnimationState::Finished {
882 self.dirty = true;
883 transition.state = AnimationState::Canceled;
884 }
885 }
886 }
887
888 pub fn apply_active_animations(
890 &self,
891 context: &SharedStyleContext,
892 style: &mut Arc<ComputedValues>,
893 ) {
894 let now = context.current_time_for_animations;
895 let mutable_style = Arc::make_mut(style);
896 if let Some(map) = self.get_value_map_for_active_animations(now) {
897 for value in map.values() {
898 value.set_in_style_for_servo(mutable_style);
899 }
900 }
901
902 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
903 for value in map.values() {
904 value.set_in_style_for_servo(mutable_style);
905 }
906 }
907 }
908
909 pub fn clear_canceled_animations(&mut self) {
911 self.animations
912 .retain(|animation| animation.state != AnimationState::Canceled);
913 self.transitions
914 .retain(|animation| animation.state != AnimationState::Canceled);
915 }
916
917 pub fn is_empty(&self) -> bool {
920 self.animations.is_empty() && self.transitions.is_empty()
921 }
922
923 pub fn needs_animation_ticks(&self) -> bool {
926 self.animations
927 .iter()
928 .any(|animation| animation.state.needs_to_be_ticked())
929 || self
930 .transitions
931 .iter()
932 .any(|transition| transition.state.needs_to_be_ticked())
933 }
934
935 pub fn running_animation_and_transition_count(&self) -> usize {
937 self.animations
938 .iter()
939 .filter(|animation| animation.state.needs_to_be_ticked())
940 .count()
941 + self
942 .transitions
943 .iter()
944 .filter(|transition| transition.state.needs_to_be_ticked())
945 .count()
946 }
947
948 pub fn has_active_animation(&self) -> bool {
950 self.animations
951 .iter()
952 .any(|animation| animation.state != AnimationState::Canceled)
953 }
954
955 pub fn has_active_transition(&self) -> bool {
957 self.transitions
958 .iter()
959 .any(|transition| transition.state != AnimationState::Canceled)
960 }
961
962 pub fn update_animations_for_new_style<E>(
965 &mut self,
966 element: E,
967 context: &SharedStyleContext,
968 new_style: &Arc<ComputedValues>,
969 resolver: &mut StyleResolverForElement<E>,
970 ) where
971 E: TElement,
972 {
973 for animation in self.animations.iter_mut() {
974 if animation.is_cancelled_in_new_style(new_style) {
975 animation.state = AnimationState::Canceled;
976 }
977 }
978
979 maybe_start_animations(element, &context, &new_style, self, resolver);
980 }
981
982 pub fn update_transitions_for_new_style(
985 &mut self,
986 might_need_transitions_update: bool,
987 context: &SharedStyleContext,
988 old_style: Option<&Arc<ComputedValues>>,
989 after_change_style: &Arc<ComputedValues>,
990 ) {
991 let mut before_change_style = match old_style {
994 Some(old_style) => Arc::clone(old_style),
995 None => return,
996 };
997
998 if after_change_style.get_box().clone_display().is_none() {
1000 self.cancel_active_transitions();
1001 return;
1002 }
1003
1004 if !might_need_transitions_update {
1005 return;
1006 }
1007
1008 if self.has_active_transition() || self.has_active_animation() {
1010 self.apply_active_animations(context, &mut before_change_style);
1011 }
1012
1013 let transitioning_properties = start_transitions_if_applicable(
1014 context,
1015 &before_change_style,
1016 after_change_style,
1017 self,
1018 );
1019
1020 for transition in self.transitions.iter_mut() {
1033 if transition.state == AnimationState::Finished
1034 || transition.state == AnimationState::Canceled
1035 {
1036 continue;
1037 }
1038 if transitioning_properties.contains(transition.property_animation.property_id()) {
1039 continue;
1040 }
1041 transition.state = AnimationState::Canceled;
1042 self.dirty = true;
1043 }
1044 }
1045
1046 fn start_transition_if_applicable(
1047 &mut self,
1048 context: &SharedStyleContext,
1049 property_declaration_id: &PropertyDeclarationId,
1050 index: usize,
1051 old_style: &ComputedValues,
1052 new_style: &Arc<ComputedValues>,
1053 ) {
1054 let style = new_style.get_ui();
1055 let allow_discrete =
1056 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1057
1058 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1060 else {
1061 return;
1062 };
1063 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1064 else {
1065 return;
1066 };
1067
1068 let timing_function = style.transition_timing_function_mod(index);
1069 let duration = style.transition_duration_mod(index).seconds() as f64;
1070 let delay = style.transition_delay_mod(index).seconds() as f64;
1071 let now = context.current_time_for_animations;
1072 let transitionable = property_declaration_id.is_animatable()
1073 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1074 && (allow_discrete || from.interpolable_with(&to));
1075
1076 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1077 transition.property_animation.property_id() == *property_declaration_id
1078 });
1079
1080 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1095 transition.state != AnimationState::Finished
1096 && transition.state != AnimationState::Canceled
1097 });
1098 let no_completed_transition_or_end_values_differ =
1099 existing_transition.as_ref().is_none_or(|transition| {
1100 transition.state != AnimationState::Finished
1101 || transition.property_animation.to != to
1102 });
1103 if !has_running_transition
1104 && from != to
1105 && transitionable
1106 && no_completed_transition_or_end_values_differ
1107 && (duration + delay > 0.0)
1108 {
1109 self.transitions.push(Transition::new(
1120 now + delay, delay,
1122 duration,
1123 from,
1124 to,
1125 &timing_function,
1126 ));
1127 self.dirty = true;
1128 return;
1129 }
1130
1131 let Some(existing_transition) = existing_transition.as_mut() else {
1154 return;
1155 };
1156
1157 if has_running_transition && existing_transition.property_animation.to != to {
1162 let current_value = existing_transition.calculate_value(now);
1167 let transitionable_from_current_value =
1168 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1169 if current_value == to || !transitionable_from_current_value {
1170 existing_transition.state = AnimationState::Canceled;
1171 self.dirty = true;
1172 return;
1173 }
1174
1175 if duration + delay <= 0.0 {
1181 existing_transition.state = AnimationState::Canceled;
1182 self.dirty = true;
1183 return;
1184 }
1185
1186 if existing_transition.reversing_adjusted_start_value == to {
1192 existing_transition.state = AnimationState::Canceled;
1193
1194 let mut transition = Transition::new(
1195 now + delay, delay,
1197 duration,
1198 from,
1199 to,
1200 &timing_function,
1201 );
1202
1203 transition.update_for_possibly_reversed_transition(
1206 &existing_transition,
1207 delay,
1208 now,
1209 );
1210
1211 self.transitions.push(transition);
1212 self.dirty = true;
1213 return;
1214 }
1215
1216 existing_transition.state = AnimationState::Canceled;
1225 self.transitions.push(Transition::new(
1226 now + delay, delay,
1228 duration,
1229 current_value,
1230 to,
1231 &timing_function,
1232 ));
1233 self.dirty = true;
1234 }
1235 }
1236
1237 fn get_value_map_for_transitions(
1241 &self,
1242 now: f64,
1243 ignore_transitions: IgnoreTransitions,
1244 ) -> Option<AnimationValueMap> {
1245 if !self.has_active_transition() {
1246 return None;
1247 }
1248
1249 let mut map =
1250 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1251 for transition in &self.transitions {
1252 match ignore_transitions {
1253 IgnoreTransitions::Canceled => {
1254 if transition.state == AnimationState::Canceled {
1255 continue;
1256 }
1257 },
1258 IgnoreTransitions::CanceledAndFinished => {
1259 if transition.state == AnimationState::Canceled
1260 || transition.state == AnimationState::Finished
1261 {
1262 continue;
1263 }
1264 },
1265 }
1266
1267 let value = transition.calculate_value(now);
1268 map.insert(value.id().to_owned(), value);
1269 }
1270
1271 Some(map)
1272 }
1273
1274 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1277 if !self.has_active_animation() {
1278 return None;
1279 }
1280
1281 let mut map = Default::default();
1282 for animation in &self.animations {
1283 animation.get_property_declaration_at_time(now, &mut map);
1284 }
1285
1286 Some(map)
1287 }
1288}
1289
1290#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1291pub struct AnimationSetKey {
1293 pub node: OpaqueNode,
1295 pub pseudo_element: Option<PseudoElement>,
1298}
1299
1300impl AnimationSetKey {
1301 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1303 AnimationSetKey {
1304 node,
1305 pseudo_element,
1306 }
1307 }
1308
1309 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1311 AnimationSetKey {
1312 node,
1313 pseudo_element: None,
1314 }
1315 }
1316
1317 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1319 AnimationSetKey {
1320 node,
1321 pseudo_element: Some(pseudo_element),
1322 }
1323 }
1324}
1325
1326#[derive(Clone, Debug, Default, MallocSizeOf)]
1327pub struct DocumentAnimationSet {
1329 #[ignore_malloc_size_of = "Arc is hard"]
1331 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1332}
1333
1334impl DocumentAnimationSet {
1335 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1337 self.sets
1338 .read()
1339 .get(key)
1340 .map_or(false, |set| set.has_active_animation())
1341 }
1342
1343 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1345 self.sets
1346 .read()
1347 .get(key)
1348 .map_or(false, |set| set.has_active_transition())
1349 }
1350
1351 pub fn get_animation_declarations(
1354 &self,
1355 key: &AnimationSetKey,
1356 time: f64,
1357 shared_lock: &SharedRwLock,
1358 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1359 self.sets
1360 .read()
1361 .get(key)
1362 .and_then(|set| set.get_value_map_for_active_animations(time))
1363 .map(|map| {
1364 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1365 Arc::new(shared_lock.wrap(block))
1366 })
1367 }
1368
1369 pub fn get_transition_declarations(
1372 &self,
1373 key: &AnimationSetKey,
1374 time: f64,
1375 shared_lock: &SharedRwLock,
1376 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1377 self.sets
1378 .read()
1379 .get(key)
1380 .and_then(|set| {
1381 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1382 })
1383 .map(|map| {
1384 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1385 Arc::new(shared_lock.wrap(block))
1386 })
1387 }
1388
1389 pub fn get_all_declarations(
1392 &self,
1393 key: &AnimationSetKey,
1394 time: f64,
1395 shared_lock: &SharedRwLock,
1396 ) -> AnimationDeclarations {
1397 let sets = self.sets.read();
1398 let set = match sets.get(key) {
1399 Some(set) => set,
1400 None => return Default::default(),
1401 };
1402
1403 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1404 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1405 Arc::new(shared_lock.wrap(block))
1406 });
1407 let transitions = set
1408 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1409 .map(|map| {
1410 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1411 Arc::new(shared_lock.wrap(block))
1412 });
1413 AnimationDeclarations {
1414 animations,
1415 transitions,
1416 }
1417 }
1418
1419 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1421 if let Some(set) = self.sets.write().get_mut(key) {
1422 set.cancel_all_animations();
1423 }
1424 }
1425}
1426
1427pub fn start_transitions_if_applicable(
1430 context: &SharedStyleContext,
1431 old_style: &ComputedValues,
1432 new_style: &Arc<ComputedValues>,
1433 animation_state: &mut ElementAnimationSet,
1434) -> PropertyDeclarationIdSet {
1435 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1450 transition_properties.reverse();
1451
1452 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1453 for transition in transition_properties {
1454 let physical_property = transition
1455 .property
1456 .as_borrowed()
1457 .to_physical(new_style.writing_mode);
1458 if properties_that_transition.contains(physical_property) {
1459 continue;
1460 }
1461
1462 properties_that_transition.insert(physical_property);
1463 animation_state.start_transition_if_applicable(
1464 context,
1465 &physical_property,
1466 transition.index,
1467 old_style,
1468 new_style,
1469 );
1470 }
1471
1472 properties_that_transition
1473}
1474
1475pub fn maybe_start_animations<E>(
1478 element: E,
1479 context: &SharedStyleContext,
1480 new_style: &Arc<ComputedValues>,
1481 animation_state: &mut ElementAnimationSet,
1482 resolver: &mut StyleResolverForElement<E>,
1483) where
1484 E: TElement,
1485{
1486 let style = new_style.get_ui();
1487 for (i, name) in style.animation_name_iter().enumerate() {
1488 let name = match name.as_atom() {
1489 Some(atom) => atom,
1490 None => continue,
1491 };
1492
1493 debug!("maybe_start_animations: name={}", name);
1494 let duration = style.animation_duration_mod(i).seconds() as f64;
1495 if duration == 0. {
1496 continue;
1497 }
1498
1499 let keyframe_animation = match context.stylist.lookup_keyframes(name, element) {
1500 Some(animation) => animation,
1501 None => continue,
1502 };
1503
1504 debug!("maybe_start_animations: animation {} found", name);
1505
1506 if keyframe_animation.steps.is_empty() {
1511 continue;
1512 }
1513
1514 let delay = style.animation_delay_mod(i).seconds();
1518
1519 let iteration_count = style.animation_iteration_count_mod(i);
1520 let iteration_state = if iteration_count.0.is_infinite() {
1521 KeyframesIterationState::Infinite(0.0)
1522 } else {
1523 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1524 };
1525
1526 let animation_direction = style.animation_direction_mod(i);
1527
1528 let initial_direction = match animation_direction {
1529 AnimationDirection::Normal | AnimationDirection::Alternate => {
1530 AnimationDirection::Normal
1531 },
1532 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1533 AnimationDirection::Reverse
1534 },
1535 };
1536
1537 let now = context.current_time_for_animations;
1538 let started_at = now + delay as f64;
1539 let mut starting_progress = (now - started_at) / duration;
1540 let state = match style.animation_play_state_mod(i) {
1541 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1542 AnimationPlayState::Running => AnimationState::Pending,
1543 };
1544
1545 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1546 element,
1547 &keyframe_animation,
1548 context,
1549 new_style,
1550 style.animation_timing_function_mod(i),
1551 resolver,
1552 );
1553
1554 let mut new_animation = Animation {
1555 name: name.clone(),
1556 properties_changed: keyframe_animation.properties_changed.clone(),
1557 computed_steps,
1558 started_at,
1559 duration,
1560 fill_mode: style.animation_fill_mode_mod(i),
1561 delay: delay as f64,
1562 iteration_state,
1563 state,
1564 direction: animation_direction,
1565 current_direction: initial_direction,
1566 cascade_style: new_style.clone(),
1567 is_new: true,
1568 };
1569
1570 while starting_progress > 1. && !new_animation.on_last_iteration() {
1573 new_animation.iterate();
1574 starting_progress -= 1.;
1575 }
1576
1577 animation_state.dirty = true;
1578
1579 for existing_animation in animation_state.animations.iter_mut() {
1581 if existing_animation.state == AnimationState::Canceled {
1582 continue;
1583 }
1584
1585 if new_animation.name == existing_animation.name {
1586 existing_animation
1587 .update_from_other(&new_animation, context.current_time_for_animations);
1588 return;
1589 }
1590 }
1591
1592 animation_state.animations.push(new_animation);
1593 }
1594}