зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1631154 - Add an iterator for transition properties. r=emilio
This simplifies the code a bit and also will allow us to more easily make improvements to servo's animation implementation in the future.
This commit is contained in:
Родитель
54e5523868
Коммит
08a4e2cbc2
|
@ -12,14 +12,13 @@ use crate::bezier::Bezier;
|
|||
use crate::context::SharedStyleContext;
|
||||
use crate::dom::{OpaqueNode, TElement};
|
||||
use crate::font_metrics::FontMetricsProvider;
|
||||
use crate::properties::animated_properties::AnimatedProperty;
|
||||
use crate::properties::animated_properties::{AnimatedProperty, TransitionPropertyIteration};
|
||||
use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection;
|
||||
use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
|
||||
use crate::properties::{self, CascadeMode, ComputedValues, LonghandId};
|
||||
use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
|
||||
use crate::stylesheets::Origin;
|
||||
use crate::timer::Timer;
|
||||
use crate::values::computed::box_::TransitionProperty;
|
||||
use crate::values::computed::Time;
|
||||
use crate::values::computed::TimingFunction;
|
||||
use crate::values::generics::box_::AnimationIterationCount;
|
||||
|
@ -271,52 +270,6 @@ impl PropertyAnimation {
|
|||
self.property.name()
|
||||
}
|
||||
|
||||
/// Creates a new property animation for the given transition index and old
|
||||
/// and new styles. Any number of animations may be returned, from zero (if
|
||||
/// the property did not animate) to one (for a single transition property)
|
||||
/// to arbitrarily many (for `all`).
|
||||
pub fn from_transition(
|
||||
transition_index: usize,
|
||||
old_style: &ComputedValues,
|
||||
new_style: &mut ComputedValues,
|
||||
) -> Vec<PropertyAnimation> {
|
||||
let mut result = vec![];
|
||||
let box_style = new_style.get_box();
|
||||
let transition_property = box_style.transition_property_at(transition_index);
|
||||
let timing_function = box_style.transition_timing_function_mod(transition_index);
|
||||
let duration = box_style.transition_duration_mod(transition_index);
|
||||
|
||||
match transition_property {
|
||||
TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => result,
|
||||
TransitionProperty::Shorthand(ref shorthand_id) => shorthand_id
|
||||
.longhands()
|
||||
.filter_map(|longhand| {
|
||||
PropertyAnimation::from_longhand(
|
||||
longhand,
|
||||
timing_function,
|
||||
duration,
|
||||
old_style,
|
||||
new_style,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
TransitionProperty::Longhand(longhand_id) => {
|
||||
let animation = PropertyAnimation::from_longhand(
|
||||
longhand_id,
|
||||
timing_function,
|
||||
duration,
|
||||
old_style,
|
||||
new_style,
|
||||
);
|
||||
|
||||
if let Some(animation) = animation {
|
||||
result.push(animation);
|
||||
}
|
||||
result
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn from_longhand(
|
||||
longhand: LonghandId,
|
||||
timing_function: TimingFunction,
|
||||
|
@ -414,11 +367,23 @@ pub fn start_transitions_if_applicable(
|
|||
running_and_expired_transitions: &[PropertyAnimation],
|
||||
) -> bool {
|
||||
let mut had_animations = false;
|
||||
for i in 0..new_style.get_box().transition_property_count() {
|
||||
// Create any property animations, if applicable.
|
||||
let property_animations =
|
||||
PropertyAnimation::from_transition(i, old_style, Arc::make_mut(new_style));
|
||||
for property_animation in property_animations {
|
||||
let transitions: Vec<TransitionPropertyIteration> = new_style.transition_properties().collect();
|
||||
for transition in &transitions {
|
||||
let property_animation = match PropertyAnimation::from_longhand(
|
||||
transition.longhand_id,
|
||||
new_style
|
||||
.get_box()
|
||||
.transition_timing_function_mod(transition.index),
|
||||
new_style
|
||||
.get_box()
|
||||
.transition_duration_mod(transition.index),
|
||||
old_style,
|
||||
Arc::make_mut(new_style),
|
||||
) {
|
||||
Some(property_animation) => property_animation,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
// Set the property to the initial value.
|
||||
//
|
||||
// NB: get_mut is guaranteed to succeed since we called make_mut()
|
||||
|
@ -450,13 +415,16 @@ pub fn start_transitions_if_applicable(
|
|||
debug!("Kicking off transition of {:?}", property_animation);
|
||||
let box_style = new_style.get_box();
|
||||
let now = timer.seconds();
|
||||
let start_time = now + (box_style.transition_delay_mod(i).seconds() as f64);
|
||||
let start_time = now + (box_style.transition_delay_mod(transition.index).seconds() as f64);
|
||||
let duration = box_style
|
||||
.transition_duration_mod(transition.index)
|
||||
.seconds() as f64;
|
||||
new_animations_sender
|
||||
.send(Animation::Transition(
|
||||
opaque_node,
|
||||
start_time,
|
||||
AnimationFrame {
|
||||
duration: box_style.transition_duration_mod(i).seconds() as f64,
|
||||
duration,
|
||||
property_animation,
|
||||
},
|
||||
))
|
||||
|
@ -464,7 +432,6 @@ pub fn start_transitions_if_applicable(
|
|||
|
||||
had_animations = true;
|
||||
}
|
||||
}
|
||||
|
||||
had_animations
|
||||
}
|
||||
|
|
|
@ -1560,9 +1560,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
before_change_style: &ComputedValues,
|
||||
after_change_style: &ComputedValues,
|
||||
) -> bool {
|
||||
use crate::gecko_bindings::structs::nsCSSPropertyID;
|
||||
use crate::properties::LonghandIdSet;
|
||||
use crate::values::computed::TransitionProperty;
|
||||
|
||||
debug_assert!(
|
||||
self.might_need_transitions_update(Some(before_change_style), after_change_style),
|
||||
|
@ -1571,54 +1569,22 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
);
|
||||
|
||||
let after_change_box_style = after_change_style.get_box();
|
||||
let transitions_count = after_change_box_style.transition_property_count();
|
||||
let existing_transitions = self.css_transitions_info();
|
||||
|
||||
// Check if this property is none, custom or unknown.
|
||||
let is_none_or_custom_property = |property: nsCSSPropertyID| -> bool {
|
||||
return property == nsCSSPropertyID::eCSSPropertyExtra_no_properties ||
|
||||
property == nsCSSPropertyID::eCSSPropertyExtra_variable ||
|
||||
property == nsCSSPropertyID::eCSSProperty_UNKNOWN;
|
||||
};
|
||||
|
||||
let mut transitions_to_keep = LonghandIdSet::new();
|
||||
|
||||
for i in 0..transitions_count {
|
||||
let property = after_change_box_style.transition_nscsspropertyid_at(i);
|
||||
let combined_duration = after_change_box_style.transition_combined_duration_at(i);
|
||||
|
||||
// We don't need to update transition for none/custom properties.
|
||||
if is_none_or_custom_property(property) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let transition_property: TransitionProperty = property.into();
|
||||
|
||||
let mut property_check_helper = |property: LonghandId| -> bool {
|
||||
let property = property.to_physical(after_change_style.writing_mode);
|
||||
transitions_to_keep.insert(property);
|
||||
self.needs_transitions_update_per_property(
|
||||
property,
|
||||
combined_duration,
|
||||
for transition_property in after_change_style.transition_properties() {
|
||||
let physical_longhand = transition_property
|
||||
.longhand_id
|
||||
.to_physical(after_change_style.writing_mode);
|
||||
transitions_to_keep.insert(physical_longhand);
|
||||
if self.needs_transitions_update_per_property(
|
||||
physical_longhand,
|
||||
after_change_box_style.transition_combined_duration_at(transition_property.index),
|
||||
before_change_style,
|
||||
after_change_style,
|
||||
&existing_transitions,
|
||||
)
|
||||
};
|
||||
|
||||
match transition_property {
|
||||
TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => {},
|
||||
TransitionProperty::Shorthand(ref shorthand) => {
|
||||
if shorthand.longhands().any(property_check_helper) {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
TransitionProperty::Longhand(longhand_id) => {
|
||||
if property_check_helper(longhand_id) {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have to cancel the running transition because this is not
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#[cfg(feature = "gecko")] use crate::gecko_bindings::structs::nsCSSPropertyID;
|
||||
use itertools::{EitherOrBoth, Itertools};
|
||||
use crate::properties::{CSSWideKeyword, PropertyDeclaration};
|
||||
use crate::properties::{CSSWideKeyword, PropertyDeclaration, NonCustomPropertyIterator};
|
||||
use crate::properties::longhands;
|
||||
use crate::properties::longhands::visibility::computed_value::T as Visibility;
|
||||
use crate::properties::LonghandId;
|
||||
|
@ -883,3 +883,66 @@ impl ToAnimatedZero for AnimatedFilter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over all the properties that transition on a given style.
|
||||
pub struct TransitionPropertyIterator<'a> {
|
||||
style: &'a ComputedValues,
|
||||
index_range: core::ops::Range<usize>,
|
||||
longhand_iterator: Option<NonCustomPropertyIterator<LonghandId>>,
|
||||
}
|
||||
|
||||
impl<'a> TransitionPropertyIterator<'a> {
|
||||
/// Create a `TransitionPropertyIterator` for the given style.
|
||||
pub fn from_style(style: &'a ComputedValues) -> Self {
|
||||
Self {
|
||||
style,
|
||||
index_range: 0..style.get_box().transition_property_count(),
|
||||
longhand_iterator: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A single iteration of the TransitionPropertyIterator.
|
||||
pub struct TransitionPropertyIteration {
|
||||
/// The id of the longhand for this property.
|
||||
pub longhand_id: LonghandId,
|
||||
|
||||
/// The index of this property in the list of transition properties for this
|
||||
/// iterator's style.
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for TransitionPropertyIterator<'a> {
|
||||
type Item = TransitionPropertyIteration;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
use crate::values::computed::TransitionProperty;
|
||||
loop {
|
||||
if let Some(ref mut longhand_iterator) = self.longhand_iterator {
|
||||
if let Some(longhand_id) = longhand_iterator.next() {
|
||||
return Some(TransitionPropertyIteration {
|
||||
longhand_id,
|
||||
index: self.index_range.start,
|
||||
});
|
||||
}
|
||||
self.longhand_iterator = None;
|
||||
}
|
||||
|
||||
let index = self.index_range.next()?;
|
||||
match self.style.get_box().transition_property_at(index) {
|
||||
TransitionProperty::Longhand(longhand_id) => {
|
||||
return Some(TransitionPropertyIteration {
|
||||
longhand_id,
|
||||
index,
|
||||
})
|
||||
}
|
||||
// In the other cases, we set up our state so that we are ready to
|
||||
// compute the next value of the iterator and then loop (equivalent
|
||||
// to calling self.next()).
|
||||
TransitionProperty::Shorthand(ref shorthand_id) =>
|
||||
self.longhand_iterator = Some(shorthand_id.longhands()),
|
||||
TransitionProperty::Custom(..) | TransitionProperty::Unsupported(..) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3020,6 +3020,13 @@ impl ComputedValues {
|
|||
% endfor
|
||||
set
|
||||
}
|
||||
|
||||
/// Create a `TransitionPropertyIterator` for this styles transition properties.
|
||||
pub fn transition_properties<'a>(
|
||||
&'a self
|
||||
) -> animated_properties::TransitionPropertyIterator<'a> {
|
||||
animated_properties::TransitionPropertyIterator::from_style(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
|
|
Загрузка…
Ссылка в новой задаче