Skip to content

Commit 6366c45

Browse files
committed
Performance Optimization: Revamp
Signed-off-by: Euclid Ye <[email protected]>
1 parent 5aae785 commit 6366c45

File tree

1 file changed

+82
-119
lines changed

1 file changed

+82
-119
lines changed

style/animation.rs

+82-119
Original file line numberDiff line numberDiff line change
@@ -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,129 @@ 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+
10981038
// Only start a new transition if the style actually changes between
10991039
// 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-
};
1040+
if from == to {
1041+
start_new_transition = false;
1042+
}
11101043

11111044
// A property may have an animation type different than 'discrete', but still
11121045
// not be able to interpolate some values. In that case we would fall back to
11131046
// discrete interpolation, so we need to abort if `transition-behavior` doesn't
11141047
// allow discrete transitions.
1115-
if !allow_discrete && !property_animation.from.interpolable_with(&property_animation.to) {
1116-
return;
1048+
if !allow_discrete && !from.interpolable_with(&to) {
1049+
start_new_transition = false;
11171050
}
11181051

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
1052+
// Step 4 in https://drafts.csswg.org/css-transitions/#starting
1053+
// "If the element has a running transition for the property, there is a matching transition-property value,
1054+
let mut running_transition = None;
1055+
if let Some(old_transition) = self
11241056
.transitions
1125-
.iter()
1057+
.iter_mut()
11261058
.filter(|transition| transition.state != AnimationState::Canceled)
1127-
.any(|transition| transition.property_animation.to == property_animation.to)
1059+
.find(|transition| {
1060+
transition.property_animation.property_id() == property_declaration
1061+
})
11281062
{
1129-
return;
1063+
// and the end value of the running transition is not equal to the value of the property in the after-change style, then:"
1064+
if to != old_transition.property_animation.to {
1065+
let current_val = old_transition.calculate_value(now);
1066+
let not_transitionable = not_transitionable||
1067+
(!allow_discrete && !current_val.interpolable_with(&to));
1068+
1069+
// Step 4.1
1070+
//"If the current value of the property in the running transition is equal
1071+
// to the value of the property in the after-change style,
1072+
// or if these two values are not transitionable, then implementations must cancel the running transition."
1073+
if current_val == to || not_transitionable {
1074+
old_transition.state = AnimationState::Canceled;
1075+
self.dirty = true;
1076+
start_new_transition = false;
1077+
}
1078+
// Step 4.2
1079+
// "Otherwise, if the combined duration is less than or equal to 0s, or if the current value of the property in the
1080+
// running transition is not transitionable with the value of the property in the after-change style,
1081+
// then implementations must cancel the running transition."
1082+
else if duration + delay <= 0.0 {
1083+
old_transition.state = AnimationState::Canceled;
1084+
self.dirty = true;
1085+
start_new_transition = false;
1086+
}
1087+
} else{
1088+
start_new_transition = false;
1089+
}
1090+
running_transition = Some(old_transition);
11301091
}
11311092

11321093
// Step 1 + 4.3 + 4.4 in https://drafts.csswg.org/css-transitions/#starting
11331094
// We are going to start a new transition, but we might have to update
11341095
// 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-
};
1096+
if start_new_transition {
1097+
let property_animation = PropertyAnimation {
1098+
from,
1099+
to,
1100+
timing_function,
1101+
duration,
1102+
};
1103+
1104+
let reversing_adjusted_start_value = property_animation.from.clone();
1105+
let mut new_transition = Transition {
1106+
start_time: now + delay,
1107+
delay,
1108+
property_animation,
1109+
state: AnimationState::Pending,
1110+
is_new: true,
1111+
reversing_adjusted_start_value,
1112+
reversing_shortening_factor: 1.0,
1113+
};
11451114

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-
{
11541115
// 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-
}
1116+
if let Some(old_transition) = running_transition {
1117+
old_transition.state = AnimationState::Canceled;
1118+
new_transition.update_for_possibly_reversed_transition(old_transition, delay, now);
1119+
}
11581120

1159-
self.transitions.push(new_transition);
1160-
self.dirty = true;
1121+
self.transitions.push(new_transition);
1122+
self.dirty = true;
1123+
}
11611124
}
11621125

11631126
/// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s
@@ -1370,7 +1333,7 @@ pub fn start_transitions_if_applicable(
13701333
properties_that_transition.insert(physical_property);
13711334
animation_state.start_transition_if_applicable(
13721335
context,
1373-
&physical_property,
1336+
physical_property,
13741337
transition.index,
13751338
old_style,
13761339
new_style,

0 commit comments

Comments
 (0)