@@ -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 ) ;
@@ -1024,48 +1000,7 @@ impl ElementAnimationSet {
10241000 self . dirty = true ;
10251001 continue ;
10261002 }
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`
1068- }
1003+ // Step 4 was done in `fn start_transition_if_applicable`
10691004 }
10701005 }
10711006
@@ -1079,85 +1014,116 @@ impl ElementAnimationSet {
10791014 ) {
10801015 let style = new_style. get_ui ( ) ;
10811016 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- }
1017+ let not_transitionable = !property_declaration_id. is_animatable ( ) ||
1018+ ( !allow_discrete && property_declaration_id. is_discrete_animatable ( ) ) ;
1019+
1020+ let mut start_new_transition = !not_transitionable;
10881021
10891022 let timing_function = style. transition_timing_function_mod ( index) ;
10901023 let duration = style. transition_duration_mod ( index) . seconds ( ) as f64 ;
10911024 let delay = style. transition_delay_mod ( index) . seconds ( ) as f64 ;
10921025 let now = context. current_time_for_animations ;
10931026
10941027 if duration + delay <= 0.0 {
1095- return ;
1028+ start_new_transition = false ;
10961029 }
10971030
1031+ // FIXME(emilio): Handle the case where old_style and new_style's writing mode differ.
1032+ let property_declaration = property_declaration_id. to_physical ( new_style. writing_mode ) ;
1033+ let Some ( from) = AnimationValue :: from_computed_values ( property_declaration, old_style) else {
1034+ return ;
1035+ } ;
1036+ let Some ( to) = AnimationValue :: from_computed_values ( property_declaration, new_style) else {
1037+ return ;
1038+ } ;
1039+
10981040 // Only start a new transition if the style actually changes between
10991041 // 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- } ;
1042+ if from == to {
1043+ start_new_transition = false ;
1044+ }
11101045
11111046 // A property may have an animation type different than 'discrete', but still
11121047 // not be able to interpolate some values. In that case we would fall back to
11131048 // discrete interpolation, so we need to abort if `transition-behavior` doesn't
11141049 // allow discrete transitions.
1115- if !allow_discrete && !property_animation . from . interpolable_with ( & property_animation . to ) {
1116- return ;
1050+ if !allow_discrete && !from. interpolable_with ( & to) {
1051+ start_new_transition = false ;
11171052 }
11181053
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
1054+ // Step 4 in https://drafts.csswg.org/css-transitions/#starting
1055+ // "If the element has a running transition for the property, there is a matching transition-property value,
1056+ let mut running_transition = None ;
1057+ if let Some ( old_transition) = self
11241058 . transitions
1125- . iter ( )
1126- . filter ( |transition| transition. state != AnimationState :: Canceled )
1127- . any ( |transition| transition. property_animation . to == property_animation. to )
1059+ . iter_mut ( )
1060+ . filter ( |transition| transition. state != AnimationState :: Canceled
1061+ && transition. state != AnimationState :: Finished )
1062+ . find ( |transition| {
1063+ transition. property_animation . property_id ( ) == * property_declaration_id
1064+ } )
11281065 {
1129- return ;
1066+ // and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1067+ if to != old_transition. property_animation . to {
1068+ let current_val = old_transition. calculate_value ( now) ;
1069+ let not_transitionable = not_transitionable||
1070+ ( !allow_discrete && !current_val. interpolable_with ( & to) ) ;
1071+
1072+ // Step 4.1
1073+ //"If the current value of the property in the running transition is equal
1074+ // to the value of the property in the after-change style,
1075+ // or if these two values are not transitionable, then implementations must cancel the running transition."
1076+ if current_val == to || not_transitionable {
1077+ old_transition. state = AnimationState :: Canceled ;
1078+ self . dirty = true ;
1079+ start_new_transition = false ;
1080+ }
1081+ // Step 4.2
1082+ // "Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1083+ // running transition is not transitionable with the value of the property in the after-change style,
1084+ // then implementations must cancel the running transition."
1085+ else if duration + delay <= 0.0 {
1086+ old_transition. state = AnimationState :: Canceled ;
1087+ self . dirty = true ;
1088+ start_new_transition = false ;
1089+ }
1090+ } else {
1091+ start_new_transition = false ;
1092+ }
1093+ running_transition = Some ( old_transition) ;
11301094 }
11311095
11321096 // Step 1 + 4.3 + 4.4 in https://drafts.csswg.org/css-transitions/#starting
11331097 // We are going to start a new transition, but we might have to update
11341098 // 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- } ;
1099+ if start_new_transition {
1100+ let property_animation = PropertyAnimation {
1101+ from,
1102+ to,
1103+ timing_function,
1104+ duration,
1105+ } ;
1106+
1107+ let reversing_adjusted_start_value = property_animation. from . clone ( ) ;
1108+ let mut new_transition = Transition {
1109+ start_time : now + delay,
1110+ delay,
1111+ property_animation,
1112+ state : AnimationState :: Pending ,
1113+ is_new : true ,
1114+ reversing_adjusted_start_value,
1115+ reversing_shortening_factor : 1.0 ,
1116+ } ;
11451117
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- {
11541118 // 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- }
1119+ if let Some ( old_transition) = running_transition {
1120+ old_transition. state = AnimationState :: Canceled ;
1121+ new_transition. update_for_possibly_reversed_transition ( old_transition, delay, now) ;
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
0 commit comments