diff --git a/components/style/data.rs b/components/style/data.rs index 41a618dd32e..a0d694b9518 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -6,7 +6,7 @@ use context::SharedStyleContext; use dom::TElement; -use properties::{ComputedValues, PropertyDeclarationBlock}; +use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; use properties::longhands::display::computed_value as display; use restyle_hints::{HintComputationContext, RestyleReplacements, RestyleHint}; use rule_tree::StrongRuleNode; @@ -571,4 +571,16 @@ impl ElementData { None => None, } } + + /// Returns AnimationRules that has processed during animation-only restyles. + pub fn get_animation_rules(&self) -> AnimationRules { + if cfg!(feature = "servo") { + return AnimationRules(None, None) + } + + match self.get_styles() { + Some(s) => s.primary.rules.get_animation_rules(), + None => AnimationRules(None, None), + } + } } diff --git a/components/style/dom.rs b/components/style/dom.rs index de9d68396c7..44d1b0c3147 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -13,7 +13,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use data::ElementData; use element_state::ElementState; use font_metrics::FontMetricsProvider; -use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; +use properties::{ComputedValues, PropertyDeclarationBlock}; #[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue; #[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty; use rule_tree::CascadeLevel; @@ -334,11 +334,6 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + None } - /// Get this element's animation rules. - fn get_animation_rules(&self) -> AnimationRules { - AnimationRules(None, None) - } - /// Get this element's animation rule by the cascade level. fn get_animation_rule_by_cascade(&self, _cascade_level: CascadeLevel) diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 011e0bff078..38f2af26249 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -57,7 +57,7 @@ use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS; use gecko_bindings::sugar::ownership::HasArcFFI; use logical_geometry::WritingMode; use media_queries::Device; -use properties::{AnimationRules, ComputedValues, parse_style_attribute}; +use properties::{ComputedValues, parse_style_attribute}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use properties::animated_properties::{AnimationValue, AnimationValueMap, TransitionProperty}; use properties::style_structs::Font; @@ -613,11 +613,6 @@ impl<'le> TElement for GeckoElement<'le> { declarations.map(|s| s.as_arc_opt()).unwrap_or(None) } - fn get_animation_rules(&self) -> AnimationRules { - AnimationRules(self.get_animation_rule(), - self.get_transition_rule()) - } - fn get_animation_rule_by_cascade(&self, cascade_level: ServoCascadeLevel) -> Option>> { match cascade_level { diff --git a/components/style/matching.rs b/components/style/matching.rs index 578ecb4f2d5..5dd820f1666 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -254,7 +254,7 @@ trait PrivateMatchMethods: TElement { // We could make that a bit better if the complexity cost is not too // big, but given further restyles are posted directly to // pseudo-elements, it doesn't seem worth the effort at a glance. - if pseudo.is_eager() && self.get_animation_rules().is_empty() { + if pseudo.is_eager() && primary_style.rules.get_animation_rules().is_empty() { let parent = self.parent_element().unwrap(); let parent_data = parent.borrow_data().unwrap(); let pseudo_style = @@ -692,38 +692,39 @@ pub trait MatchMethods : TElement { let pseudo_style = parent_data.styles().pseudos.get(&pseudo).unwrap(); let mut rules = pseudo_style.rules.clone(); - let animation_rules = self.get_animation_rules(); + { + let animation_rules = data.get_animation_rules(); - // Handle animations here. - if let Some(animation_rule) = animation_rules.0 { - let animation_rule_node = - context.shared.stylist.rule_tree() - .update_rule_at_level(CascadeLevel::Animations, - Some(&animation_rule), - &mut rules, - &context.shared.guards); - if let Some(node) = animation_rule_node { - rules = node; + // Handle animations here. + if let Some(animation_rule) = animation_rules.0 { + let animation_rule_node = + context.shared.stylist.rule_tree() + .update_rule_at_level(CascadeLevel::Animations, + Some(&animation_rule), + &mut rules, + &context.shared.guards); + if let Some(node) = animation_rule_node { + rules = node; + } + } + + if let Some(animation_rule) = animation_rules.1 { + let animation_rule_node = + context.shared.stylist.rule_tree() + .update_rule_at_level(CascadeLevel::Transitions, + Some(&animation_rule), + &mut rules, + &context.shared.guards); + if let Some(node) = animation_rule_node { + rules = node; + } } } - - if let Some(animation_rule) = animation_rules.1 { - let animation_rule_node = - context.shared.stylist.rule_tree() - .update_rule_at_level(CascadeLevel::Transitions, - Some(&animation_rule), - &mut rules, - &context.shared.guards); - if let Some(node) = animation_rule_node { - rules = node; - } - } - let important_rules_changed = self.has_animations() && data.has_styles() && data.important_rules_are_different(&rules, - &context.shared.guards); + &context.shared.guards); return RulesMatchedResult { rule_nodes_changed: data.set_primary_rules(rules), @@ -738,10 +739,9 @@ pub trait MatchMethods : TElement { let style_attribute = self.style_attribute(); { let smil_override = data.get_smil_override(); - let animation_rules = self.get_animation_rules(); + let animation_rules = data.get_animation_rules(); let bloom = context.thread_local.bloom_filter.filter(); - let map = &mut context.thread_local.selector_flags; let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| { self.apply_selector_flags(map, element, flags); diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index c826d56a6b3..e7c1b73d6c8 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -23,10 +23,10 @@ use super::*; /// /// The first one is for Animation cascade level, and the second one is for /// Transition cascade level. -pub struct AnimationRules(pub Option>>, - pub Option>>); +pub struct AnimationRules<'a>(pub Option<&'a Arc>>, + pub Option<&'a Arc>>); -impl AnimationRules { +impl<'a> AnimationRules<'a> { /// Returns whether these animation rules represents an actual rule or not. pub fn is_empty(&self) -> bool { self.0.is_none() && self.1.is_none() diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index d5c44329b72..c7d7e9815b7 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -8,7 +8,7 @@ #[cfg(feature = "servo")] use heapsize::HeapSizeOf; -use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock}; +use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock}; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use smallvec::SmallVec; use std::io::{self, Write}; @@ -1152,6 +1152,32 @@ impl StrongRuleNode { .find(|node| node.cascade_level() == CascadeLevel::SMILOverride) .map(|node| node.get_animation_style()) } + + /// Returns AnimationRules that has processed during animation-only restyles. + pub fn get_animation_rules(&self) -> AnimationRules { + if cfg!(feature = "servo") { + return AnimationRules(None, None); + } + + let mut animation = None; + let mut transition = None; + + for node in self.self_and_ancestors() + .take_while(|node| node.cascade_level() >= CascadeLevel::Animations) { + match node.cascade_level() { + CascadeLevel::Animations => { + debug_assert!(animation.is_none()); + animation = Some(node.get_animation_style()) + }, + CascadeLevel::Transitions => { + debug_assert!(transition.is_none()); + transition = Some(node.get_animation_style()) + }, + _ => {}, + } + } + AnimationRules(animation, transition) + } } /// An iterator over a rule node and its ancestors. diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 315e0b5207c..6093aa50820 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -943,7 +943,7 @@ impl Stylist { if let Some(anim) = animation_rules.0 { Push::push( applicable_declarations, - ApplicableDeclarationBlock::from_declarations(anim, + ApplicableDeclarationBlock::from_declarations(anim.clone(), CascadeLevel::Animations)); } debug!("animation: {:?}", context.relations); @@ -961,7 +961,8 @@ impl Stylist { if let Some(anim) = animation_rules.1 { Push::push( applicable_declarations, - ApplicableDeclarationBlock::from_declarations(anim, CascadeLevel::Transitions)); + ApplicableDeclarationBlock::from_declarations(anim.clone(), + CascadeLevel::Transitions)); } debug!("transition: {:?}", context.relations); debug!("push_applicable_declarations: shareable: {:?}", context.relations);