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 {
76 progress,
77 };
78 self.from.animate(&self.to, procedure).unwrap_or_else(|()| {
79 if progress < 0.5 {
81 self.from.clone()
82 } else {
83 self.to.clone()
84 }
85 })
86 }
87}
88
89#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
91pub enum AnimationState {
92 Pending,
95 Running,
97 Paused(f64),
100 Finished,
102 Canceled,
104}
105
106impl AnimationState {
107 fn needs_to_be_ticked(&self) -> bool {
109 *self == AnimationState::Running || *self == AnimationState::Pending
110 }
111}
112
113enum IgnoreTransitions {
114 Canceled,
115 CanceledAndFinished,
116}
117
118#[derive(Clone, Debug, MallocSizeOf)]
123pub enum KeyframesIterationState {
124 Infinite(f64),
126 Finite(f64, f64),
128}
129
130struct IntermediateComputedKeyframe {
135 declarations: PropertyDeclarationBlock,
136 timing_function: Option<TimingFunction>,
137 start_percentage: f32,
138}
139
140impl IntermediateComputedKeyframe {
141 fn new(start_percentage: f32) -> Self {
142 IntermediateComputedKeyframe {
143 declarations: PropertyDeclarationBlock::new(),
144 timing_function: None,
145 start_percentage,
146 }
147 }
148
149 fn generate_for_keyframes(
152 animation: &KeyframesAnimation,
153 context: &SharedStyleContext,
154 base_style: &ComputedValues,
155 ) -> Vec<Self> {
156 let mut intermediate_steps: Vec<Self> = Vec::with_capacity(animation.steps.len());
157 let mut current_step = IntermediateComputedKeyframe::new(0.);
158 for step in animation.steps.iter() {
159 let start_percentage = step.start_percentage.0;
160 if start_percentage != current_step.start_percentage {
161 let new_step = IntermediateComputedKeyframe::new(start_percentage);
162 intermediate_steps.push(std::mem::replace(&mut current_step, new_step));
163 }
164
165 current_step.update_from_step(step, context, base_style);
166 }
167 intermediate_steps.push(current_step);
168
169 debug_assert!(intermediate_steps.first().unwrap().start_percentage == 0.);
172 debug_assert!(intermediate_steps.last().unwrap().start_percentage == 1.);
173
174 intermediate_steps
175 }
176
177 fn update_from_step(
178 &mut self,
179 step: &KeyframesStep,
180 context: &SharedStyleContext,
181 base_style: &ComputedValues,
182 ) {
183 let guard = &context.guards.author;
186 if let Some(timing_function) = step.get_animation_timing_function(&guard) {
187 self.timing_function = Some(timing_function.to_computed_value_without_context());
188 }
189
190 let block = match step.value {
191 KeyframesStepValue::ComputedValues => return,
192 KeyframesStepValue::Declarations { ref block } => block,
193 };
194
195 let guard = block.read_with(&guard);
198 for declaration in guard.normal_declaration_iter() {
199 if let PropertyDeclarationId::Longhand(id) = declaration.id() {
200 if id == LonghandId::Display {
201 continue;
202 }
203
204 if !id.is_animatable() {
205 continue;
206 }
207 }
208
209 self.declarations.push(
210 declaration.to_physical(base_style.writing_mode),
211 Importance::Normal,
212 );
213 }
214 }
215
216 fn resolve_style<E>(
217 self,
218 element: E,
219 context: &SharedStyleContext,
220 base_style: &Arc<ComputedValues>,
221 resolver: &mut StyleResolverForElement<E>,
222 ) -> Arc<ComputedValues>
223 where
224 E: TElement,
225 {
226 if !self.declarations.any_normal() {
227 return base_style.clone();
228 }
229
230 let document = element.as_node().owner_doc();
231 let locked_block = Arc::new(document.shared_lock().wrap(self.declarations));
232 let mut important_rules_changed = false;
233 let rule_node = base_style.rules().clone();
234 let new_node = context.stylist.rule_tree().update_rule_at_level(
235 CascadeLevel::Animations,
236 LayerOrder::root(),
237 Some(locked_block.borrow_arc()),
238 &rule_node,
239 &context.guards,
240 &mut important_rules_changed,
241 );
242
243 if new_node.is_none() {
244 return base_style.clone();
245 }
246
247 let inputs = CascadeInputs {
248 rules: new_node,
249 visited_rules: base_style.visited_rules().cloned(),
250 flags: base_style.flags.for_cascade_inputs(),
251 };
252 resolver
253 .cascade_style_and_visited_with_default_parents(inputs)
254 .0
255 }
256}
257
258#[derive(Clone, MallocSizeOf)]
260struct ComputedKeyframe {
261 timing_function: TimingFunction,
264
265 start_percentage: f32,
268
269 values: Box<[AnimationValue]>,
272}
273
274impl ComputedKeyframe {
275 fn generate_for_keyframes<E>(
276 element: E,
277 animation: &KeyframesAnimation,
278 context: &SharedStyleContext,
279 base_style: &Arc<ComputedValues>,
280 default_timing_function: TimingFunction,
281 resolver: &mut StyleResolverForElement<E>,
282 ) -> Box<[Self]>
283 where
284 E: TElement,
285 {
286 let mut animating_properties = PropertyDeclarationIdSet::default();
287 for property in animation.properties_changed.iter() {
288 debug_assert!(property.is_animatable());
289 animating_properties.insert(property.to_physical(base_style.writing_mode));
290 }
291
292 let animation_values_from_style: Vec<AnimationValue> = animating_properties
293 .iter()
294 .map(|property| {
295 AnimationValue::from_computed_values(property, &**base_style)
296 .expect("Unexpected non-animatable property.")
297 })
298 .collect();
299
300 let intermediate_steps =
301 IntermediateComputedKeyframe::generate_for_keyframes(animation, context, base_style);
302
303 let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
304 for (step_index, step) in intermediate_steps.into_iter().enumerate() {
305 let start_percentage = step.start_percentage;
306 let properties_changed_in_step = step.declarations.property_ids().clone();
307 let step_timing_function = step.timing_function.clone();
308 let step_style = step.resolve_style(element, context, base_style, resolver);
309 let timing_function =
310 step_timing_function.unwrap_or_else(|| default_timing_function.clone());
311
312 let values = {
313 let default_values = if start_percentage == 0. || start_percentage == 1.0 {
320 animation_values_from_style.as_slice()
321 } else {
322 debug_assert!(step_index != 0);
323 &computed_steps[step_index - 1].values
324 };
325
326 animating_properties
330 .iter()
331 .zip(default_values.iter())
332 .map(|(property_declaration, default_value)| {
333 if properties_changed_in_step.contains(property_declaration) {
334 AnimationValue::from_computed_values(property_declaration, &step_style)
335 .unwrap_or_else(|| default_value.clone())
336 } else {
337 default_value.clone()
338 }
339 })
340 .collect()
341 };
342
343 computed_steps.push(ComputedKeyframe {
344 timing_function,
345 start_percentage,
346 values,
347 });
348 }
349 computed_steps.into_boxed_slice()
350 }
351}
352
353#[derive(Clone, MallocSizeOf)]
355pub struct Animation {
356 pub name: Atom,
358
359 properties_changed: PropertyDeclarationIdSet,
361
362 computed_steps: Box<[ComputedKeyframe]>,
364
365 pub started_at: f64,
368
369 pub duration: f64,
371
372 pub delay: f64,
374
375 pub fill_mode: AnimationFillMode,
377
378 pub iteration_state: KeyframesIterationState,
380
381 pub state: AnimationState,
383
384 pub direction: AnimationDirection,
386
387 pub current_direction: AnimationDirection,
389
390 #[ignore_malloc_size_of = "ComputedValues"]
393 pub cascade_style: Arc<ComputedValues>,
394
395 pub is_new: bool,
398}
399
400impl Animation {
401 fn is_cancelled_in_new_style(&self, new_style: &Arc<ComputedValues>) -> bool {
403 let new_ui = new_style.get_ui();
404 let index = new_ui
405 .animation_name_iter()
406 .position(|animation_name| Some(&self.name) == animation_name.as_atom());
407 let index = match index {
408 Some(index) => index,
409 None => return true,
410 };
411
412 new_ui.animation_duration_mod(index).seconds() == 0.
413 }
414
415 pub fn iterate_if_necessary(&mut self, time: f64) -> bool {
419 if !self.iteration_over(time) {
420 return false;
421 }
422
423 if self.state != AnimationState::Running {
425 return false;
426 }
427
428 if self.on_last_iteration() {
429 return false;
430 }
431
432 self.iterate();
433 true
434 }
435
436 fn iterate(&mut self) {
437 debug_assert!(!self.on_last_iteration());
438
439 if let KeyframesIterationState::Finite(ref mut current, max) = self.iteration_state {
440 *current = (*current + 1.).min(max);
441 }
442
443 if let AnimationState::Paused(ref mut progress) = self.state {
444 debug_assert!(*progress > 1.);
445 *progress -= 1.;
446 }
447
448 self.started_at += self.duration;
450 match self.direction {
451 AnimationDirection::Alternate | AnimationDirection::AlternateReverse => {
452 self.current_direction = match self.current_direction {
453 AnimationDirection::Normal => AnimationDirection::Reverse,
454 AnimationDirection::Reverse => AnimationDirection::Normal,
455 _ => unreachable!(),
456 };
457 },
458 _ => {},
459 }
460 }
461
462 pub fn current_iteration_end_progress(&self) -> f64 {
467 match self.iteration_state {
468 KeyframesIterationState::Finite(current, max) => (max - current).min(1.),
469 KeyframesIterationState::Infinite(_) => 1.,
470 }
471 }
472
473 pub fn current_iteration_duration(&self) -> f64 {
476 self.current_iteration_end_progress() * self.duration
477 }
478
479 fn iteration_over(&self, time: f64) -> bool {
482 time > (self.started_at + self.current_iteration_duration())
483 }
484
485 fn on_last_iteration(&self) -> bool {
487 match self.iteration_state {
488 KeyframesIterationState::Finite(current, max) => current >= (max - 1.),
489 KeyframesIterationState::Infinite(_) => false,
490 }
491 }
492
493 pub fn has_ended(&self, time: f64) -> bool {
497 if !self.on_last_iteration() {
498 return false;
499 }
500
501 let progress = match self.state {
502 AnimationState::Finished => return true,
503 AnimationState::Paused(progress) => progress,
504 AnimationState::Running => (time - self.started_at) / self.duration,
505 AnimationState::Pending | AnimationState::Canceled => return false,
506 };
507
508 progress >= self.current_iteration_end_progress()
509 }
510
511 pub fn update_from_other(&mut self, other: &Self, now: f64) {
519 use self::AnimationState::*;
520
521 debug!(
522 "KeyframesAnimationState::update_from_other({:?}, {:?})",
523 self, other
524 );
525
526 let old_started_at = self.started_at;
529 let old_duration = self.duration;
530 let old_direction = self.current_direction;
531 let old_state = self.state.clone();
532 let old_iteration_state = self.iteration_state.clone();
533
534 *self = other.clone();
535
536 self.started_at = old_started_at;
537 self.current_direction = old_direction;
538
539 match (&mut self.iteration_state, old_iteration_state) {
543 (
544 &mut KeyframesIterationState::Finite(ref mut iters, _),
545 KeyframesIterationState::Finite(old_iters, _),
546 ) => *iters = old_iters,
547 _ => {},
548 }
549
550 let new_state = std::mem::replace(&mut self.state, Running);
553 if old_state == Finished && self.has_ended(now) {
554 self.state = Finished;
555 } else {
556 self.state = new_state;
557 }
558
559 match (&mut self.state, &old_state) {
566 (&mut Pending, &Paused(progress)) => {
567 self.started_at = now - (self.duration * progress);
568 },
569 (&mut Paused(ref mut new), &Paused(old)) => *new = old,
570 (&mut Paused(ref mut progress), &Running) => {
571 *progress = (now - old_started_at) / old_duration
572 },
573 _ => {},
574 }
575
576 if self.state == Pending && self.started_at <= now && old_state != Pending {
579 self.state = Running;
580 }
581 }
582
583 fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) {
586 debug_assert!(!self.computed_steps.is_empty());
587
588 let total_progress = match self.state {
589 AnimationState::Running | AnimationState::Pending | AnimationState::Finished => {
590 (now - self.started_at) / self.duration
591 },
592 AnimationState::Paused(progress) => progress,
593 AnimationState::Canceled => return,
594 };
595
596 if total_progress < 0. &&
597 self.fill_mode != AnimationFillMode::Backwards &&
598 self.fill_mode != AnimationFillMode::Both
599 {
600 return;
601 }
602 if self.has_ended(now) &&
603 self.fill_mode != AnimationFillMode::Forwards &&
604 self.fill_mode != AnimationFillMode::Both
605 {
606 return;
607 }
608 let total_progress = total_progress
609 .min(self.current_iteration_end_progress())
610 .max(0.0);
611
612 let next_keyframe_index;
614 let prev_keyframe_index;
615 let num_steps = self.computed_steps.len();
616 match self.current_direction {
617 AnimationDirection::Normal => {
618 next_keyframe_index = self
619 .computed_steps
620 .iter()
621 .position(|step| total_progress as f32 <= step.start_percentage);
622 prev_keyframe_index = next_keyframe_index
623 .and_then(|pos| if pos != 0 { Some(pos - 1) } else { None })
624 .unwrap_or(0);
625 },
626 AnimationDirection::Reverse => {
627 next_keyframe_index = self
628 .computed_steps
629 .iter()
630 .rev()
631 .position(|step| total_progress as f32 <= 1. - step.start_percentage)
632 .map(|pos| num_steps - pos - 1);
633 prev_keyframe_index = next_keyframe_index
634 .and_then(|pos| {
635 if pos != num_steps - 1 {
636 Some(pos + 1)
637 } else {
638 None
639 }
640 })
641 .unwrap_or(num_steps - 1)
642 },
643 _ => unreachable!(),
644 }
645
646 debug!(
647 "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}",
648 prev_keyframe_index, next_keyframe_index
649 );
650
651 let prev_keyframe = &self.computed_steps[prev_keyframe_index];
652 let next_keyframe = match next_keyframe_index {
653 Some(index) => &self.computed_steps[index],
654 None => return,
655 };
656
657 let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
660 for value in keyframe.values.iter() {
661 map.insert(value.id().to_owned(), value.clone());
662 }
663 };
664 if total_progress <= 0.0 {
665 add_declarations_to_map(&prev_keyframe);
666 return;
667 }
668 if total_progress >= 1.0 {
669 add_declarations_to_map(&next_keyframe);
670 return;
671 }
672
673 let percentage_between_keyframes =
674 (next_keyframe.start_percentage - prev_keyframe.start_percentage).abs() as f64;
675 let duration_between_keyframes = percentage_between_keyframes * self.duration;
676 let direction_aware_prev_keyframe_start_percentage = match self.current_direction {
677 AnimationDirection::Normal => prev_keyframe.start_percentage as f64,
678 AnimationDirection::Reverse => 1. - prev_keyframe.start_percentage as f64,
679 _ => unreachable!(),
680 };
681 let progress_between_keyframes = (total_progress -
682 direction_aware_prev_keyframe_start_percentage) /
683 percentage_between_keyframes;
684
685 for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) {
686 let animation = PropertyAnimation {
687 from: from.clone(),
688 to: to.clone(),
689 timing_function: prev_keyframe.timing_function.clone(),
690 duration: duration_between_keyframes as f64,
691 };
692
693 let value = animation.calculate_value(progress_between_keyframes);
694 map.insert(value.id().to_owned(), value);
695 }
696 }
697}
698
699impl fmt::Debug for Animation {
700 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
701 f.debug_struct("Animation")
702 .field("name", &self.name)
703 .field("started_at", &self.started_at)
704 .field("duration", &self.duration)
705 .field("delay", &self.delay)
706 .field("iteration_state", &self.iteration_state)
707 .field("state", &self.state)
708 .field("direction", &self.direction)
709 .field("current_direction", &self.current_direction)
710 .field("cascade_style", &())
711 .finish()
712 }
713}
714
715#[derive(Clone, Debug, MallocSizeOf)]
717pub struct Transition {
718 pub start_time: f64,
721
722 pub delay: f64,
724
725 pub property_animation: PropertyAnimation,
727
728 pub state: AnimationState,
730
731 pub is_new: bool,
734
735 pub reversing_adjusted_start_value: AnimationValue,
738
739 pub reversing_shortening_factor: f64,
742}
743
744impl Transition {
745 fn new(
746 start_time: f64,
747 delay: f64,
748 duration: f64,
749 from: AnimationValue,
750 to: AnimationValue,
751 timing_function: &TimingFunction,
752 ) -> Self {
753 let property_animation = PropertyAnimation {
754 from: from.clone(),
755 to,
756 timing_function: timing_function.clone(),
757 duration,
758 };
759 Self {
760 start_time,
761 delay,
762 property_animation,
763 state: AnimationState::Pending,
764 is_new: true,
765 reversing_adjusted_start_value: from,
766 reversing_shortening_factor: 1.0,
767 }
768 }
769
770 fn update_for_possibly_reversed_transition(
771 &mut self,
772 replaced_transition: &Transition,
773 delay: f64,
774 now: f64,
775 ) {
776 if replaced_transition.reversing_adjusted_start_value != self.property_animation.to {
785 return;
786 }
787
788 let replaced_animation = &replaced_transition.property_animation;
790 self.reversing_adjusted_start_value = replaced_animation.to.clone();
791
792 let transition_progress = ((now - replaced_transition.start_time) /
799 (replaced_transition.property_animation.duration))
800 .min(1.0)
801 .max(0.0);
802 let timing_function_output = replaced_animation.timing_function_output(transition_progress);
803 let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor;
804 self.reversing_shortening_factor = ((timing_function_output *
805 old_reversing_shortening_factor) +
806 (1.0 - old_reversing_shortening_factor))
807 .abs()
808 .min(1.0)
809 .max(0.0);
810
811 self.start_time = if delay >= 0. {
817 now + delay
818 } else {
819 now + (self.reversing_shortening_factor * delay)
820 };
821
822 self.property_animation.duration *= self.reversing_shortening_factor;
825
826 let procedure = Procedure::Interpolate {
829 progress: timing_function_output,
830 };
831 match replaced_animation
832 .from
833 .animate(&replaced_animation.to, procedure)
834 {
835 Ok(new_start) => self.property_animation.from = new_start,
836 Err(..) => {},
837 }
838 }
839
840 pub fn has_ended(&self, time: f64) -> bool {
844 time >= self.start_time + (self.property_animation.duration)
845 }
846
847 pub fn calculate_value(&self, time: f64) -> AnimationValue {
849 let progress = (time - self.start_time) / (self.property_animation.duration);
850 self.property_animation.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.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.transitions
941 .iter()
942 .filter(|transition| transition.state.needs_to_be_ticked())
943 .count()
944 }
945
946 pub fn has_active_animation(&self) -> bool {
948 self.animations
949 .iter()
950 .any(|animation| animation.state != AnimationState::Canceled)
951 }
952
953 pub fn has_active_transition(&self) -> bool {
955 self.transitions
956 .iter()
957 .any(|transition| transition.state != AnimationState::Canceled)
958 }
959
960 pub fn update_animations_for_new_style<E>(
963 &mut self,
964 element: E,
965 context: &SharedStyleContext,
966 new_style: &Arc<ComputedValues>,
967 resolver: &mut StyleResolverForElement<E>,
968 ) where
969 E: TElement,
970 {
971 for animation in self.animations.iter_mut() {
972 if animation.is_cancelled_in_new_style(new_style) {
973 animation.state = AnimationState::Canceled;
974 }
975 }
976
977 maybe_start_animations(element, &context, &new_style, self, resolver);
978 }
979
980 pub fn update_transitions_for_new_style(
983 &mut self,
984 might_need_transitions_update: bool,
985 context: &SharedStyleContext,
986 old_style: Option<&Arc<ComputedValues>>,
987 after_change_style: &Arc<ComputedValues>,
988 ) {
989 let mut before_change_style = match old_style {
992 Some(old_style) => Arc::clone(old_style),
993 None => return,
994 };
995
996 if after_change_style.get_box().clone_display().is_none() {
998 self.cancel_active_transitions();
999 return;
1000 }
1001
1002 if !might_need_transitions_update {
1003 return;
1004 }
1005
1006 if self.has_active_transition() || self.has_active_animation() {
1008 self.apply_active_animations(context, &mut before_change_style);
1009 }
1010
1011 let transitioning_properties = start_transitions_if_applicable(
1012 context,
1013 &before_change_style,
1014 after_change_style,
1015 self,
1016 );
1017
1018 for transition in self.transitions.iter_mut() {
1031 if transition.state == AnimationState::Finished
1032 || transition.state == AnimationState::Canceled
1033 {
1034 continue;
1035 }
1036 if transitioning_properties.contains(transition.property_animation.property_id()) {
1037 continue;
1038 }
1039 transition.state = AnimationState::Canceled;
1040 self.dirty = true;
1041 }
1042 }
1043
1044 fn start_transition_if_applicable(
1045 &mut self,
1046 context: &SharedStyleContext,
1047 property_declaration_id: &PropertyDeclarationId,
1048 index: usize,
1049 old_style: &ComputedValues,
1050 new_style: &Arc<ComputedValues>,
1051 ) {
1052 let style = new_style.get_ui();
1053 let allow_discrete =
1054 style.transition_behavior_mod(index) == TransitionBehavior::AllowDiscrete;
1055
1056 let Some(from) = AnimationValue::from_computed_values(*property_declaration_id, old_style)
1058 else {
1059 return;
1060 };
1061 let Some(to) = AnimationValue::from_computed_values(*property_declaration_id, new_style)
1062 else {
1063 return;
1064 };
1065
1066 let timing_function = style.transition_timing_function_mod(index);
1067 let duration = style.transition_duration_mod(index).seconds() as f64;
1068 let delay = style.transition_delay_mod(index).seconds() as f64;
1069 let now = context.current_time_for_animations;
1070 let transitionable = property_declaration_id.is_animatable()
1071 && (allow_discrete || !property_declaration_id.is_discrete_animatable())
1072 && (allow_discrete || from.interpolable_with(&to));
1073
1074 let mut existing_transition = self.transitions.iter_mut().find(|transition| {
1075 transition.property_animation.property_id() == *property_declaration_id
1076 });
1077
1078 let has_running_transition = existing_transition.as_ref().is_some_and(|transition| {
1093 transition.state != AnimationState::Finished
1094 && transition.state != AnimationState::Canceled
1095 });
1096 let no_completed_transition_or_end_values_differ = existing_transition.as_ref().is_none_or(|transition| {
1097 transition.state != AnimationState::Finished || transition.property_animation.to != to
1098 });
1099 if !has_running_transition &&
1100 from != to && transitionable &&
1101 no_completed_transition_or_end_values_differ &&
1102 (duration + delay > 0.0) {
1103 self.transitions.push(Transition::new(
1114 now + delay, delay,
1116 duration,
1117 from,
1118 to,
1119 &timing_function,
1120 ));
1121 self.dirty = true;
1122 return;
1123 }
1124
1125 let Some(existing_transition) = existing_transition.as_mut() else {
1148 return;
1149 };
1150
1151 if has_running_transition && existing_transition.property_animation.to != to {
1156 let current_value = existing_transition.calculate_value(now);
1161 let transitionable_from_current_value =
1162 transitionable && (allow_discrete || current_value.interpolable_with(&to));
1163 if current_value == to || !transitionable_from_current_value {
1164 existing_transition.state = AnimationState::Canceled;
1165 self.dirty = true;
1166 return;
1167 }
1168
1169 if duration + delay <= 0.0 {
1175 existing_transition.state = AnimationState::Canceled;
1176 self.dirty = true;
1177 return;
1178 }
1179
1180 if existing_transition.reversing_adjusted_start_value == to {
1186 existing_transition.state = AnimationState::Canceled;
1187
1188 let mut transition = Transition::new(
1189 now + delay, delay,
1191 duration,
1192 from,
1193 to,
1194 &timing_function,
1195 );
1196
1197 transition.update_for_possibly_reversed_transition(
1200 &existing_transition,
1201 delay,
1202 now,
1203 );
1204
1205 self.transitions.push(transition);
1206 self.dirty = true;
1207 return;
1208 }
1209
1210 existing_transition.state = AnimationState::Canceled;
1219 self.transitions.push(Transition::new(
1220 now + delay, delay,
1222 duration,
1223 current_value,
1224 to,
1225 &timing_function,
1226 ));
1227 self.dirty = true;
1228 }
1229 }
1230
1231 fn get_value_map_for_transitions(
1235 &self,
1236 now: f64,
1237 ignore_transitions: IgnoreTransitions,
1238 ) -> Option<AnimationValueMap> {
1239 if !self.has_active_transition() {
1240 return None;
1241 }
1242
1243 let mut map =
1244 AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default());
1245 for transition in &self.transitions {
1246 match ignore_transitions {
1247 IgnoreTransitions::Canceled => {
1248 if transition.state == AnimationState::Canceled {
1249 continue;
1250 }
1251 },
1252 IgnoreTransitions::CanceledAndFinished => {
1253 if transition.state == AnimationState::Canceled
1254 || transition.state == AnimationState::Finished
1255 {
1256 continue;
1257 }
1258 },
1259 }
1260
1261 let value = transition.calculate_value(now);
1262 map.insert(value.id().to_owned(), value);
1263 }
1264
1265 Some(map)
1266 }
1267
1268 pub fn get_value_map_for_active_animations(&self, now: f64) -> Option<AnimationValueMap> {
1271 if !self.has_active_animation() {
1272 return None;
1273 }
1274
1275 let mut map = Default::default();
1276 for animation in &self.animations {
1277 animation.get_property_declaration_at_time(now, &mut map);
1278 }
1279
1280 Some(map)
1281 }
1282}
1283
1284#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
1285pub struct AnimationSetKey {
1287 pub node: OpaqueNode,
1289 pub pseudo_element: Option<PseudoElement>,
1292}
1293
1294impl AnimationSetKey {
1295 pub fn new(node: OpaqueNode, pseudo_element: Option<PseudoElement>) -> Self {
1297 AnimationSetKey {
1298 node,
1299 pseudo_element,
1300 }
1301 }
1302
1303 pub fn new_for_non_pseudo(node: OpaqueNode) -> Self {
1305 AnimationSetKey {
1306 node,
1307 pseudo_element: None,
1308 }
1309 }
1310
1311 pub fn new_for_pseudo(node: OpaqueNode, pseudo_element: PseudoElement) -> Self {
1313 AnimationSetKey {
1314 node,
1315 pseudo_element: Some(pseudo_element),
1316 }
1317 }
1318}
1319
1320#[derive(Clone, Debug, Default, MallocSizeOf)]
1321pub struct DocumentAnimationSet {
1323 #[ignore_malloc_size_of = "Arc is hard"]
1325 pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
1326}
1327
1328impl DocumentAnimationSet {
1329 pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
1331 self.sets
1332 .read()
1333 .get(key)
1334 .map_or(false, |set| set.has_active_animation())
1335 }
1336
1337 pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
1339 self.sets
1340 .read()
1341 .get(key)
1342 .map_or(false, |set| set.has_active_transition())
1343 }
1344
1345 pub fn get_animation_declarations(
1348 &self,
1349 key: &AnimationSetKey,
1350 time: f64,
1351 shared_lock: &SharedRwLock,
1352 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1353 self.sets
1354 .read()
1355 .get(key)
1356 .and_then(|set| set.get_value_map_for_active_animations(time))
1357 .map(|map| {
1358 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1359 Arc::new(shared_lock.wrap(block))
1360 })
1361 }
1362
1363 pub fn get_transition_declarations(
1366 &self,
1367 key: &AnimationSetKey,
1368 time: f64,
1369 shared_lock: &SharedRwLock,
1370 ) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
1371 self.sets
1372 .read()
1373 .get(key)
1374 .and_then(|set| {
1375 set.get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1376 })
1377 .map(|map| {
1378 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1379 Arc::new(shared_lock.wrap(block))
1380 })
1381 }
1382
1383 pub fn get_all_declarations(
1386 &self,
1387 key: &AnimationSetKey,
1388 time: f64,
1389 shared_lock: &SharedRwLock,
1390 ) -> AnimationDeclarations {
1391 let sets = self.sets.read();
1392 let set = match sets.get(key) {
1393 Some(set) => set,
1394 None => return Default::default(),
1395 };
1396
1397 let animations = set.get_value_map_for_active_animations(time).map(|map| {
1398 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1399 Arc::new(shared_lock.wrap(block))
1400 });
1401 let transitions = set
1402 .get_value_map_for_transitions(time, IgnoreTransitions::CanceledAndFinished)
1403 .map(|map| {
1404 let block = PropertyDeclarationBlock::from_animation_value_map(&map);
1405 Arc::new(shared_lock.wrap(block))
1406 });
1407 AnimationDeclarations {
1408 animations,
1409 transitions,
1410 }
1411 }
1412
1413 pub fn cancel_all_animations_for_key(&self, key: &AnimationSetKey) {
1415 if let Some(set) = self.sets.write().get_mut(key) {
1416 set.cancel_all_animations();
1417 }
1418 }
1419}
1420
1421pub fn start_transitions_if_applicable(
1424 context: &SharedStyleContext,
1425 old_style: &ComputedValues,
1426 new_style: &Arc<ComputedValues>,
1427 animation_state: &mut ElementAnimationSet,
1428) -> PropertyDeclarationIdSet {
1429 let mut transition_properties = new_style.transition_properties().collect::<Vec<_>>();
1444 transition_properties.reverse();
1445
1446 let mut properties_that_transition = PropertyDeclarationIdSet::default();
1447 for transition in transition_properties {
1448 let physical_property = transition
1449 .property
1450 .as_borrowed()
1451 .to_physical(new_style.writing_mode);
1452 if properties_that_transition.contains(physical_property) {
1453 continue;
1454 }
1455
1456 properties_that_transition.insert(physical_property);
1457 animation_state.start_transition_if_applicable(
1458 context,
1459 &physical_property,
1460 transition.index,
1461 old_style,
1462 new_style,
1463 );
1464 }
1465
1466 properties_that_transition
1467}
1468
1469pub fn maybe_start_animations<E>(
1472 element: E,
1473 context: &SharedStyleContext,
1474 new_style: &Arc<ComputedValues>,
1475 animation_state: &mut ElementAnimationSet,
1476 resolver: &mut StyleResolverForElement<E>,
1477) where
1478 E: TElement,
1479{
1480 let style = new_style.get_ui();
1481 for (i, name) in style.animation_name_iter().enumerate() {
1482 let name = match name.as_atom() {
1483 Some(atom) => atom,
1484 None => continue,
1485 };
1486
1487 debug!("maybe_start_animations: name={}", name);
1488 let duration = style.animation_duration_mod(i).seconds() as f64;
1489 if duration == 0. {
1490 continue;
1491 }
1492
1493 let keyframe_animation = match context.stylist.get_animation(name, element) {
1494 Some(animation) => animation,
1495 None => continue,
1496 };
1497
1498 debug!("maybe_start_animations: animation {} found", name);
1499
1500 if keyframe_animation.steps.is_empty() {
1505 continue;
1506 }
1507
1508 let delay = style.animation_delay_mod(i).seconds();
1512
1513 let iteration_count = style.animation_iteration_count_mod(i);
1514 let iteration_state = if iteration_count.0.is_infinite() {
1515 KeyframesIterationState::Infinite(0.0)
1516 } else {
1517 KeyframesIterationState::Finite(0.0, iteration_count.0 as f64)
1518 };
1519
1520 let animation_direction = style.animation_direction_mod(i);
1521
1522 let initial_direction = match animation_direction {
1523 AnimationDirection::Normal | AnimationDirection::Alternate => {
1524 AnimationDirection::Normal
1525 },
1526 AnimationDirection::Reverse | AnimationDirection::AlternateReverse => {
1527 AnimationDirection::Reverse
1528 },
1529 };
1530
1531 let now = context.current_time_for_animations;
1532 let started_at = now + delay as f64;
1533 let mut starting_progress = (now - started_at) / duration;
1534 let state = match style.animation_play_state_mod(i) {
1535 AnimationPlayState::Paused => AnimationState::Paused(starting_progress),
1536 AnimationPlayState::Running => AnimationState::Pending,
1537 };
1538
1539 let computed_steps = ComputedKeyframe::generate_for_keyframes(
1540 element,
1541 &keyframe_animation,
1542 context,
1543 new_style,
1544 style.animation_timing_function_mod(i),
1545 resolver,
1546 );
1547
1548 let mut new_animation = Animation {
1549 name: name.clone(),
1550 properties_changed: keyframe_animation.properties_changed.clone(),
1551 computed_steps,
1552 started_at,
1553 duration,
1554 fill_mode: style.animation_fill_mode_mod(i),
1555 delay: delay as f64,
1556 iteration_state,
1557 state,
1558 direction: animation_direction,
1559 current_direction: initial_direction,
1560 cascade_style: new_style.clone(),
1561 is_new: true,
1562 };
1563
1564 while starting_progress > 1. && !new_animation.on_last_iteration() {
1567 new_animation.iterate();
1568 starting_progress -= 1.;
1569 }
1570
1571 animation_state.dirty = true;
1572
1573 for existing_animation in animation_state.animations.iter_mut() {
1575 if existing_animation.state == AnimationState::Canceled {
1576 continue;
1577 }
1578
1579 if new_animation.name == existing_animation.name {
1580 existing_animation
1581 .update_from_other(&new_animation, context.current_time_for_animations);
1582 return;
1583 }
1584 }
1585
1586 animation_state.animations.push(new_animation);
1587 }
1588}