@@ -57,30 +57,6 @@ impl PropertyAnimation {
5757 self . from . id ( )
5858 }
5959
60- fn from_property_declaration (
61- property_declaration : & PropertyDeclarationId ,
62- timing_function : TimingFunction ,
63- duration : f64 ,
64- old_style : & ComputedValues ,
65- new_style : & ComputedValues ,
66- ) -> Option < PropertyAnimation > {
67- // FIXME(emilio): Handle the case where old_style and new_style's writing mode differ.
68- let property_declaration = property_declaration. to_physical ( new_style. writing_mode ) ;
69- let from = AnimationValue :: from_computed_values ( property_declaration, old_style) ?;
70- let to = AnimationValue :: from_computed_values ( property_declaration, new_style) ?;
71-
72- if from == to {
73- return None ;
74- }
75-
76- Some ( PropertyAnimation {
77- from,
78- to,
79- timing_function,
80- duration,
81- } )
82- }
83-
8460 /// The output of the timing function given the progress ration of this animation.
8561 fn timing_function_output ( & self , progress : f64 ) -> f64 {
8662 let epsilon = 1. / ( 200. * self . duration ) ;
@@ -1022,142 +998,132 @@ impl ElementAnimationSet {
1022998 if !transitioning_properties. contains ( transition_property_id) {
1023999 transition. state = AnimationState :: Canceled ;
10241000 self . dirty = true ;
1025- continue ;
1026- }
1027-
1028- let after_change_to = AnimationValue :: from_computed_values ( transition_property_id, & after_change_style) . unwrap ( ) ;
1029- // Step 4
1030- // "If the element has a running transition for the property, there is a matching transition-property value,
1031- // and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1032- if transition. property_animation . to != after_change_to {
1033- // index for after-change transition declaration
1034- let index = after_change_style. transition_properties ( ) . position ( |declared_transition| declared_transition. property
1035- . as_borrowed ( )
1036- . to_physical ( after_change_style. writing_mode ) == transition_property_id) . unwrap ( ) ;
1037-
1038- let now = context. current_time_for_animations ;
1039- let after_change_style = after_change_style. get_ui ( ) ;
1040- let allow_discrete = after_change_style. transition_behavior_mod ( index) == TransitionBehavior :: AllowDiscrete ;
1041- let current_val = transition. calculate_value ( now) ;
1042- let not_transitionable =
1043- ( !transition_property_id. is_animatable ( ) || ( !allow_discrete && transition_property_id. is_discrete_animatable ( ) ) )
1044- || ( !allow_discrete && !current_val. interpolable_with ( & after_change_to) ) ;
1045-
1046- let combined_duration = after_change_style. transition_duration_mod ( index) . seconds ( ) + after_change_style. transition_delay_mod ( index) . seconds ( ) ;
1047-
1048- // Step 4.1
1049- //"If the current value of the property in the running transition is equal
1050- // to the value of the property in the after-change style,
1051- // or if these two values are not transitionable, then implementations must cancel the running transition."
1052- if current_val == after_change_to || not_transitionable {
1053- transition. state = AnimationState :: Canceled ;
1054- self . dirty = true ;
1055- continue ;
1056- }
1057- // Step 4.2
1058- // "Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1059- // running transition is not transitionable with the value of the property in the after-change style,
1060- // then implementations must cancel the running transition."
1061- else if combined_duration <= 0.0 {
1062- transition. state = AnimationState :: Canceled ;
1063- self . dirty = true ;
1064- continue ;
1065- }
1066-
1067- //Step 4.3, 4.4 have been done in `fn start_transition_if_applicable`
10681001 }
1002+ // Step 4 was done in `fn start_transition_if_applicable`
10691003 }
10701004 }
10711005
10721006 fn start_transition_if_applicable (
10731007 & mut self ,
10741008 context : & SharedStyleContext ,
1075- property_declaration_id : & PropertyDeclarationId ,
1009+ property_declaration : PropertyDeclarationId ,
10761010 index : usize ,
10771011 old_style : & ComputedValues ,
10781012 new_style : & Arc < ComputedValues > ,
10791013 ) {
10801014 let style = new_style. get_ui ( ) ;
10811015 let allow_discrete = style. transition_behavior_mod ( index) == TransitionBehavior :: AllowDiscrete ;
1082-
1083- if !property_declaration_id. is_animatable ( )
1084- || ( !allow_discrete && property_declaration_id. is_discrete_animatable ( ) )
1085- {
1086- return ;
1087- }
1016+ let not_transitionable = !property_declaration. is_animatable ( ) ||
1017+ ( !allow_discrete && property_declaration. is_discrete_animatable ( ) ) ;
1018+
1019+ let mut start_new_transition = !not_transitionable;
10881020
10891021 let timing_function = style. transition_timing_function_mod ( index) ;
10901022 let duration = style. transition_duration_mod ( index) . seconds ( ) as f64 ;
10911023 let delay = style. transition_delay_mod ( index) . seconds ( ) as f64 ;
10921024 let now = context. current_time_for_animations ;
10931025
10941026 if duration + delay <= 0.0 {
1095- return ;
1027+ start_new_transition = false ;
10961028 }
10971029
1030+ // FIXME(emilio): Handle the case where old_style and new_style's writing mode differ.
1031+ let Some ( from) = AnimationValue :: from_computed_values ( property_declaration, old_style) else {
1032+ return ;
1033+ } ;
1034+ let Some ( to) = AnimationValue :: from_computed_values ( property_declaration, new_style) else {
1035+ return ;
1036+ } ;
1037+
1038+
10981039 // Only start a new transition if the style actually changes between
10991040 // the old style and the new style.
1100- let property_animation = match PropertyAnimation :: from_property_declaration (
1101- property_declaration_id,
1102- timing_function,
1103- duration,
1104- old_style,
1105- new_style,
1106- ) {
1107- Some ( property_animation) => property_animation,
1108- None => return ,
1109- } ;
1041+ if from == to {
1042+ start_new_transition = false ;
1043+ }
11101044
11111045 // A property may have an animation type different than 'discrete', but still
11121046 // not be able to interpolate some values. In that case we would fall back to
11131047 // discrete interpolation, so we need to abort if `transition-behavior` doesn't
11141048 // allow discrete transitions.
1115- if !allow_discrete && !property_animation . from . interpolable_with ( & property_animation . to ) {
1116- return ;
1049+ if !allow_discrete && !from. interpolable_with ( & to) {
1050+ start_new_transition = false ;
11171051 }
11181052
1119- // Per [1], don't trigger a new transition if the end state for that
1120- // transition is the same as that of a transition that's running or
1121- // completed. We don't take into account any canceled animations.
1122- // [1]: https://drafts.csswg.org/css-transitions/#starting
1123- if self
1053+ // Step 4 in https://drafts.csswg.org/css-transitions/#starting
1054+ // "If the element has a running transition for the property, there is a matching transition-property value,
1055+ let mut running_transition = None ;
1056+ if let Some ( old_transition) = self
11241057 . transitions
1125- . iter ( )
1058+ . iter_mut ( )
11261059 . filter ( |transition| transition. state != AnimationState :: Canceled )
1127- . any ( |transition| transition. property_animation . to == property_animation. to )
1060+ . find ( |transition| {
1061+ transition. property_animation . property_id ( ) == property_declaration
1062+ } )
11281063 {
1129- return ;
1064+ // and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1065+ if to != old_transition. property_animation . to {
1066+ let current_val = old_transition. calculate_value ( now) ;
1067+ let not_transitionable = not_transitionable||
1068+ ( !allow_discrete && !current_val. interpolable_with ( & to) ) ;
1069+
1070+ // Step 4.1
1071+ //"If the current value of the property in the running transition is equal
1072+ // to the value of the property in the after-change style,
1073+ // or if these two values are not transitionable, then implementations must cancel the running transition."
1074+ if current_val == to || not_transitionable {
1075+ old_transition. state = AnimationState :: Canceled ;
1076+ self . dirty = true ;
1077+ start_new_transition = false ;
1078+ }
1079+ // Step 4.2
1080+ // "Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1081+ // running transition is not transitionable with the value of the property in the after-change style,
1082+ // then implementations must cancel the running transition."
1083+ else if duration + delay <= 0.0 {
1084+ old_transition. state = AnimationState :: Canceled ;
1085+ self . dirty = true ;
1086+ start_new_transition = false ;
1087+ }
1088+ } else {
1089+ start_new_transition = false ;
1090+ }
1091+ running_transition = Some ( old_transition) ;
11301092 }
11311093
11321094 // Step 1 + 4.3 + 4.4 in https://drafts.csswg.org/css-transitions/#starting
11331095 // We are going to start a new transition, but we might have to update
11341096 // it if we are replacing a reversed transition.
1135- let reversing_adjusted_start_value = property_animation. from . clone ( ) ;
1136- let mut new_transition = Transition {
1137- start_time : now + delay,
1138- delay,
1139- property_animation,
1140- state : AnimationState :: Pending ,
1141- is_new : true ,
1142- reversing_adjusted_start_value,
1143- reversing_shortening_factor : 1.0 ,
1144- } ;
1097+ if start_new_transition {
1098+ let property_animation = PropertyAnimation {
1099+ from,
1100+ to,
1101+ timing_function,
1102+ duration,
1103+ } ;
1104+
1105+ let reversing_adjusted_start_value = property_animation. from . clone ( ) ;
1106+ let mut new_transition = Transition {
1107+ start_time : now + delay,
1108+ delay,
1109+ property_animation,
1110+ state : AnimationState :: Pending ,
1111+ is_new : true ,
1112+ reversing_adjusted_start_value,
1113+ reversing_shortening_factor : 1.0 ,
1114+ } ;
11451115
1146- if let Some ( old_transition) = self
1147- . transitions
1148- . iter_mut ( )
1149- . filter ( |transition| transition. state == AnimationState :: Running )
1150- . find ( |transition| {
1151- transition. property_animation . property_id ( ) == * property_declaration_id
1152- } )
1153- {
11541116 // We always cancel any running transitions for the same property.
1155- old_transition. state = AnimationState :: Canceled ;
1156- new_transition. update_for_possibly_reversed_transition ( old_transition, delay, now) ;
1157- }
1117+ if let Some ( old_transition) = running_transition {
1118+ if old_transition. state == AnimationState :: Running {
1119+ old_transition. state = AnimationState :: Canceled ;
1120+ new_transition. update_for_possibly_reversed_transition ( old_transition, delay, now) ;
1121+ }
1122+ }
11581123
1159- self . transitions . push ( new_transition) ;
1160- self . dirty = true ;
1124+ self . transitions . push ( new_transition) ;
1125+ self . dirty = true ;
1126+ }
11611127 }
11621128
11631129 /// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
@@ -1370,7 +1336,7 @@ pub fn start_transitions_if_applicable(
13701336 properties_that_transition. insert ( physical_property) ;
13711337 animation_state. start_transition_if_applicable (
13721338 context,
1373- & physical_property,
1339+ physical_property,
13741340 transition. index ,
13751341 old_style,
13761342 new_style,
0 commit comments