From 4c4b01954c471c87e65ef1adb0f0754ddf5fef01 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 24 Mar 2017 09:54:12 +0900 Subject: [PATCH 1/5] Drop mut from pseudo_style for the argument of cascade_internal. --- components/style/matching.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/style/matching.rs b/components/style/matching.rs index 8820108766a..2cd06236473 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -472,7 +472,7 @@ trait PrivateMatchMethods: TElement { fn cascade_internal(&self, context: &StyleContext, primary_style: &ComputedStyle, - pseudo_style: &mut Option<(&PseudoElement, &mut ComputedStyle)>, + pseudo_style: &Option<(&PseudoElement, &mut ComputedStyle)>, booleans: &CascadeBooleans) -> Arc { let shared_context = context.shared; @@ -570,7 +570,7 @@ trait PrivateMatchMethods: TElement { // Compute the new values. let mut new_values = self.cascade_internal(context, primary_style, - &mut pseudo_style, &booleans); + &pseudo_style, &booleans); // Handle animations. if booleans.animate { From 959f1c8360733a02d9615d5337aaa7f63469c433 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 24 Mar 2017 09:54:36 +0900 Subject: [PATCH 2/5] Add a function that returns new rules by removing transition level rule. This will be used for after-change-style of CSS Transition. --- components/style/rule_tree/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 54cf785e458..f9c92fa3c25 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -239,6 +239,16 @@ impl RuleTree { // necessary. Some(self.insert_ordered_rules_from(current, children.into_iter().rev())) } + + /// Returns new rule nodes without Transitions level rule. + pub fn remove_transition_rule_if_applicable(&self, path: &StrongRuleNode) -> StrongRuleNode { + // Return a clone if there is no transition level. + if path.cascade_level() != CascadeLevel::Transitions { + return path.clone(); + } + + path.parent().unwrap().clone() + } } /// The number of RuleNodes added to the free list before we will consider From aa6433b6d6fd1f0d0fef72bcf2ec9901a02dedb2 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 24 Mar 2017 09:54:49 +0900 Subject: [PATCH 3/5] Add a function that returns new rules by removing transition and animation level rules. This will be used for additive animations and SMIL. --- components/style/rule_tree/mod.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index f9c92fa3c25..53a78ac2cad 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -249,6 +249,27 @@ impl RuleTree { path.parent().unwrap().clone() } + + /// Returns new rule node without Animations and Transitions level rules. + pub fn remove_animation_and_transition_rules(&self, path: &StrongRuleNode) -> StrongRuleNode { + // Return a clone if there is neither animation nor transition level. + if !path.has_animation_or_transition_rules() { + return path.clone(); + } + + let iter = path.self_and_ancestors().take_while(|node| node.cascade_level() >= CascadeLevel::Animations); + let mut last = path; + let mut children = vec![]; + for node in iter { + if node.cascade_level() != CascadeLevel::Animations && + node.cascade_level() != CascadeLevel::Transitions { + children.push((node.get().source.clone().unwrap(), node.cascade_level())); + } + last = node; + } + + self.insert_ordered_rules_from(last.parent().unwrap().clone(), children.into_iter().rev()) + } } /// The number of RuleNodes added to the free list before we will consider @@ -738,6 +759,13 @@ impl StrongRuleNode { self.gc(); } } + + /// Returns true if there is either animation or transition level rule. + pub fn has_animation_or_transition_rules(&self) -> bool { + self.self_and_ancestors() + .take_while(|node| node.cascade_level() >= CascadeLevel::Animations) + .any(|node| matches!(node.cascade_level(), CascadeLevel::Animations | CascadeLevel::Transitions)) + } } /// An iterator over a rule node and its ancestors. From dde46c5c90b1a1e0dcc68205957f0adc72785d87 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 24 Mar 2017 09:55:36 +0900 Subject: [PATCH 4/5] Make cascade_internal() reusable with rule nodes. A new function, cascade_with_rules, takes StrongRuleNode and computes cascading result values with the StrongRuleNode. This new function will be used for getting after-change-style for CSS Transitions. --- components/style/matching.rs | 42 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/components/style/matching.rs b/components/style/matching.rs index 2cd06236473..934072f2935 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -469,24 +469,15 @@ trait PrivateMatchMethods: TElement { } } - fn cascade_internal(&self, - context: &StyleContext, - primary_style: &ComputedStyle, - pseudo_style: &Option<(&PseudoElement, &mut ComputedStyle)>, - booleans: &CascadeBooleans) - -> Arc { + fn cascade_with_rules(&self, + context: &StyleContext, + rule_node: &StrongRuleNode, + primary_style: &ComputedStyle, + pseudo_style: &Option<(&PseudoElement, &mut ComputedStyle)>, + cascade_flags: CascadeFlags) + -> Arc { let shared_context = context.shared; let mut cascade_info = CascadeInfo::new(); - let mut cascade_flags = CascadeFlags::empty(); - if booleans.shareable { - cascade_flags.insert(SHAREABLE) - } - if self.skip_root_and_item_based_display_fixup() { - cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) - } - - // Grab the rule node. - let rule_node = &pseudo_style.as_ref().map_or(primary_style, |p| &*p.1).rules; // Grab the inherited values. let parent_el; @@ -552,6 +543,25 @@ trait PrivateMatchMethods: TElement { values } + fn cascade_internal(&self, + context: &StyleContext, + primary_style: &ComputedStyle, + pseudo_style: &Option<(&PseudoElement, &mut ComputedStyle)>, + booleans: &CascadeBooleans) + -> Arc { + let mut cascade_flags = CascadeFlags::empty(); + if booleans.shareable { + cascade_flags.insert(SHAREABLE) + } + if self.skip_root_and_item_based_display_fixup() { + cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) + } + + // Grab the rule node. + let rule_node = &pseudo_style.as_ref().map_or(primary_style, |p| &*p.1).rules; + self.cascade_with_rules(context, rule_node, primary_style, pseudo_style, cascade_flags) + } + /// Computes values and damage for the primary or pseudo style of an element, /// setting them on the ElementData. fn cascade_primary_or_pseudo<'a>(&self, From 6bbd8b09f4c9a51a9a87f77dc884d7d9018f3d5e Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Fri, 24 Mar 2017 09:55:51 +0900 Subject: [PATCH 5/5] Add a function to get after-change style for CSS Transition. --- components/style/matching.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/components/style/matching.rs b/components/style/matching.rs index 934072f2935..33905e0aebb 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -604,6 +604,33 @@ trait PrivateMatchMethods: TElement { } } + #[cfg(feature = "gecko")] + fn get_after_change_style(&self, + context: &mut StyleContext, + primary_style: &ComputedStyle, + pseudo_style: &Option<(&PseudoElement, &mut ComputedStyle)>) + -> Arc { + let style = &pseudo_style.as_ref().map_or(primary_style, |p| &*p.1); + let rule_node = &style.rules; + let without_transition_rules = + context.shared.stylist.rule_tree.remove_transition_rule_if_applicable(rule_node); + if without_transition_rules == *rule_node { + // Note that unwrapping here is fine, because the style is + // only incomplete during the styling process. + return style.values.as_ref().unwrap().clone(); + } + + let mut cascade_flags = CascadeFlags::empty(); + if self.skip_root_and_item_based_display_fixup() { + cascade_flags.insert(SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP) + } + self.cascade_with_rules(context, + &without_transition_rules, + primary_style, + &pseudo_style, + cascade_flags) + } + #[cfg(feature = "gecko")] fn process_animations(&self, context: &mut StyleContext,