1use crate::context::{CascadeInputs, SharedStyleContext};
11use crate::dom::{OpaqueNode, TDocument, TElement, TNode};
12use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
13use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
14use crate::properties::longhands::animation_fill_mode::computed_value::single_value::T as AnimationFillMode;
15use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
16use crate::properties::AnimationDeclarations;
17use crate::properties::{
18 ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
19 PropertyDeclarationIdSet,
20};
21use crate::rule_tree::CascadeLevel;
22use crate::selector_parser::PseudoElement;
23use crate::shared_lock::{Locked, SharedRwLock};
24use crate::style_resolver::StyleResolverForElement;
25use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
26use crate::stylesheets::layer_rule::LayerOrder;
27use crate::values::animated::{Animate, Procedure};
28use crate::values::computed::TimingFunction;
29use crate::values::generics::easing::BeforeFlag;
30use crate::values::specified::TransitionBehavior;
31use crate::Atom;
32use fxhash::FxHashMap;
33use parking_lot::RwLock;
34use servo_arc::Arc;
35use std::fmt;
36
37#[derive(Clone, Debug, MallocSizeOf)]
39pub struct PropertyAnimation {
40 from: AnimationValue,
42
43 to: AnimationValue,
45
46 timing_function: TimingFunction,
48
49 pub duration: f64,
51}
52
53impl PropertyAnimation {
54 pub fn property_id(&self) -> PropertyDeclarationId {
56 debug_assert_eq!(self.from.id(), self.to.id());
57 self.from.id()
58 }
59
60 fn timing_function_output(&self, progress: f64) -> f64 {
62 let epsilon = 1. / (200. * self.duration);
63 self.timing_function
69 .calculate_output(progress, BeforeFlag::Unset, epsilon)
70 }
71
72 fn calculate_value(&self, progress: f64) -> AnimationValue {
74 let progress = self.timing_function_output(progress);
75 let procedure = Procedure::Interpolate { progress };
76 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
77 if progress < 0.5 {
79 self.from.clone()
80 } else {
81 self.to.clone()
82 }
83 })
84 }
85}
86
87#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
89pub enum AnimationState {
90 Pending,
93 Running,
95 Paused(f64),
98 Finished,
100 Canceled,
102}
103
104impl AnimationState {
105 fn needs_to_be_ticked(&self) -> bool {
107 *self == AnimationState::Running || *self == AnimationState::Pending
108 }
109}
110
111enum IgnoreTransitions {
112 Canceled,
113 CanceledAndFinished,
114}
115
116#[derive(Clone, Debug, MallocSizeOf)]
121pub enum KeyframesIterationState {
122 Infinite(f64),
124 Finite(f64, f64),
126}
127
128struct IntermediateComputedKeyframe {
133 declarations: PropertyDeclarationBlock,
134 timing_function: Option<TimingFunction>,
135 start_percentage: f32,
136}
137
138impl IntermediateComputedKeyframe {
139 fn new(start_percentage: f32) -> Self {
140 IntermediateComputedKeyframe {
141 declarations: PropertyDeclarationBlock::new(),
142 timing_function: None,
143 start_percentage,
144 }
145 }
146
147 fn generate_for_keyframes(
150 animation: &KeyframesAnimation,
151 context: &SharedStyleContext,
152 base_style: &ComputedValues,
153 ) -> Vec<Self> {
154 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
155 let mut current_step = IntermediateComputedKeyframe::new(0.);
156 for step in animation.steps.iter() {
157 let start_percentage = step.start_percentage.0;
158 if start_percentage != current_step.start_percentage {
159 let new_step = IntermediateComputedKeyframe::new(start_percentage);
160 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
161 }
162
163 current_step.update_from_step(step, context, base_style);
164 }
165 intermediate_steps.push(current_step);
166
167 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
170 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
171
172 intermediate_steps
173 }
174
175 fn update_from_step(
176 &mut self,
177 step: &KeyframesStep,
178 context: &SharedStyleContext,
179 base_style: &ComputedValues,
180 ) {
181 let guard = &context.guards.author;
184 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
185 self.timing_function = Some(timing_function.to_computed_value_without_context());
186 }
187
188 let block = match step.value {
189 KeyframesStepValue::ComputedValues => return,
190 KeyframesStepValue::Declarations { ref block } => block,
191 };
192
193 let guard = block.read_with(&guard);
196 for declaration in guard.normal_declaration_iter() {
197 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
198 if id == LonghandId::Display {
199 continue;
200 }
201
202 if !id.is_animatable() {
203 continue;
204 }
205 }
206
207 self.declarations.push(
208 declaration.to_physical(base_style.writing_mode),
209 Importance::Normal,
210 );
211 }
212 }
213
214 fn resolve_style<E>(
215 self,
216 element: E,
217 context: &SharedStyleContext,
218 base_style: &Arc<ComputedValues>,
219 resolver: &mut StyleResolverForElement<E>,
220 ) -> Arc<ComputedValues>
221 where
222 E: TElement,
223 {
224 if !self.declarations.any_normal() {
225 return base_style.clone();
226 }
227
228 let document = element.as_node().owner_doc();
229 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
230 let mut important_rules_changed = false;
231 let rule_node = base_style.rules().clone();
232 let new_node = context.stylist.rule_tree().update_rule_at_level(
233 CascadeLevel::Animations,
234 LayerOrder::root(),
235 Some(locked_block.borrow_arc()),
236 &rule_node,
237 &context.guards,
238 &mut important_rules_changed,
239 );
240
241 if new_node.is_none() {
242 return base_style.clone();
243 }
244
245 let inputs = CascadeInputs {
246 rules: new_node,
247 visited_rules: base_style.visited_rules().cloned(),
248 flags: base_style.flags.for_cascade_inputs(),
249 };
250 resolver
251 .cascade_style_and_visited_with_default_parents(inputs)
252 .0
253 }
254}
255
256#[derive(Clone, MallocSizeOf)]
258struct ComputedKeyframe {
259 timing_function: TimingFunction,
262
263 start_percentage: f32,
266
267 values: Box<[AnimationValue]>,
270}
271
272impl ComputedKeyframe {
273 fn generate_for_keyframes<E>(
274 element: E,
275 animation: &KeyframesAnimation,
276 context: &SharedStyleContext,
277 base_style: &Arc<ComputedValues>,
278 default_timing_function: TimingFunction,
279 resolver: &mut StyleResolverForElement<E>,
280 ) -> Box<[Self]>
281 where
282 E: TElement,
283 {
284 let mut animating_properties = PropertyDeclarationIdSet::default();
285 for property in animation.properties_changed.iter() {
286 debug_assert!(property.is_animatable());
287 animating_properties.insert(property.to_physical(base_style.writing_mode));
288 }
289
290 let animation_values_from_style: Vec<AnimationValue> = animating_properties
291 .iter()
292 .map(|property| {
293 AnimationValue::from_computed_values(property, &**base_style)
294 .expect("Unexpected non-animatable property.")
295 })
296 .collect();
297
298 let intermediate_steps =
299 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
300
301 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
302 for (step_index, step) in intermediate_steps.into_iter().enumerate() {
303 let start_percentage = step.start_percentage;
304 let properties_changed_in_step = step.declarations.property_ids().clone();
305 let step_timing_function = step.timing_function.clone();
306 let step_style = step.resolve_style(element, context, base_style, resolver);
307 let timing_function =
308 step_timing_function.unwrap_or_else(|| default_timing_function.clone());
309
310 let values = {
311 let default_values = if start_percentage == 0. || start_percentage == 1.0 {
318 animation_values_from_style.as_slice()
319 } else {
320 debug_assert!(step_index != 0);
321 &computed_steps[step_index - 1].values
322 };
323
324 animating_properties
328 .iter()
329 .zip(default_values.iter())
330 .map(|(property_declaration, default_value)| {
331 if properties_changed_in_step.contains(property_declaration) {
332 AnimationValue::from_computed_values(property_declaration, &step_style)
333 .unwrap_or_else(|| default_value.clone())
334 } else {
335 default_value.clone()
336 }
337 })
338 .collect()
339 };
340
341 computed_steps.push(ComputedKeyframe {
342 timing_function,
343 start_percentage,
344 values,
345 });
346 }
347 computed_steps.into_boxed_slice()
348 }
349}
350
351#[derive(Clone, MallocSizeOf)]
353pub struct Animation {
354 pub name: Atom,
356
357 properties_changed: PropertyDeclarationIdSet,
359
360 computed_steps: Box<[ComputedKeyframe]>,
362
363 pub started_at: f64,
366
367 pub duration: f64,
369
370 pub delay: f64,
372
373 pub fill_mode: AnimationFillMode,
375
376 pub iteration_state: KeyframesIterationState,
378
379 pub state: AnimationState,
381
382 pub direction: AnimationDirection,
384
385 pub current_direction: AnimationDirection,
387
388 #[ignore_malloc_size_of = "ComputedValues"]
391 pub cascade_style: Arc<ComputedValues>,
392
393 pub is_new: bool,
396}
397
398impl Animation {
399 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
401 let new_ui = new_style.get_ui();
402 let index = new_ui
403 .animation_name_iter()
404 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
405 let index = match index {
406 Some(index) => index,
407 None => return true,
408 };
409
410 new_ui.animation_duration_mod(index).seconds() == 0.
411 }
412
413 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
417 if !self.iteration_over(time) {
418 return false;
419 }
420
421 if self.state != AnimationState::Running {
423 return false;
424 }
425
426 if self.on_last_iteration() {
427 return false;
428 }
429
430 self.iterate();
431 true
432 }
433
434 fn iterate(&mut self) {
435 debug_assert!(!self.on_last_iteration());
436
437 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
438 *current = (*current + 1.).min(max);
439 }
440
441 if let AnimationState::Paused(ref mut progress) = self.state {
442 debug_assert!(*progress > 1.);
443 *progress -= 1.;
444 }
445
446 self.started_at += self.duration;
448 match self.direction {
449 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
450 self.current_direction = match self.current_direction {
451 AnimationDirection::Normal => AnimationDirection::Reverse,
452 AnimationDirection::Reverse => AnimationDirection::Normal,
453 _ => unreachable!(),
454 };
455 },
456 _ => {},
457 }
458 }
459
460 pub fn current_iteration_end_progress(&self) -> f64 {
465 match self.iteration_state {
466 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
467 KeyframesIterationState::Infinite(_) => 1.,
468 }
469 }
470
471 pub fn current_iteration_duration(&self) -> f64 {
474 self.current_iteration_end_progress() * self.duration
475 }
476
477 fn iteration_over(&self, time: f64) -> bool {
480 time > (self.started_at + self.current_iteration_duration())
481 }
482
483 fn on_last_iteration(&self) -> bool {
485 match self.iteration_state {
486 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
487 KeyframesIterationState::Infinite(_) => false,
488 }
489 }
490
491 pub fn has_ended(&self, time: f64) -> bool {
495 if !self.on_last_iteration() {
496 return false;
497 }
498
499 let progress = match self.state {
500 AnimationState::Finished => return true,
501 AnimationState::Paused(progress) => progress,
502 AnimationState::Running => (time - self.started_at) / self.duration,
503 AnimationState::Pending | AnimationState::Canceled => return false,
504 };
505
506 progress >= self.current_iteration_end_progress()
507 }
508
509 pub fn update_from_other(&mut self, other: &Self, now: f64) {
517 use self::AnimationState::*;
518
519 debug!(
520 "KeyframesAnimationState::update_from_other({:?}, {:?})",
521 self, other
522 );
523
524 let old_started_at = self.started_at;
527 let old_duration = self.duration;
528 let old_direction = self.current_direction;
529 let old_state = self.state.clone();
530 let old_iteration_state = self.iteration_state.clone();
531
532 *self = other.clone();
533
534 self.started_at = old_started_at;
535 self.current_direction = old_direction;
536
537 match (&mut self.iteration_state, old_iteration_state) {
541 (
542 &mut KeyframesIterationState::Finite(ref mut iters, _),
543 KeyframesIterationState::Finite(old_iters, _),
544 ) => *iters = old_iters,
545 _ => {},
546 }
547
548 let new_state = std::mem::replace(&mut self.state, Running);
551 if old_state == Finished && self.has_ended(now) {
552 self.state = Finished;
553 } else {
554 self.state = new_state;
555 }
556
557 match (&mut self.state, &old_state) {
564 (&mut Pending, &Paused(progress)) => {
565 self.started_at = now - (self.duration * progress);
566 },
567 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
568 (&mut Paused(ref mut progress), &Running) => {
569 *progress = (now - old_started_at) / old_duration
570 },
571 _ => {},
572 }
573
574 if self.state == Pending && self.started_at <= now && old_state != Pending {
577 self.state = Running;
578 }
579 }
580
581 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
584 debug_assert!(!self.computed_steps.is_empty());
585
586 let total_progress = match self.state {
587 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
588 (now - self.started_at) / self.duration
589 },
590 AnimationState::Paused(progress) => progress,
591 AnimationState::Canceled => return,
592 };
593
594 if total_progress < 0.
595 && self.fill_mode != AnimationFillMode::Backwards
596 && self.fill_mode != AnimationFillMode::Both
597 {
598 return;
599 }
600 if self.has_ended(now)
601 && self.fill_mode != AnimationFillMode::Forwards
602 && self.fill_mode != AnimationFillMode::Both
603 {
604 return;
605 }
606 let total_progress = total_progress
607 .min(self.current_iteration_end_progress())
608 .max(0.0);
609
610 let next_keyframe_index;
612 let prev_keyframe_index;
613 let num_steps = self.computed_steps.len();
614 match self.current_direction {
615 AnimationDirection::Normal => {
616 next_keyframe_index = self
617 .computed_steps
618 .iter()
619 .position(|step| total_progress as f32 <= step.start_percentage);
620 prev_keyframe_index = next_keyframe_index
621 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
622 .unwrap_or(0);
623 },
624 AnimationDirection::Reverse => {
625 next_keyframe_index = self
626 .computed_steps
627 .iter()
628 .rev()
629 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
630 .map(|pos| num_steps - pos - 1);
631 prev_keyframe_index = next_keyframe_index
632 .and_then(|pos| {
633 if pos != num_steps - 1 {
634 Some(pos + 1)
635 } else {
636 None
637 }
638 })
639 .unwrap_or(num_steps - 1)
640 },
641 _ => unreachable!(),
642 }
643
644 debug!(
645 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
646 prev_keyframe_index, next_keyframe_index
647 );
648
649 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
650 let next_keyframe = match next_keyframe_index {
651 Some(index) => &self.computed_steps[index],
652 None => return,
653 };
654
655 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
658 for value in keyframe.values.iter() {
659 map.insert(value.id().to_owned(), value.clone());
660 }
661 };
662 if total_progress <= 0.0 {
663 add_declarations_to_map(&prev_keyframe);
664 return;
665 }
666 if total_progress >= 1.0 {
667 add_declarations_to_map(&next_keyframe);
668 return;
669 }
670
671 let percentage_between_keyframes =
672 (next_keyframe.start_percentage - prev_keyframe.start_percentage).abs() as f64;
673 let duration_between_keyframes = percentage_between_keyframes * self.duration;
674 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
675 AnimationDirection::Normal => prev_keyframe.start_percentage as f64,
676 AnimationDirection::Reverse => 1. - prev_keyframe.start_percentage as f64,
677 _ => unreachable!(),
678 };
679 let progress_between_keyframes = (total_progress
680 - direction_aware_prev_keyframe_start_percentage)
681 / percentage_between_keyframes;
682
683 for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) {
684 let animation = PropertyAnimation {
685 from: from.clone(),
686 to: to.clone(),
687 timing_function: prev_keyframe.timing_function.clone(),
688 duration: duration_between_keyframes as f64,
689 };
690
691 let value = animation.calculate_value(progress_between_keyframes);
692 map.insert(value.id().to_owned(), value);
693 }
694 }
695}
696
697impl fmt::Debug for Animation {
698 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
699 f.debug_struct("Animation")
700 .field("name", &self.name)
701 .field("started_at", &self.started_at)
702 .field("duration", &self.duration)
703 .field("delay", &self.delay)
704 .field("iteration_state", &self.iteration_state)
705 .field("state", &self.state)
706 .field("direction", &self.direction)
707 .field("current_direction", &self.current_direction)
708 .field("cascade_style", &())
709 .finish()
710 }
711}
712
713#[derive(Clone, Debug, MallocSizeOf)]
715pub struct Transition {
716 pub start_time: f64,
719
720 pub delay: f64,
722
723 pub property_animation: PropertyAnimation,
725
726 pub state: AnimationState,
728
729 pub is_new: bool,
732
733 pub reversing_adjusted_start_value: AnimationValue,
736
737 pub reversing_shortening_factor: f64,
740}
741
742impl Transition {
743 fn new(
744 start_time: f64,
745 delay: f64,
746 duration: f64,
747 from: AnimationValue,
748 to: AnimationValue,
749 timing_function: &TimingFunction,
750 ) -> Self {
751 let property_animation = PropertyAnimation {
752 from: from.clone(),
753 to,
754 timing_function: timing_function.clone(),
755 duration,
756 };
757 Self {
758 start_time,
759 delay,
760 property_animation,
761 state: AnimationState::Pending,
762 is_new: true,
763 reversing_adjusted_start_value: from,
764 reversing_shortening_factor: 1.0,
765 }
766 }
767
768 fn update_for_possibly_reversed_transition(
769 &mut self,
770 replaced_transition: &Transition,
771 delay: f64,
772 now: f64,
773 ) {
774 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
783 return;
784 }
785
786 let replaced_animation = &replaced_transition.property_animation;
788 self.reversing_adjusted_start_value = replaced_animation.to.clone();
789
790 let transition_progress = ((now - replaced_transition.start_time)
797 / (replaced_transition.property_animation.duration))
798 .min(1.0)
799 .max(0.0);
800 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
801 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
802 self.reversing_shortening_factor = ((timing_function_output
803 * old_reversing_shortening_factor)
804 + (1.0 - old_reversing_shortening_factor))
805 .abs()
806 .min(1.0)
807 .max(0.0);
808
809 self.start_time = if delay >= 0. {
815 now + delay
816 } else {
817 now + (self.reversing_shortening_factor * delay)
818 };
819
820 self.property_animation.duration *= self.reversing_shortening_factor;
823
824 let procedure = Procedure::Interpolate {
827 progress: timing_function_output,
828 };
829 match replaced_animation
830 .from
831 .animate(&replaced_animation.to, procedure)
832 {
833 Ok(new_start) => self.property_animation.from = new_start,
834 Err(..) => {},
835 }
836 }
837
838 pub fn has_ended(&self, time: f64) -> bool {
842 time >= self.start_time + (self.property_animation.duration)
843 }
844
845 pub fn calculate_value(&self, time: f64) -> AnimationValue {
847 let progress = (time - self.start_time) / (self.property_animation.duration);
848 self.property_animation
849 .calculate_value(progress.clamp(0.0, 1.0))
850 }
851}
852
853#[derive(Debug, Default, MallocSizeOf)]
855pub struct ElementAnimationSet {
856 pub animations: Vec<Animation>,
858
859 pub transitions: Vec<Transition>,
861
862 pub dirty: bool,
865}
866
867impl ElementAnimationSet {
868 pub fn cancel_all_animations(&mut self) {
871 self.dirty = !self.animations.is_empty();
872 for animation in self.animations.iter_mut() {
873 animation.state = AnimationState::Canceled;
874 }
875 self.cancel_active_transitions();
876 }
877
878 fn cancel_active_transitions(&mut self) {
879 for transition in self.transitions.iter_mut() {
880 if transition.state != AnimationState::Finished {
881 self.dirty = true;
882 transition.state = AnimationState::Canceled;
883 }
884 }
885 }
886
887 pub fn apply_active_animations(
889 &self,
890 context: &SharedStyleContext,
891 style: &mut Arc<ComputedValues>,
892 ) {
893 let now = context.current_time_for_animations;
894 let mutable_style = Arc::make_mut(style);
895 if let Some(map) = self.get_value_map_for_active_animations(now) {
896 for value in map.values() {
897 value.set_in_style_for_servo(mutable_style);
898 }
899 }
900
901 if let Some(map) = self.get_value_map_for_transitions(now, IgnoreTransitions::Canceled) {
902 for value in map.values() {
903 value.set_in_style_for_servo(mutable_style);
904 }
905 }
906 }
907
908 pub fn clear_canceled_animations(&mut self) {
910 self.animations
911 .retain(|animation| animation.state != AnimationState::Canceled);
912 self.transitions
913 .retain(|animation| animation.state != AnimationState::Canceled);
914 }
915
916 pub fn is_empty(&self) -> bool {
919 self.animations.is_empty() && self.transitions.is_empty()
920 }
921
922 pub fn needs_animation_ticks(&self) -> bool {
925 self.animations
926 .iter()
927 .any(|animation| animation.state.needs_to_be_ticked())
928 || self
929 .transitions
930 .iter()
931 .any(|transition| transition.state.needs_to_be_ticked())
932 }
933
934 pub fn running_animation_and_transition_count(&self) -> usize {
936 self.animations
937 .iter()
938 .filter(|animation| animation.state.needs_to_be_ticked())
939 .count()
940 + self
941 .transitions
942 .iter()
943 .filter(|transition| transition.state.needs_to_be_ticked())
944 .count()
945 }
946
947 pub fn has_active_animation(&self) -> bool {
949 self.animations
950 .iter()
951 .any(|animation| animation.state != AnimationState::Canceled)
952 }
953
954 pub fn has_active_transition(&self) -> bool {
956 self.transitions
957 .iter()
958 .any(|transition| transition.state != AnimationState::Canceled)
959 }
960
961 pub fn update_animations_for_new_style<E>(
964 &mut self,
965 element: E,
966 context: &SharedStyleContext,
967 new_style: &Arc<ComputedValues>,
968 resolver: &mut StyleResolverForElement<E>,
969 ) where
970 E: TElement,
971 {
972 for animation in self.animations.iter_mut() {
973 if animation.is_cancelled_in_new_style(new_style) {
974 animation.state = AnimationState::Canceled;
975 }
976 }
977
978 maybe_start_animations(element, &context, &new_style, self, resolver);
979 }
980
981 pub fn update_transitions_for_new_style(
984 &mut self,
985 might_need_transitions_update: bool,
986 context: &SharedStyleContext,
987 old_style: Option<&Arc<ComputedValues>>,
988 after_change_style: &Arc<ComputedValues>,
989 ) {
990 let mut before_change_style = match old_style {
993 Some(old_style) => Arc::clone(old_style),
994 None => return,
995 };
996
997 if after_change_style.get_box().clone_display().is_none() {
999 self.cancel_active_transitions();
1000 return;
1001 }
1002
1003 if !might_need_transitions_update {
1004 return;
1005 }
1006
1007 if self.has_active_transition() || self.has_active_animation() {
1009 self.apply_active_animations(context, &mut before_change_style);
1010 }
1011
1012 let transitioning_properties = start_transitions_if_applicable(
1013 context,
1014 &before_change_style,
1015 after_change_style,
1016 self,
1017 );
1018
1019 for transition in self.transitions.iter_mut() {
1032 if transition.state == AnimationState::Finished
1033 || transition.state == AnimationState::Canceled
1034 {
1035 continue;
1036 }
1037 if transitioning_properties.contains(transition.property_animation.property_id()) {
1038 continue;
1039 }
1040 transition.state = AnimationState::Canceled;
1041 self.dirty = true;
1042 }
1043 }
1044
1045 fn start_transition_if_applicable(
1046 &mut self,
1047 context: &SharedStyleContext,
1048 property_declaration_id: &PropertyDeclarationId,
1049 index: usize,
1050 old_style: &ComputedValues,
1051 new_style: &Arc<ComputedValues>,
1052 ) {
1053 let style = new_style.get_ui();
1054 let allow_discrete =
1055 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1056
1057 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1059 else {
1060 return;
1061 };
1062 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1063 else {
1064 return;
1065 };
1066
1067 let timing_function = style.transition_timing_function_mod(index);
1068 let duration = style.transition_duration_mod(index).seconds() as f64;
1069 let delay = style.transition_delay_mod(index).seconds() as f64;
1070 let now = context.current_time_for_animations;
1071 let transitionable = property_declaration_id.is_animatable()
1072 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1073 && (allow_discrete || from.interpolable_with(&to));
1074
1075 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1076 transition.property_animation.property_id() == *property_declaration_id
1077 });
1078
1079 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1094 transition.state != AnimationState::Finished
1095 && transition.state != AnimationState::Canceled
1096 });
1097 let no_completed_transition_or_end_values_differ =
1098 existing_transition.as_ref().is_none_or(|transition| {
1099 transition.state != AnimationState::Finished
1100 || transition.property_animation.to != to
1101 });
1102 if !has_running_transition
1103 && from != to
1104 && transitionable
1105 && no_completed_transition_or_end_values_differ
1106 && (duration + delay > 0.0)
1107 {
1108 self.transitions.push(Transition::new(
1119 now + delay, delay,
1121 duration,
1122 from,
1123 to,
1124 &timing_function,
1125 ));
1126 self.dirty = true;
1127 return;
1128 }
1129
1130 let Some(existing_transition) = existing_transition.as_mut() else {
1153 return;
1154 };
1155
1156 if has_running_transition && existing_transition.property_animation.to != to {
1161 let current_value = existing_transition.calculate_value(now);
1166 let transitionable_from_current_value =
1167 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1168 if current_value == to || !transitionable_from_current_value {
1169 existing_transition.state = AnimationState::Canceled;
1170 self.dirty = true;
1171 return;
1172 }
1173
1174 if duration + delay <= 0.0 {
1180 existing_transition.state = AnimationState::Canceled;
1181 self.dirty = true;
1182 return;
1183 }
1184
1185 if existing_transition.reversing_adjusted_start_value == to {
1191 existing_transition.state = AnimationState::Canceled;
1192
1193 let mut transition = Transition::new(
1194 now + delay, delay,
1196 duration,
1197 from,
1198 to,
1199 &timing_function,
1200 );
1201
1202 transition.update_for_possibly_reversed_transition(
1205 &existing_transition,
1206 delay,
1207 now,
1208 );
1209
1210 self.transitions.push(transition);
1211 self.dirty = true;
1212 return;
1213 }
1214
1215 existing_transition.state = AnimationState::Canceled;
1224 self.transitions.push(Transition::new(
1225 now + delay, delay,
1227 duration,
1228 current_value,
1229 to,
1230 &timing_function,
1231 ));
1232 self.dirty = true;
1233 }
1234 }
1235
1236 fn get_value_map_for_transitions(
1240 &self,
1241 now: f64,
1242 ignore_transitions: IgnoreTransitions,
1243 ) -> Option<AnimationValueMap> {
1244 if !self.has_active_transition() {
1245 return None;
1246 }
1247
1248 let mut map =
1249 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1250 for transition in &self.transitions {
1251 match ignore_transitions {
1252 IgnoreTransitions::Canceled => {
1253 if transition.state == AnimationState::Canceled {
1254 continue;
1255 }
1256 },
1257 IgnoreTransitions::CanceledAndFinished => {
1258 if transition.state == AnimationState::Canceled
1259 || transition.state == AnimationState::Finished
1260 {
1261 continue;
1262 }
1263 },
1264 }
1265
1266 let value = transition.calculate_value(now);
1267 map.insert(value.id().to_owned(), value);
1268 }
1269
1270 Some(map)
1271 }
1272
1273 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1276 if !self.has_active_animation() {
1277 return None;
1278 }
1279
1280 let mut map = Default::default();
1281 for animation in &self.animations {
1282 animation.get_property_declaration_at_time(now, &mut map);
1283 }
1284
1285 Some(map)
1286 }
1287}
1288
1289#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1290pub struct AnimationSetKey {
1292 pub node: OpaqueNode,
1294 pub pseudo_element: Option<PseudoElement>,
1297}
1298
1299impl AnimationSetKey {
1300 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1302 AnimationSetKey {
1303 node,
1304 pseudo_element,
1305 }
1306 }
1307
1308 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1310 AnimationSetKey {
1311 node,
1312 pseudo_element: None,
1313 }
1314 }
1315
1316 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1318 AnimationSetKey {
1319 node,
1320 pseudo_element: Some(pseudo_element),
1321 }
1322 }
1323}
1324
1325#[derive(Clone, Debug, Default, MallocSizeOf)]
1326pub struct DocumentAnimationSet {
1328 #[ignore_malloc_size_of = "Arc is hard"]
1330 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1331}
1332
1333impl DocumentAnimationSet {
1334 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1336 self.sets
1337 .read()
1338 .get(key)
1339 .map_or(false, |set| set.has_active_animation())
1340 }
1341
1342 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1344 self.sets
1345 .read()
1346 .get(key)
1347 .map_or(false, |set| set.has_active_transition())
1348 }
1349
1350 pub fn get_animation_declarations(
1353 &self,
1354 key: &AnimationSetKey,
1355 time: f64,
1356 shared_lock: &SharedRwLock,
1357 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1358 self.sets
1359 .read()
1360 .get(key)
1361 .and_then(|set| set.get_value_map_for_active_animations(time))
1362 .map(|map| {
1363 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1364 Arc::new(shared_lock.wrap(block))
1365 })
1366 }
1367
1368 pub fn get_transition_declarations(
1371 &self,
1372 key: &AnimationSetKey,
1373 time: f64,
1374 shared_lock: &SharedRwLock,
1375 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1376 self.sets
1377 .read()
1378 .get(key)
1379 .and_then(|set| {
1380 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1381 })
1382 .map(|map| {
1383 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1384 Arc::new(shared_lock.wrap(block))
1385 })
1386 }
1387
1388 pub fn get_all_declarations(
1391 &self,
1392 key: &AnimationSetKey,
1393 time: f64,
1394 shared_lock: &SharedRwLock,
1395 ) -> AnimationDeclarations {
1396 let sets = self.sets.read();
1397 let set = match sets.get(key) {
1398 Some(set) => set,
1399 None => return Default::default(),
1400 };
1401
1402 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1403 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1404 Arc::new(shared_lock.wrap(block))
1405 });
1406 let transitions = set
1407 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1408 .map(|map| {
1409 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1410 Arc::new(shared_lock.wrap(block))
1411 });
1412 AnimationDeclarations {
1413 animations,
1414 transitions,
1415 }
1416 }
1417
1418 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1420 if let Some(set) = self.sets.write().get_mut(key) {
1421 set.cancel_all_animations();
1422 }
1423 }
1424}
1425
1426pub fn start_transitions_if_applicable(
1429 context: &SharedStyleContext,
1430 old_style: &ComputedValues,
1431 new_style: &Arc<ComputedValues>,
1432 animation_state: &mut ElementAnimationSet,
1433) -> PropertyDeclarationIdSet {
1434 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1449 transition_properties.reverse();
1450
1451 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1452 for transition in transition_properties {
1453 let physical_property = transition
1454 .property
1455 .as_borrowed()
1456 .to_physical(new_style.writing_mode);
1457 if properties_that_transition.contains(physical_property) {
1458 continue;
1459 }
1460
1461 properties_that_transition.insert(physical_property);
1462 animation_state.start_transition_if_applicable(
1463 context,
1464 &physical_property,
1465 transition.index,
1466 old_style,
1467 new_style,
1468 );
1469 }
1470
1471 properties_that_transition
1472}
1473
1474pub fn maybe_start_animations<E>(
1477 element: E,
1478 context: &SharedStyleContext,
1479 new_style: &Arc<ComputedValues>,
1480 animation_state: &mut ElementAnimationSet,
1481 resolver: &mut StyleResolverForElement<E>,
1482) where
1483 E: TElement,
1484{
1485 let style = new_style.get_ui();
1486 for (i, name) in style.animation_name_iter().enumerate() {
1487 let name = match name.as_atom() {
1488 Some(atom) => atom,
1489 None => continue,
1490 };
1491
1492 debug!("maybe_start_animations: name={}", name);
1493 let duration = style.animation_duration_mod(i).seconds() as f64;
1494 if duration == 0. {
1495 continue;
1496 }
1497
1498 let keyframe_animation = match context.stylist.get_animation(name, element) {
1499 Some(animation) => animation,
1500 None => continue,
1501 };
1502
1503 debug!("maybe_start_animations: animation {} found", name);
1504
1505 if keyframe_animation.steps.is_empty() {
1510 continue;
1511 }
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}