Use animation values that have been processed during animation-only restyle for normal restyle.

This commit is contained in:
Hiroyuki Ikezoe 2017-05-24 11:11:56 +09:00
parent 35e0e3aa11
commit 4935d972e5
7 changed files with 76 additions and 47 deletions

View file

@ -6,7 +6,7 @@
use context::SharedStyleContext; use context::SharedStyleContext;
use dom::TElement; use dom::TElement;
use properties::{ComputedValues, PropertyDeclarationBlock}; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock};
use properties::longhands::display::computed_value as display; use properties::longhands::display::computed_value as display;
use restyle_hints::{HintComputationContext, RestyleReplacements, RestyleHint}; use restyle_hints::{HintComputationContext, RestyleReplacements, RestyleHint};
use rule_tree::StrongRuleNode; use rule_tree::StrongRuleNode;
@ -571,4 +571,16 @@ impl ElementData {
None => None, 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),
}
}
} }

View file

@ -13,7 +13,7 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use data::ElementData; use data::ElementData;
use element_state::ElementState; use element_state::ElementState;
use font_metrics::FontMetricsProvider; 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::AnimationValue;
#[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty; #[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty;
use rule_tree::CascadeLevel; use rule_tree::CascadeLevel;
@ -334,11 +334,6 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone +
None 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. /// Get this element's animation rule by the cascade level.
fn get_animation_rule_by_cascade(&self, fn get_animation_rule_by_cascade(&self,
_cascade_level: CascadeLevel) _cascade_level: CascadeLevel)

View file

@ -57,7 +57,7 @@ use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
use gecko_bindings::sugar::ownership::HasArcFFI; use gecko_bindings::sugar::ownership::HasArcFFI;
use logical_geometry::WritingMode; use logical_geometry::WritingMode;
use media_queries::Device; use media_queries::Device;
use properties::{AnimationRules, ComputedValues, parse_style_attribute}; use properties::{ComputedValues, parse_style_attribute};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock}; use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use properties::animated_properties::{AnimationValue, AnimationValueMap, TransitionProperty}; use properties::animated_properties::{AnimationValue, AnimationValueMap, TransitionProperty};
use properties::style_structs::Font; 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) 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) fn get_animation_rule_by_cascade(&self, cascade_level: ServoCascadeLevel)
-> Option<Arc<Locked<PropertyDeclarationBlock>>> { -> Option<Arc<Locked<PropertyDeclarationBlock>>> {
match cascade_level { match cascade_level {

View file

@ -254,7 +254,7 @@ trait PrivateMatchMethods: TElement {
// We could make that a bit better if the complexity cost is not too // We could make that a bit better if the complexity cost is not too
// big, but given further restyles are posted directly to // big, but given further restyles are posted directly to
// pseudo-elements, it doesn't seem worth the effort at a glance. // 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 = self.parent_element().unwrap();
let parent_data = parent.borrow_data().unwrap(); let parent_data = parent.borrow_data().unwrap();
let pseudo_style = let pseudo_style =
@ -692,38 +692,39 @@ pub trait MatchMethods : TElement {
let pseudo_style = let pseudo_style =
parent_data.styles().pseudos.get(&pseudo).unwrap(); parent_data.styles().pseudos.get(&pseudo).unwrap();
let mut rules = pseudo_style.rules.clone(); let mut rules = pseudo_style.rules.clone();
let animation_rules = self.get_animation_rules(); {
let animation_rules = data.get_animation_rules();
// Handle animations here. // Handle animations here.
if let Some(animation_rule) = animation_rules.0 { if let Some(animation_rule) = animation_rules.0 {
let animation_rule_node = let animation_rule_node =
context.shared.stylist.rule_tree() context.shared.stylist.rule_tree()
.update_rule_at_level(CascadeLevel::Animations, .update_rule_at_level(CascadeLevel::Animations,
Some(&animation_rule), Some(&animation_rule),
&mut rules, &mut rules,
&context.shared.guards); &context.shared.guards);
if let Some(node) = animation_rule_node { if let Some(node) = animation_rule_node {
rules = 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 = let important_rules_changed =
self.has_animations() && self.has_animations() &&
data.has_styles() && data.has_styles() &&
data.important_rules_are_different(&rules, data.important_rules_are_different(&rules,
&context.shared.guards); &context.shared.guards);
return RulesMatchedResult { return RulesMatchedResult {
rule_nodes_changed: data.set_primary_rules(rules), rule_nodes_changed: data.set_primary_rules(rules),
@ -738,10 +739,9 @@ pub trait MatchMethods : TElement {
let style_attribute = self.style_attribute(); let style_attribute = self.style_attribute();
{ {
let smil_override = data.get_smil_override(); 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 bloom = context.thread_local.bloom_filter.filter();
let map = &mut context.thread_local.selector_flags; let map = &mut context.thread_local.selector_flags;
let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| { let mut set_selector_flags = |element: &Self, flags: ElementSelectorFlags| {
self.apply_selector_flags(map, element, flags); self.apply_selector_flags(map, element, flags);

View file

@ -23,10 +23,10 @@ use super::*;
/// ///
/// The first one is for Animation cascade level, and the second one is for /// The first one is for Animation cascade level, and the second one is for
/// Transition cascade level. /// Transition cascade level.
pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>, pub struct AnimationRules<'a>(pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>,
pub Option<Arc<Locked<PropertyDeclarationBlock>>>); pub Option<&'a Arc<Locked<PropertyDeclarationBlock>>>);
impl AnimationRules { impl<'a> AnimationRules<'a> {
/// Returns whether these animation rules represents an actual rule or not. /// Returns whether these animation rules represents an actual rule or not.
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.0.is_none() && self.1.is_none() self.0.is_none() && self.1.is_none()

View file

@ -8,7 +8,7 @@
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock}; use properties::{AnimationRules, Importance, LonghandIdSet, PropertyDeclarationBlock};
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::io::{self, Write}; use std::io::{self, Write};
@ -1152,6 +1152,32 @@ impl StrongRuleNode {
.find(|node| node.cascade_level() == CascadeLevel::SMILOverride) .find(|node| node.cascade_level() == CascadeLevel::SMILOverride)
.map(|node| node.get_animation_style()) .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. /// An iterator over a rule node and its ancestors.

View file

@ -943,7 +943,7 @@ impl Stylist {
if let Some(anim) = animation_rules.0 { if let Some(anim) = animation_rules.0 {
Push::push( Push::push(
applicable_declarations, applicable_declarations,
ApplicableDeclarationBlock::from_declarations(anim, ApplicableDeclarationBlock::from_declarations(anim.clone(),
CascadeLevel::Animations)); CascadeLevel::Animations));
} }
debug!("animation: {:?}", context.relations); debug!("animation: {:?}", context.relations);
@ -961,7 +961,8 @@ impl Stylist {
if let Some(anim) = animation_rules.1 { if let Some(anim) = animation_rules.1 {
Push::push( Push::push(
applicable_declarations, applicable_declarations,
ApplicableDeclarationBlock::from_declarations(anim, CascadeLevel::Transitions)); ApplicableDeclarationBlock::from_declarations(anim.clone(),
CascadeLevel::Transitions));
} }
debug!("transition: {:?}", context.relations); debug!("transition: {:?}", context.relations);
debug!("push_applicable_declarations: shareable: {:?}", context.relations); debug!("push_applicable_declarations: shareable: {:?}", context.relations);