Skip to content

Commit

Permalink
Bug 1846516 - [css-properties-values-api] Use PropertyDeclarationId/P…
Browse files Browse the repository at this point in the history
…ropertyDeclarationIdSet for animated properties. r=firefox-style-system-reviewers,emilio

This will make possible to animate custom properties. For now, the
animation code keeps only dealing with PropertyDeclarationId::Longhand,
so behavior is unchanged.

Co-authored-by: Frederic Wang <[email protected]>

Depends on D195972

Differential Revision: https://phabricator.services.mozilla.com/D190816
  • Loading branch information
zrhoffman committed Dec 18, 2023
1 parent ebaf393 commit 0ec875a
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 122 deletions.
56 changes: 30 additions & 26 deletions servo/components/style/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::properties::longhands::animation_fill_mode::computed_value::single_va
use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState;
use crate::properties::AnimationDeclarations;
use crate::properties::{
ComputedValues, Importance, LonghandId, LonghandIdSet, PropertyDeclarationBlock,
PropertyDeclarationId,
ComputedValues, Importance, LonghandId, PropertyDeclarationBlock, PropertyDeclarationId,
PropertyDeclarationIdSet,
};
use crate::rule_tree::CascadeLevel;
use crate::selector_parser::PseudoElement;
Expand Down Expand Up @@ -51,22 +51,22 @@ pub struct PropertyAnimation {

impl PropertyAnimation {
/// Returns the given property longhand id.
pub fn property_id(&self) -> LonghandId {
pub fn property_id(&self) -> PropertyDeclarationId {
debug_assert_eq!(self.from.id(), self.to.id());
self.from.id()
}

fn from_longhand(
longhand: LonghandId,
fn from_property_declaration(
property_declaration: &PropertyDeclarationId,
timing_function: TimingFunction,
duration: Time,
old_style: &ComputedValues,
new_style: &ComputedValues,
) -> Option<PropertyAnimation> {
// FIXME(emilio): Handle the case where old_style and new_style's writing mode differ.
let longhand = longhand.to_physical(new_style.writing_mode);
let from = AnimationValue::from_computed_values(longhand, old_style)?;
let to = AnimationValue::from_computed_values(longhand, new_style)?;
let property_declaration = property_declaration.to_physical(new_style.writing_mode);
let from = AnimationValue::from_computed_values(property_declaration, old_style)?;
let to = AnimationValue::from_computed_values(property_declaration, new_style)?;
let duration = duration.seconds() as f64;

if from == to || duration == 0.0 {
Expand Down Expand Up @@ -294,7 +294,7 @@ impl ComputedKeyframe {
where
E: TElement,
{
let mut animating_properties = LonghandIdSet::new();
let mut animating_properties = PropertyDeclarationIdSet::default();
for property in animation.properties_changed.iter() {
debug_assert!(property.is_animatable());
animating_properties.insert(property.to_physical(base_style.writing_mode));
Expand All @@ -314,7 +314,7 @@ impl ComputedKeyframe {
let mut computed_steps: Vec<Self> = Vec::with_capacity(intermediate_steps.len());
for (step_index, step) in intermediate_steps.into_iter().enumerate() {
let start_percentage = step.start_percentage;
let properties_changed_in_step = step.declarations.longhands().clone();
let properties_changed_in_step = step.declarations.property_ids().clone();
let step_timing_function = step.timing_function.clone();
let step_style = step.resolve_style(element, context, base_style, resolver);
let timing_function =
Expand All @@ -340,9 +340,9 @@ impl ComputedKeyframe {
animating_properties
.iter()
.zip(default_values.iter())
.map(|(longhand, default_value)| {
if properties_changed_in_step.contains(longhand) {
AnimationValue::from_computed_values(longhand, &step_style)
.map(|(property_declaration, default_value)| {
if properties_changed_in_step.contains(property_declaration) {
AnimationValue::from_computed_values(property_declaration, &step_style)
.unwrap_or_else(|| default_value.clone())
} else {
default_value.clone()
Expand All @@ -368,7 +368,7 @@ pub struct Animation {
pub name: Atom,

/// The properties that change in this animation.
properties_changed: LonghandIdSet,
properties_changed: PropertyDeclarationIdSet,

/// The computed style for each keyframe of this animation.
computed_steps: Vec<ComputedKeyframe>,
Expand Down Expand Up @@ -669,7 +669,7 @@ impl Animation {
// in order to avoid doing more work.
let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| {
for value in keyframe.values.iter() {
map.insert(value.id(), value.clone());
map.insert(value.id().to_owned(), value.clone());
}
};
if total_progress <= 0.0 {
Expand Down Expand Up @@ -702,7 +702,7 @@ impl Animation {
};

if let Ok(value) = animation.calculate_value(progress_between_keyframes) {
map.insert(value.id(), value);
map.insert(value.id().to_owned(), value);
}
}
}
Expand Down Expand Up @@ -1024,7 +1024,7 @@ impl ElementAnimationSet {
fn start_transition_if_applicable(
&mut self,
context: &SharedStyleContext,
longhand_id: LonghandId,
property_declaration_id: &PropertyDeclarationId,
index: usize,
old_style: &ComputedValues,
new_style: &Arc<ComputedValues>,
Expand All @@ -1037,8 +1037,8 @@ impl ElementAnimationSet {

// Only start a new transition if the style actually changes between
// the old style and the new style.
let property_animation = match PropertyAnimation::from_longhand(
longhand_id,
let property_animation = match PropertyAnimation::from_property_declaration(
property_declaration_id,
timing_function,
duration,
old_style,
Expand Down Expand Up @@ -1078,7 +1078,9 @@ impl ElementAnimationSet {
.transitions
.iter_mut()
.filter(|transition| transition.state == AnimationState::Running)
.find(|transition| transition.property_animation.property_id() == longhand_id)
.find(|transition| {
transition.property_animation.property_id() == *property_declaration_id
})
{
// We always cancel any running transitions for the same property.
old_transition.state = AnimationState::Canceled;
Expand Down Expand Up @@ -1106,7 +1108,7 @@ impl ElementAnimationSet {
Some(value) => value,
None => continue,
};
map.insert(value.id(), value);
map.insert(value.id().to_owned(), value);
}

Some(map)
Expand Down Expand Up @@ -1268,18 +1270,20 @@ pub fn start_transitions_if_applicable(
old_style: &ComputedValues,
new_style: &Arc<ComputedValues>,
animation_state: &mut ElementAnimationSet,
) -> LonghandIdSet {
let mut properties_that_transition = LonghandIdSet::new();
) -> PropertyDeclarationIdSet {
let mut properties_that_transition = PropertyDeclarationIdSet::default();
for transition in new_style.transition_properties() {
let physical_property = transition.longhand_id.to_physical(new_style.writing_mode);
let physical_property = PropertyDeclarationId::Longhand(
transition.longhand_id.to_physical(new_style.writing_mode),
);
if properties_that_transition.contains(physical_property) {
continue;
}

properties_that_transition.insert(physical_property);
animation_state.start_transition_if_applicable(
context,
physical_property,
&physical_property,
transition.index,
old_style,
new_style,
Expand Down Expand Up @@ -1370,7 +1374,7 @@ pub fn maybe_start_animations<E>(

let mut new_animation = Animation {
name: name.clone(),
properties_changed: keyframe_animation.properties_changed,
properties_changed: keyframe_animation.properties_changed.clone(),
computed_steps,
started_at,
duration,
Expand Down
42 changes: 23 additions & 19 deletions servo/components/style/gecko/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,11 @@ use crate::gecko_bindings::structs::{nsINode as RawGeckoNode, Element as RawGeck
use crate::global_style_data::GLOBAL_STYLE_DATA;
use crate::invalidation::element::restyle_hints::RestyleHint;
use crate::media_queries::Device;
use crate::properties::animated_properties::{AnimationValue, AnimationValueMap};
use crate::properties::{ComputedValues, LonghandId};
use crate::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use crate::properties::{
animated_properties::{AnimationValue, AnimationValueMap},
ComputedValues, Importance, OwnedPropertyDeclarationId, PropertyDeclaration,
PropertyDeclarationBlock, PropertyDeclarationId, PropertyDeclarationIdSet,
};
use crate::rule_tree::CascadeLevel as ServoCascadeLevel;
use crate::selector_parser::{AttrValue, Lang};
use crate::shared_lock::{Locked, SharedRwLock};
Expand Down Expand Up @@ -812,7 +814,7 @@ impl<'le> GeckoElement<'le> {
host.is_svg_element() && host.local_name() == &**local_name!("use")
}

fn css_transitions_info(&self) -> FxHashMap<LonghandId, Arc<AnimationValue>> {
fn css_transitions_info(&self) -> FxHashMap<OwnedPropertyDeclarationId, Arc<AnimationValue>> {
use crate::gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
use crate::gecko_bindings::bindings::Gecko_ElementTransitions_Length;

Expand All @@ -824,37 +826,39 @@ impl<'le> GeckoElement<'le> {
unsafe { Arc::from_raw_addrefed(Gecko_ElementTransitions_EndValueAt(self.0, i)) };
let property = end_value.id();
debug_assert!(!property.is_logical());
map.insert(property, end_value);
map.insert(property.to_owned(), end_value);
}
map
}

fn needs_transitions_update_per_property(
&self,
longhand_id: LonghandId,
property_declaration_id: PropertyDeclarationId,
combined_duration_seconds: f32,
before_change_style: &ComputedValues,
after_change_style: &ComputedValues,
existing_transitions: &FxHashMap<LonghandId, Arc<AnimationValue>>,
existing_transitions: &FxHashMap<OwnedPropertyDeclarationId, Arc<AnimationValue>>,
) -> bool {
use crate::values::animated::{Animate, Procedure};
debug_assert!(!longhand_id.is_logical());
debug_assert!(!property_declaration_id.is_logical());

// If there is an existing transition, update only if the end value
// differs.
//
// If the end value has not changed, we should leave the currently
// running transition as-is since we don't want to interrupt its timing
// function.
if let Some(ref existing) = existing_transitions.get(&longhand_id) {
if let Some(ref existing) = existing_transitions.get(&property_declaration_id.to_owned()) {
let after_value =
AnimationValue::from_computed_values(longhand_id, after_change_style).unwrap();
AnimationValue::from_computed_values(property_declaration_id, after_change_style)
.unwrap();

return ***existing != after_value;
}

let from = AnimationValue::from_computed_values(longhand_id, before_change_style);
let to = AnimationValue::from_computed_values(longhand_id, after_change_style);
let from =
AnimationValue::from_computed_values(property_declaration_id, before_change_style);
let to = AnimationValue::from_computed_values(property_declaration_id, after_change_style);

debug_assert_eq!(to.is_some(), from.is_some());

Expand Down Expand Up @@ -1517,8 +1521,6 @@ impl<'le> TElement for GeckoElement<'le> {
before_change_style: &ComputedValues,
after_change_style: &ComputedValues,
) -> bool {
use crate::properties::LonghandIdSet;

let after_change_ui_style = after_change_style.get_ui();
let existing_transitions = self.css_transitions_info();

Expand All @@ -1527,11 +1529,13 @@ impl<'le> TElement for GeckoElement<'le> {
return !existing_transitions.is_empty();
}

let mut transitions_to_keep = LonghandIdSet::new();
let mut transitions_to_keep = PropertyDeclarationIdSet::default();
for transition_property in after_change_style.transition_properties() {
let physical_longhand = transition_property
.longhand_id
.to_physical(after_change_style.writing_mode);
let physical_longhand = PropertyDeclarationId::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,
Expand All @@ -1550,7 +1554,7 @@ impl<'le> TElement for GeckoElement<'le> {
// a matching transition-property value.
existing_transitions
.keys()
.any(|property| !transitions_to_keep.contains(*property))
.any(|property| !transitions_to_keep.contains(property.as_borrowed()))
}

/// Whether there is an ElementData container.
Expand Down
Loading

0 comments on commit 0ec875a

Please sign in to comment.