aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/layout_2020/flow/root.rs5
-rw-r--r--components/layout_thread/dom_wrapper.rs55
-rw-r--r--components/layout_thread/lib.rs24
-rw-r--r--components/layout_thread_2020/dom_wrapper.rs55
-rw-r--r--components/layout_thread_2020/lib.rs20
-rw-r--r--components/script/animations.rs67
-rw-r--r--components/script/dom/bindings/trace.rs4
-rw-r--r--components/script_layout_interface/message.rs6
-rw-r--r--components/style/animation.rs86
-rw-r--r--components/style/context.rs9
-rw-r--r--components/style/matching.rs15
11 files changed, 184 insertions, 162 deletions
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index 46b7cf8438c..55c325a3cd0 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -35,6 +35,7 @@ use gfx_traits::print_tree::PrintTree;
use script_layout_interface::wrapper_traits::LayoutNode;
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use servo_arc::Arc;
+use style::animation::AnimationSetKey;
use style::dom::OpaqueNode;
use style::properties::ComputedValues;
use style::values::computed::Length;
@@ -446,10 +447,10 @@ impl FragmentTree {
})
}
- pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<OpaqueNode>) {
+ pub fn remove_nodes_in_fragment_tree_from_set(&self, set: &mut FxHashSet<AnimationSetKey>) {
self.find(|fragment, _| {
if let Some(tag) = fragment.tag().as_ref() {
- set.remove(&tag.node());
+ set.remove(&AnimationSetKey(tag.node()));
}
None::<()>
});
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs
index b477a653188..3d3f50317a9 100644
--- a/components/layout_thread/dom_wrapper.rs
+++ b/components/layout_thread/dom_wrapper.rs
@@ -72,6 +72,7 @@ use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::sync::atomic::Ordering;
use std::sync::Arc as StdArc;
+use style::animation::AnimationSetKey;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::attr::AttrValue;
use style::context::SharedStyleContext;
@@ -474,20 +475,11 @@ impl<'le> TElement for ServoLayoutElement<'le> {
) -> Option<Arc<StyleLocked<PropertyDeclarationBlock>>> {
let node = self.as_node();
let document = node.owner_doc();
- context
- .animation_states
- .read()
- .get(&node.opaque())
- .and_then(|set| {
- set.get_value_map_for_active_animations(context.current_time_for_animations)
- })
- .map(|map| {
- Arc::new(
- document
- .style_shared_lock()
- .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)),
- )
- })
+ context.animations.get_animation_declarations(
+ &AnimationSetKey(node.opaque()),
+ context.current_time_for_animations,
+ document.style_shared_lock(),
+ )
}
fn transition_rule(
@@ -496,20 +488,11 @@ impl<'le> TElement for ServoLayoutElement<'le> {
) -> Option<Arc<StyleLocked<PropertyDeclarationBlock>>> {
let node = self.as_node();
let document = node.owner_doc();
- context
- .animation_states
- .read()
- .get(&node.opaque())
- .and_then(|set| {
- set.get_value_map_for_active_transitions(context.current_time_for_animations)
- })
- .map(|map| {
- Arc::new(
- document
- .style_shared_lock()
- .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)),
- )
- })
+ context.animations.get_transition_declarations(
+ &AnimationSetKey(node.opaque()),
+ context.current_time_for_animations,
+ document.style_shared_lock(),
+ )
}
fn state(&self) -> ElementState {
@@ -634,21 +617,13 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
fn has_css_animations(&self, context: &SharedStyleContext) -> bool {
- context
- .animation_states
- .read()
- .get(&self.as_node().opaque())
- .map(|set| set.has_active_animation())
- .unwrap_or(false)
+ let key = AnimationSetKey(self.as_node().opaque());
+ context.animations.has_active_animations(&key)
}
fn has_css_transitions(&self, context: &SharedStyleContext) -> bool {
- context
- .animation_states
- .read()
- .get(&self.as_node().opaque())
- .map(|set| set.has_active_transition())
- .unwrap_or(false)
+ let key = AnimationSetKey(self.as_node().opaque());
+ context.animations.has_active_transitions(&key)
}
#[inline]
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 14dbfc0c80e..5930e85b08c 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -42,7 +42,7 @@ use layout::context::malloc_size_of_persistent_local_context;
use layout::context::LayoutContext;
use layout::context::RegisteredPainter;
use layout::context::RegisteredPainters;
-use layout::display_list::items::{OpaqueNode, WebRenderImageInfo};
+use layout::display_list::items::WebRenderImageInfo;
use layout::display_list::{IndexableText, ToLayout};
use layout::flow::{Flow, GetBaseFlow, ImmutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow_ref::FlowRef;
@@ -98,7 +98,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use std::time::Duration;
-use style::animation::ElementAnimationSet;
+use style::animation::{AnimationSetKey, DocumentAnimationSet, ElementAnimationSet};
use style::context::SharedStyleContext;
use style::context::{QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters};
use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TDocument, TElement, TNode};
@@ -604,7 +604,7 @@ impl LayoutThread {
snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin,
animation_timeline_value: f64,
- animation_states: ServoArc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
+ animations: &DocumentAnimationSet,
stylesheets_changed: bool,
) -> LayoutContext<'a> {
let traversal_flags = match stylesheets_changed {
@@ -620,7 +620,7 @@ impl LayoutThread {
options: GLOBAL_STYLE_DATA.options.clone(),
guards,
visited_styles_enabled: false,
- animation_states,
+ animations: animations.clone(),
registered_speculative_painters: &self.registered_painters,
current_time_for_animations: animation_timeline_value,
traversal_flags,
@@ -1402,7 +1402,7 @@ impl LayoutThread {
&map,
origin,
data.animation_timeline_value,
- data.animations.clone(),
+ &data.animations,
data.stylesheets_changed,
);
@@ -1643,24 +1643,26 @@ impl LayoutThread {
/// TODO(mrobinson): We should look into a way of doing this during flow tree construction.
/// This also doesn't yet handles nodes that have been reparented.
fn cancel_animations_for_nodes_not_in_flow_tree(
- animation_states: &mut FxHashMap<OpaqueNode, ElementAnimationSet>,
+ animations: &mut FxHashMap<AnimationSetKey, ElementAnimationSet>,
root_flow: &mut dyn Flow,
) {
// Assume all nodes have been removed until proven otherwise.
- let mut invalid_nodes: FxHashSet<OpaqueNode> = animation_states.keys().cloned().collect();
- fn traverse_flow(flow: &mut dyn Flow, invalid_nodes: &mut FxHashSet<OpaqueNode>) {
+ let mut invalid_nodes = animations.keys().cloned().collect();
+
+ fn traverse_flow(flow: &mut dyn Flow, invalid_nodes: &mut FxHashSet<AnimationSetKey>) {
flow.mutate_fragments(&mut |fragment| {
- invalid_nodes.remove(&fragment.node);
+ invalid_nodes.remove(&AnimationSetKey(fragment.node));
});
for kid in flow.mut_base().children.iter_mut() {
traverse_flow(kid, invalid_nodes)
}
}
+
traverse_flow(root_flow, &mut invalid_nodes);
// Cancel animations for any nodes that are no longer in the flow tree.
for node in &invalid_nodes {
- if let Some(state) = animation_states.get_mut(node) {
+ if let Some(state) = animations.get_mut(node) {
state.cancel_all_animations();
}
}
@@ -1676,7 +1678,7 @@ impl LayoutThread {
context: &mut LayoutContext,
) {
Self::cancel_animations_for_nodes_not_in_flow_tree(
- &mut *(context.style_context.animation_states.write()),
+ &mut *(context.style_context.animations.sets.write()),
FlowRef::deref_mut(root_flow),
);
diff --git a/components/layout_thread_2020/dom_wrapper.rs b/components/layout_thread_2020/dom_wrapper.rs
index 037b927539e..c8a7aa4dd05 100644
--- a/components/layout_thread_2020/dom_wrapper.rs
+++ b/components/layout_thread_2020/dom_wrapper.rs
@@ -72,6 +72,7 @@ use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::sync::atomic::Ordering;
use std::sync::Arc as StdArc;
+use style::animation::AnimationSetKey;
use style::applicable_declarations::ApplicableDeclarationBlock;
use style::attr::AttrValue;
use style::context::SharedStyleContext;
@@ -482,20 +483,11 @@ impl<'le> TElement for ServoLayoutElement<'le> {
) -> Option<Arc<StyleLocked<PropertyDeclarationBlock>>> {
let node = self.as_node();
let document = node.owner_doc();
- context
- .animation_states
- .read()
- .get(&node.opaque())
- .and_then(|set| {
- set.get_value_map_for_active_animations(context.current_time_for_animations)
- })
- .map(|map| {
- Arc::new(
- document
- .style_shared_lock()
- .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)),
- )
- })
+ context.animations.get_animation_declarations(
+ &AnimationSetKey(node.opaque()),
+ context.current_time_for_animations,
+ document.style_shared_lock(),
+ )
}
fn transition_rule(
@@ -504,20 +496,11 @@ impl<'le> TElement for ServoLayoutElement<'le> {
) -> Option<Arc<StyleLocked<PropertyDeclarationBlock>>> {
let node = self.as_node();
let document = node.owner_doc();
- context
- .animation_states
- .read()
- .get(&node.opaque())
- .and_then(|set| {
- set.get_value_map_for_active_transitions(context.current_time_for_animations)
- })
- .map(|map| {
- Arc::new(
- document
- .style_shared_lock()
- .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)),
- )
- })
+ context.animations.get_transition_declarations(
+ &AnimationSetKey(node.opaque()),
+ context.current_time_for_animations,
+ document.style_shared_lock(),
+ )
}
fn state(&self) -> ElementState {
@@ -642,21 +625,13 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
fn has_css_animations(&self, context: &SharedStyleContext) -> bool {
- context
- .animation_states
- .read()
- .get(&self.as_node().opaque())
- .map(|set| set.has_active_animation())
- .unwrap_or(false)
+ let key = AnimationSetKey(self.as_node().opaque());
+ context.animations.has_active_animations(&key)
}
fn has_css_transitions(&self, context: &SharedStyleContext) -> bool {
- context
- .animation_states
- .read()
- .get(&self.as_node().opaque())
- .map(|set| set.has_active_transition())
- .unwrap_or(false)
+ let key = AnimationSetKey(self.as_node().opaque());
+ context.animations.has_active_transitions(&key)
}
#[inline]
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 4ae69e6255a..4e04f6f0c4b 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -27,7 +27,7 @@ use crossbeam_channel::{Receiver, Sender};
use embedder_traits::resources::{self, Resource};
use euclid::{default::Size2D as UntypedSize2D, Point2D, Rect, Scale, Size2D};
use fnv::FnvHashMap;
-use fxhash::{FxHashMap, FxHashSet};
+use fxhash::FxHashMap;
use gfx::font_cache_thread::FontCacheThread;
use gfx::font_context;
use gfx_traits::{node_id_from_scroll_id, Epoch};
@@ -81,11 +81,10 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use std::time::Duration;
-use style::animation::ElementAnimationSet;
+use style::animation::DocumentAnimationSet;
use style::context::{
QuirksMode, RegisteredSpeculativePainter, RegisteredSpeculativePainters, SharedStyleContext,
};
-use style::dom::OpaqueNode;
use style::dom::{TDocument, TElement, TNode};
use style::driver;
use style::error_reporting::RustLogReporter;
@@ -568,7 +567,7 @@ impl LayoutThread {
snapshot_map: &'a SnapshotMap,
origin: ImmutableOrigin,
animation_timeline_value: f64,
- animation_states: ServoArc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
+ animations: &DocumentAnimationSet,
stylesheets_changed: bool,
) -> LayoutContext<'a> {
let traversal_flags = match stylesheets_changed {
@@ -584,7 +583,7 @@ impl LayoutThread {
options: GLOBAL_STYLE_DATA.options.clone(),
guards,
visited_styles_enabled: false,
- animation_states,
+ animations: animations.clone(),
registered_speculative_painters: &self.registered_painters,
current_time_for_animations: animation_timeline_value,
traversal_flags,
@@ -1065,7 +1064,7 @@ impl LayoutThread {
&map,
origin,
data.animation_timeline_value,
- data.animations.clone(),
+ &data.animations,
data.stylesheets_changed,
);
@@ -1292,7 +1291,7 @@ impl LayoutThread {
context: &mut LayoutContext,
) {
Self::cancel_animations_for_nodes_not_in_fragment_tree(
- &mut *(context.style_context.animation_states.write()),
+ &context.style_context.animations,
&fragment_tree,
);
@@ -1380,16 +1379,17 @@ impl LayoutThread {
/// TODO(mrobinson): We should look into a way of doing this during flow tree construction.
/// This also doesn't yet handles nodes that have been reparented.
fn cancel_animations_for_nodes_not_in_fragment_tree(
- animation_states: &mut FxHashMap<OpaqueNode, ElementAnimationSet>,
+ animations: &DocumentAnimationSet,
root: &FragmentTree,
) {
// Assume all nodes have been removed until proven otherwise.
- let mut invalid_nodes: FxHashSet<OpaqueNode> = animation_states.keys().cloned().collect();
+ let mut animations = animations.sets.write();
+ let mut invalid_nodes = animations.keys().cloned().collect();
root.remove_nodes_in_fragment_tree_from_set(&mut invalid_nodes);
// Cancel animations for any nodes that are no longer in the fragment tree.
for node in &invalid_nodes {
- if let Some(state) = animation_states.get_mut(node) {
+ if let Some(state) = animations.get_mut(node) {
state.cancel_all_animations();
}
}
diff --git a/components/script/animations.rs b/components/script/animations.rs
index d0bfcef6f79..0b35ba4ae1d 100644
--- a/components/script/animations.rs
+++ b/components/script/animations.rs
@@ -19,15 +19,14 @@ use crate::dom::event::Event;
use crate::dom::node::{from_untrusted_node_address, window_from_node, Node, NodeDamage};
use crate::dom::transitionevent::TransitionEvent;
use crate::dom::window::Window;
-use fxhash::FxHashMap;
+use fxhash::{FxHashMap, FxHashSet};
use libc::c_void;
use msg::constellation_msg::PipelineId;
-use parking_lot::RwLock;
use script_traits::{AnimationState as AnimationsPresentState, ScriptMsg, UntrustedNodeAddress};
-use servo_arc::Arc;
use std::cell::Cell;
use style::animation::{
- Animation, AnimationState, ElementAnimationSet, KeyframesIterationState, Transition,
+ Animation, AnimationSetKey, AnimationState, DocumentAnimationSet, ElementAnimationSet,
+ KeyframesIterationState, Transition,
};
use style::dom::OpaqueNode;
@@ -36,8 +35,7 @@ use style::dom::OpaqueNode;
#[unrooted_must_root_lint::must_root]
pub(crate) struct Animations {
/// The map of nodes to their animation states.
- #[ignore_malloc_size_of = "Arc is hard"]
- pub sets: Arc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
+ pub sets: DocumentAnimationSet,
/// Whether or not we have animations that are running.
have_running_animations: Cell<bool>,
@@ -60,30 +58,31 @@ impl Animations {
}
pub(crate) fn clear(&self) {
- self.sets.write().clear();
+ self.sets.sets.write().clear();
self.rooted_nodes.borrow_mut().clear();
self.pending_events.borrow_mut().clear();
}
pub(crate) fn mark_animating_nodes_as_dirty(&self) {
- let sets = self.sets.read();
+ let sets = self.sets.sets.read();
let rooted_nodes = self.rooted_nodes.borrow();
- for node in sets.keys().filter_map(|node| rooted_nodes.get(&node)) {
+ for node in sets.keys().filter_map(|key| rooted_nodes.get(&key.0)) {
node.dirty(NodeDamage::NodeStyleDamaged);
}
}
pub(crate) fn update_for_new_timeline_value(&self, window: &Window, now: f64) {
let pipeline_id = window.pipeline_id();
- let mut sets = self.sets.write();
+ let mut sets = self.sets.sets.write();
- for set in sets.values_mut() {
- self.start_pending_animations(set, now, pipeline_id);
+ for (key, set) in sets.iter_mut() {
+ self.start_pending_animations(key, set, now, pipeline_id);
// When necessary, iterate our running animations to the next iteration.
for animation in set.animations.iter_mut() {
if animation.iterate_if_necessary(now) {
self.add_animation_event(
+ key,
animation,
TransitionOrAnimationEventType::AnimationIteration,
now,
@@ -92,7 +91,7 @@ impl Animations {
}
}
- self.finish_running_animations(set, now, pipeline_id);
+ self.finish_running_animations(key, set, now, pipeline_id);
}
self.unroot_unused_nodes(&sets);
@@ -102,12 +101,12 @@ impl Animations {
/// that trigger events for any animations that changed state.
pub(crate) fn do_post_reflow_update(&self, window: &Window, now: f64) {
let pipeline_id = window.pipeline_id();
- let mut sets = self.sets.write();
+ let mut sets = self.sets.sets.write();
self.root_newly_animating_dom_nodes(&sets, window);
- for set in sets.values_mut() {
- self.handle_canceled_animations(set, now, pipeline_id);
- self.handle_new_animations(set, now, pipeline_id);
+ for (key, set) in sets.iter_mut() {
+ self.handle_canceled_animations(key, set, now, pipeline_id);
+ self.handle_new_animations(key, set, now, pipeline_id);
}
// Remove empty states from our collection of states in order to free
@@ -136,6 +135,7 @@ impl Animations {
pub(crate) fn running_animation_count(&self) -> usize {
self.sets
+ .sets
.read()
.values()
.map(|state| state.running_animation_and_transition_count())
@@ -146,6 +146,7 @@ impl Animations {
/// have left the delay phase.
fn start_pending_animations(
&self,
+ key: &AnimationSetKey,
set: &mut ElementAnimationSet,
now: f64,
pipeline_id: PipelineId,
@@ -154,6 +155,7 @@ impl Animations {
if animation.state == AnimationState::Pending && animation.started_at <= now {
animation.state = AnimationState::Running;
self.add_animation_event(
+ key,
animation,
TransitionOrAnimationEventType::AnimationStart,
now,
@@ -166,6 +168,7 @@ impl Animations {
if transition.state == AnimationState::Pending && transition.start_time <= now {
transition.state = AnimationState::Running;
self.add_transition_event(
+ key,
transition,
TransitionOrAnimationEventType::TransitionStart,
now,
@@ -179,6 +182,7 @@ impl Animations {
/// have ended.
fn finish_running_animations(
&self,
+ key: &AnimationSetKey,
set: &mut ElementAnimationSet,
now: f64,
pipeline_id: PipelineId,
@@ -187,6 +191,7 @@ impl Animations {
if animation.state == AnimationState::Running && animation.has_ended(now) {
animation.state = AnimationState::Finished;
self.add_animation_event(
+ key,
animation,
TransitionOrAnimationEventType::AnimationEnd,
now,
@@ -199,6 +204,7 @@ impl Animations {
if transition.state == AnimationState::Running && transition.has_ended(now) {
transition.state = AnimationState::Finished;
self.add_transition_event(
+ key,
transition,
TransitionOrAnimationEventType::TransitionEnd,
now,
@@ -213,6 +219,7 @@ impl Animations {
/// well.
fn handle_canceled_animations(
&self,
+ key: &AnimationSetKey,
set: &mut ElementAnimationSet,
now: f64,
pipeline_id: PipelineId,
@@ -220,6 +227,7 @@ impl Animations {
for transition in &set.transitions {
if transition.state == AnimationState::Canceled {
self.add_transition_event(
+ key,
transition,
TransitionOrAnimationEventType::TransitionCancel,
now,
@@ -231,6 +239,7 @@ impl Animations {
for animation in &set.animations {
if animation.state == AnimationState::Canceled {
self.add_animation_event(
+ key,
animation,
TransitionOrAnimationEventType::AnimationCancel,
now,
@@ -244,6 +253,7 @@ impl Animations {
fn handle_new_animations(
&self,
+ key: &AnimationSetKey,
set: &mut ElementAnimationSet,
now: f64,
pipeline_id: PipelineId,
@@ -255,6 +265,7 @@ impl Animations {
for transition in set.transitions.iter_mut() {
if transition.is_new {
self.add_transition_event(
+ key,
transition,
TransitionOrAnimationEventType::TransitionRun,
now,
@@ -270,13 +281,14 @@ impl Animations {
#[allow(unsafe_code)]
fn root_newly_animating_dom_nodes(
&self,
- sets: &FxHashMap<OpaqueNode, ElementAnimationSet>,
+ sets: &FxHashMap<AnimationSetKey, ElementAnimationSet>,
window: &Window,
) {
let js_runtime = window.get_js_runtime().as_ref().unwrap().rt();
let mut rooted_nodes = self.rooted_nodes.borrow_mut();
- for (opaque_node, set) in sets.iter() {
- if rooted_nodes.contains_key(opaque_node) {
+ for (key, set) in sets.iter() {
+ let opaque_node = key.0;
+ if rooted_nodes.contains_key(&opaque_node) {
continue;
}
@@ -286,7 +298,7 @@ impl Animations {
let address = UntrustedNodeAddress(opaque_node.0 as *const c_void);
unsafe {
rooted_nodes.insert(
- opaque_node.clone(),
+ opaque_node,
Dom::from_ref(&*from_untrusted_node_address(js_runtime, address)),
)
};
@@ -295,15 +307,17 @@ impl Animations {
}
// Unroot any nodes that we have rooted but are no longer tracking animations for.
- fn unroot_unused_nodes(&self, sets: &FxHashMap<OpaqueNode, ElementAnimationSet>) {
+ fn unroot_unused_nodes(&self, sets: &FxHashMap<AnimationSetKey, ElementAnimationSet>) {
let pending_events = self.pending_events.borrow();
- self.rooted_nodes.borrow_mut().retain(|key, _| {
- sets.contains_key(key) || pending_events.iter().any(|event| event.node == *key)
+ let nodes: FxHashSet<OpaqueNode> = sets.keys().map(|key| key.0).collect();
+ self.rooted_nodes.borrow_mut().retain(|node, _| {
+ nodes.contains(&node) || pending_events.iter().any(|event| event.node == *node)
});
}
fn add_transition_event(
&self,
+ key: &AnimationSetKey,
transition: &Transition,
event_type: TransitionOrAnimationEventType,
now: f64,
@@ -330,7 +344,7 @@ impl Animations {
.push(TransitionOrAnimationEvent {
pipeline_id,
event_type,
- node: transition.node.clone(),
+ node: key.0,
property_or_animation_name: transition
.property_animation
.property_id()
@@ -342,6 +356,7 @@ impl Animations {
fn add_animation_event(
&self,
+ key: &AnimationSetKey,
animation: &Animation,
event_type: TransitionOrAnimationEventType,
now: f64,
@@ -377,7 +392,7 @@ impl Animations {
.push(TransitionOrAnimationEvent {
pipeline_id,
event_type,
- node: animation.node.clone(),
+ node: key.0,
property_or_animation_name: animation.name.to_string(),
elapsed_time,
});
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 01cbde4bcfa..3c1a78802b4 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -141,7 +141,7 @@ use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::sync::{Arc, Mutex};
use std::thread::JoinHandle;
use std::time::{Instant, SystemTime};
-use style::animation::ElementAnimationSet;
+use style::animation::DocumentAnimationSet;
use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::author_styles::AuthorStyles;
use style::context::QuirksMode;
@@ -621,7 +621,7 @@ unsafe_no_jsmanaged_fields!(MediaSessionActionType);
unsafe_no_jsmanaged_fields!(MediaMetadata);
unsafe_no_jsmanaged_fields!(WebrenderIpcSender);
unsafe_no_jsmanaged_fields!(StreamConsumer);
-unsafe_no_jsmanaged_fields!(ElementAnimationSet);
+unsafe_no_jsmanaged_fields!(DocumentAnimationSet);
unsafe impl<'a> JSTraceable for &'a str {
#[inline]
diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs
index 724cd2b79e7..2d1ca34eef3 100644
--- a/components/script_layout_interface/message.rs
+++ b/components/script_layout_interface/message.rs
@@ -7,13 +7,11 @@ use crate::{PendingImage, TrustedNodeAddress};
use app_units::Au;
use crossbeam_channel::{Receiver, Sender};
use euclid::default::{Point2D, Rect};
-use fxhash::FxHashMap;
use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use metrics::PaintTimeMetrics;
use msg::constellation_msg::{BackgroundHangMonitorRegister, BrowsingContextId, PipelineId};
use net_traits::image_cache::ImageCache;
-use parking_lot::RwLock;
use profile_traits::mem::ReportsChan;
use script_traits::Painter;
use script_traits::{
@@ -25,7 +23,7 @@ use servo_atoms::Atom;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
-use style::animation::ElementAnimationSet;
+use style::animation::DocumentAnimationSet;
use style::context::QuirksMode;
use style::dom::OpaqueNode;
use style::invalidation::element::restyle_hints::RestyleHint;
@@ -215,7 +213,7 @@ pub struct ScriptReflow {
/// The current animation timeline value.
pub animation_timeline_value: f64,
/// The set of animations for this document.
- pub animations: ServoArc<RwLock<FxHashMap<OpaqueNode, ElementAnimationSet>>>,
+ pub animations: DocumentAnimationSet,
}
pub struct LayoutThreadInit {
diff --git a/components/style/animation.rs b/components/style/animation.rs
index 75efde37b67..ecb921a5e4a 100644
--- a/components/style/animation.rs
+++ b/components/style/animation.rs
@@ -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,
diff --git a/components/style/context.rs b/components/style/context.rs
index 832fcd10986..608e58ea032 100644
--- a/components/style/context.rs
+++ b/components/style/context.rs
@@ -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")]
diff --git a/components/style/matching.rs b/components/style/matching.rs
index 36369af5ec9..a8edf36829e 100644
--- a/components/style/matching.rs
+++ b/components/style/matching.rs
@@ -524,7 +524,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().
@@ -541,12 +541,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
@@ -571,7 +572,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),
);
@@ -590,9 +590,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