Bug 1646811 - servo: Add DocumentAnimationSet and AnimationSetKey.

This will be used in order to hold animations for pseudo elements in the
DocumentAnimationSet. Also no longer store the OpaqueNode in the
animation and transition data structures. This is already part of the
DocumentAnimationSet key.

Depends on D80241

Differential Revision: https://phabricator.services.mozilla.com/D80242
This commit is contained in:
Martin Robinson 2020-06-18 18:14:02 +00:00
parent 1a949f1378
commit d406afe4e6
3 changed files with 83 additions and 27 deletions

View File

@ -19,6 +19,7 @@ use crate::properties::{
PropertyDeclarationId,
};
use crate::rule_tree::CascadeLevel;
use crate::shared_lock::{Locked, SharedRwLock};
use crate::style_resolver::StyleResolverForElement;
use crate::stylesheets::keyframes_rule::{KeyframesAnimation, KeyframesStep, KeyframesStepValue};
use crate::values::animated::{Animate, Procedure};
@ -26,6 +27,8 @@ use crate::values::computed::{Time, TimingFunction};
use crate::values::generics::box_::AnimationIterationCount;
use crate::values::generics::easing::{StepPosition, TimingFunction as GenericTimingFunction};
use crate::Atom;
use fxhash::FxHashMap;
use parking_lot::RwLock;
use servo_arc::Arc;
use std::fmt;
@ -393,9 +396,6 @@ impl ComputedKeyframe {
/// A CSS Animation
#[derive(Clone, MallocSizeOf)]
pub struct Animation {
/// The node associated with this animation.
pub node: OpaqueNode,
/// The name of this animation as defined by the style.
pub name: Atom,
@ -736,9 +736,6 @@ impl fmt::Debug for Animation {
/// A CSS Transition
#[derive(Clone, Debug, MallocSizeOf)]
pub struct Transition {
/// The node associated with this animation.
pub node: OpaqueNode,
/// The start time of this transition, which is the current value of the animation
/// timeline when this transition was created plus any animation delay.
pub start_time: f64,
@ -891,7 +888,7 @@ impl ElementAnimationSet {
}
pub(crate) fn apply_active_animations(
&mut self,
&self,
context: &SharedStyleContext,
style: &mut Arc<ComputedValues>,
) {
@ -987,7 +984,6 @@ impl ElementAnimationSet {
&mut self,
might_need_transitions_update: bool,
context: &SharedStyleContext,
opaque_node: OpaqueNode,
old_style: Option<&Arc<ComputedValues>>,
after_change_style: &Arc<ComputedValues>,
) {
@ -1015,7 +1011,6 @@ impl ElementAnimationSet {
let transitioning_properties = start_transitions_if_applicable(
context,
opaque_node,
&before_change_style,
after_change_style,
self,
@ -1037,7 +1032,6 @@ impl ElementAnimationSet {
fn start_transition_if_applicable(
&mut self,
context: &SharedStyleContext,
opaque_node: OpaqueNode,
longhand_id: LonghandId,
index: usize,
old_style: &ComputedValues,
@ -1079,7 +1073,6 @@ impl ElementAnimationSet {
// it if we are replacing a reversed transition.
let reversing_adjusted_start_value = property_animation.from.clone();
let mut new_transition = Transition {
node: opaque_node,
start_time: now + delay,
delay,
property_animation,
@ -1143,11 +1136,78 @@ impl ElementAnimationSet {
}
}
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
/// A key that is used to identify nodes in the `DocumentAnimationSet`.
pub struct AnimationSetKey(pub OpaqueNode);
#[derive(Clone, Debug, Default, MallocSizeOf)]
/// A set of animations for a document.
pub struct DocumentAnimationSet {
/// The `ElementAnimationSet`s that this set contains.
#[ignore_malloc_size_of = "Arc is hard"]
pub sets: Arc<RwLock<FxHashMap<AnimationSetKey, ElementAnimationSet>>>,
}
impl DocumentAnimationSet {
/// Return whether or not the provided node has active CSS animations.
pub fn has_active_animations(&self, key: &AnimationSetKey) -> bool {
self.sets
.read()
.get(key)
.map(|set| set.has_active_animation())
.unwrap_or(false)
}
/// Return whether or not the provided node has active CSS transitions.
pub fn has_active_transitions(&self, key: &AnimationSetKey) -> bool {
self.sets
.read()
.get(key)
.map(|set| set.has_active_transition())
.unwrap_or(false)
}
/// Return a locked PropertyDeclarationBlock with animation values for the given
/// key and time.
pub fn get_animation_declarations(
&self,
key: &AnimationSetKey,
time: f64,
shared_lock: &SharedRwLock,
) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
self.sets
.read()
.get(key)
.and_then(|set| set.get_value_map_for_active_animations(time))
.map(|map| {
let block = PropertyDeclarationBlock::from_animation_value_map(&map);
Arc::new(shared_lock.wrap(block))
})
}
/// Return a locked PropertyDeclarationBlock with transition values for the given
/// key and time.
pub fn get_transition_declarations(
&self,
key: &AnimationSetKey,
time: f64,
shared_lock: &SharedRwLock,
) -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
self.sets
.read()
.get(key)
.and_then(|set| set.get_value_map_for_active_transitions(time))
.map(|map| {
let block = PropertyDeclarationBlock::from_animation_value_map(&map);
Arc::new(shared_lock.wrap(block))
})
}
}
/// Kick off any new transitions for this node and return all of the properties that are
/// transitioning. This is at the end of calculating style for a single node.
pub fn start_transitions_if_applicable(
context: &SharedStyleContext,
opaque_node: OpaqueNode,
old_style: &ComputedValues,
new_style: &Arc<ComputedValues>,
animation_state: &mut ElementAnimationSet,
@ -1162,7 +1222,6 @@ pub fn start_transitions_if_applicable(
properties_that_transition.insert(physical_property);
animation_state.start_transition_if_applicable(
context,
opaque_node,
physical_property,
transition.index,
old_style,
@ -1245,7 +1304,6 @@ pub fn maybe_start_animations<E>(
);
let new_animation = Animation {
node: element.as_node().opaque(),
name: name.clone(),
properties_changed: keyframe_animation.properties_changed,
computed_steps,

View File

@ -5,11 +5,9 @@
//! The context within which style is calculated.
#[cfg(feature = "servo")]
use crate::animation::ElementAnimationSet;
use crate::animation::DocumentAnimationSet;
use crate::bloom::StyleBloom;
use crate::data::{EagerPseudoStyles, ElementData};
#[cfg(feature = "servo")]
use crate::dom::OpaqueNode;
use crate::dom::{SendElement, TElement};
use crate::font_metrics::FontMetricsProvider;
#[cfg(feature = "gecko")]
@ -31,10 +29,9 @@ use app_units::Au;
use euclid::default::Size2D;
use euclid::Scale;
use fxhash::FxHashMap;
#[cfg(feature = "servo")]
use parking_lot::RwLock;
use selectors::matching::ElementSelectorFlags;
use selectors::NthIndexCache;
#[cfg(feature = "gecko")]
use servo_arc::Arc;
#[cfg(feature = "servo")]
use servo_atoms::Atom;
@ -167,7 +164,7 @@ pub struct SharedStyleContext<'a> {
/// The state of all animations for our styled elements.
#[cfg(feature = "servo")]
pub animation_states: Arc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
pub animations: DocumentAnimationSet,
/// Paint worklets
#[cfg(feature = "servo")]

View File

@ -527,7 +527,7 @@ trait PrivateMatchMethods: TElement {
old_values: &mut Option<Arc<ComputedValues>>,
new_values: &mut Arc<ComputedValues>,
) -> bool {
use crate::animation::AnimationState;
use crate::animation::{AnimationSetKey, AnimationState};
// We need to call this before accessing the `ElementAnimationSet` from the
// map because this call will do a RwLock::read().
@ -544,12 +544,13 @@ trait PrivateMatchMethods: TElement {
after_change_style = self.after_change_style(context, new_values);
}
let this_opaque = self.as_node().opaque();
let key = AnimationSetKey(self.as_node().opaque());
let shared_context = context.shared;
let mut animation_set = shared_context
.animation_states
.animations
.sets
.write()
.remove(&this_opaque)
.remove(&key)
.unwrap_or_default();
// Starting animations is expensive, because we have to recalculate the style
@ -574,7 +575,6 @@ trait PrivateMatchMethods: TElement {
animation_set.update_transitions_for_new_style(
might_need_transitions_update,
&shared_context,
this_opaque,
old_values.as_ref(),
after_change_style.as_ref().unwrap_or(new_values),
);
@ -593,9 +593,10 @@ trait PrivateMatchMethods: TElement {
if !animation_set.is_empty() {
animation_set.dirty = false;
shared_context
.animation_states
.animations
.sets
.write()
.insert(this_opaque, animation_set);
.insert(key, animation_set);
}
changed_animations