diff options
-rw-r--r-- | components/style/data.rs | 7 | ||||
-rw-r--r-- | components/style/gecko/media_queries.rs | 13 | ||||
-rw-r--r-- | components/style/matching.rs | 34 | ||||
-rw-r--r-- | components/style/restyle_hints.rs | 6 | ||||
-rw-r--r-- | components/style/servo/media_queries.rs | 13 | ||||
-rw-r--r-- | components/style/traversal.rs | 24 |
6 files changed, 76 insertions, 21 deletions
diff --git a/components/style/data.rs b/components/style/data.rs index 5d56ace2441..2833bde2493 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -9,7 +9,7 @@ use context::SharedStyleContext; use dom::TElement; use properties::{AnimationRules, ComputedValues, PropertyDeclarationBlock}; use properties::longhands::display::computed_value as display; -use restyle_hints::{HintComputationContext, RestyleReplacements, RestyleHint}; +use restyle_hints::{CascadeHint, HintComputationContext, RestyleReplacements, RestyleHint}; use rule_tree::StrongRuleNode; use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage}; use selectors::matching::VisitedHandlingMode; @@ -414,6 +414,11 @@ impl StoredRestyleHint { pub fn has_recascade_self(&self) -> bool { self.0.has_recascade_self() } + + /// Insert the specified `CascadeHint`. + pub fn insert_cascade_hint(&mut self, cascade_hint: CascadeHint) { + self.0.insert_cascade_hint(cascade_hint); + } } impl Default for StoredRestyleHint { diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 0b60a502df9..cc18f056121 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -20,7 +20,7 @@ use parser::ParserContext; use properties::{ComputedValues, StyleBuilder}; use properties::longhands::font_size; use std::fmt::{self, Write}; -use std::sync::atomic::{AtomicIsize, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use str::starts_with_ignore_ascii_case; use string_cache::Atom; use style_traits::ToCss; @@ -47,6 +47,9 @@ pub struct Device { /// the parent to compute everything else. So it is correct to just use /// a relaxed atomic here. root_font_size: AtomicIsize, + /// Whether any styles computed in the document relied on the root font-size + /// by using rem units. + used_root_font_size: AtomicBool, } unsafe impl Sync for Device {} @@ -61,6 +64,7 @@ impl Device { default_values: ComputedValues::default_values(unsafe { &*pres_context }), viewport_override: None, root_font_size: AtomicIsize::new(font_size::get_initial_value().0 as isize), // FIXME(bz): Seems dubious? + used_root_font_size: AtomicBool::new(false), } } @@ -91,6 +95,7 @@ impl Device { /// Get the font size of the root element (for rem) pub fn root_font_size(&self) -> Au { + self.used_root_font_size.store(true, Ordering::Relaxed); Au::new(self.root_font_size.load(Ordering::Relaxed) as i32) } @@ -104,6 +109,12 @@ impl Device { // NB: A following stylesheet flush will populate this if appropriate. self.viewport_override = None; self.default_values = ComputedValues::default_values(unsafe { &*self.pres_context }); + self.used_root_font_size.store(false, Ordering::Relaxed); + } + + /// Returns whether we ever looked up the root font size of the Device. + pub fn used_root_font_size(&self) -> bool { + self.used_root_font_size.load(Ordering::Relaxed) } /// Recreates all the temporary state that the `Device` stores. diff --git a/components/style/matching.rs b/components/style/matching.rs index eb88914f8ed..24ac00e4abc 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -78,17 +78,21 @@ pub enum ChildCascadeRequirement { /// /// FIXME(heycam) Although this is "must" cascade, in the future we should /// track whether child elements rely specifically on inheriting particular - /// property values. When we do that, we can treat `MustCascade` as "must - /// cascade unless we know that changes to these properties can be + /// property values. When we do that, we can treat `MustCascadeChildren` as + /// "must cascade unless we know that changes to these properties can be /// ignored". - MustCascade, + MustCascadeChildren, + /// The same as `MustCascadeChildren`, but for the entire subtree. This is + /// used to handle root font-size updates needing to recascade the whole + /// document. + MustCascadeDescendants, } impl From<StyleChange> for ChildCascadeRequirement { fn from(change: StyleChange) -> ChildCascadeRequirement { match change { StyleChange::Unchanged => ChildCascadeRequirement::CanSkipCascade, - StyleChange::Changed => ChildCascadeRequirement::MustCascade, + StyleChange::Changed => ChildCascadeRequirement::MustCascadeChildren, } } } @@ -447,6 +451,22 @@ trait PrivateMatchMethods: TElement { old_values.as_ref().map(|v| v.as_ref()), &new_values, None); + + // Handle root font-size changes. + if self.is_root() && !self.is_native_anonymous() { + // The new root font-size has already been updated on the Device + // in properties::apply_declarations. + let device = context.shared.stylist.device(); + let new_font_size = new_values.get_font().clone_font_size(); + + // If the root font-size changed since last time, and something + // in the document did use rem units, ensure we recascade the + // entire tree. + if old_values.map_or(false, |v| v.get_font().clone_font_size() != new_font_size) && + device.used_root_font_size() { + child_cascade_requirement = ChildCascadeRequirement::MustCascadeDescendants; + } + } } // Set the new computed values. @@ -664,7 +684,7 @@ trait PrivateMatchMethods: TElement { -> ChildCascadeRequirement { // Don't accumulate damage if we're in a restyle for reconstruction. if shared_context.traversal_flags.for_reconstruct() { - return ChildCascadeRequirement::MustCascade; + return ChildCascadeRequirement::MustCascadeChildren; } // If an ancestor is already getting reconstructed by Gecko's top-down @@ -1220,12 +1240,12 @@ pub trait MatchMethods : TElement { -> ChildCascadeRequirement { let restyle = match restyle { Some(r) => r, - None => return ChildCascadeRequirement::MustCascade, + None => return ChildCascadeRequirement::MustCascadeChildren, }; let old_values = match old_values { Some(v) => v, - None => return ChildCascadeRequirement::MustCascade, + None => return ChildCascadeRequirement::MustCascadeChildren, }; // ::before and ::after are element-backed in Gecko, so they do the diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index c9b8918b33c..acca66d6fdb 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -446,6 +446,12 @@ impl RestyleHint { self.insert_from(&other) } + /// Inserts the specified `CascadeHint`. + #[inline] + pub fn insert_cascade_hint(&mut self, cascade_hint: CascadeHint) { + self.recascade.insert(cascade_hint); + } + /// Returns whether this `RestyleHint` represents at least as much restyle /// work as the specified one. #[inline] diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index 8e1f12b6b94..bd5210819d1 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -14,7 +14,7 @@ use parser::ParserContext; use properties::{ComputedValues, StyleBuilder}; use properties::longhands::font_size; use std::fmt; -use std::sync::atomic::{AtomicIsize, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use style_traits::{CSSPixel, ToCss}; use style_traits::viewport::ViewportConstraints; use values::computed::{self, ToComputedValue}; @@ -41,6 +41,10 @@ pub struct Device { /// a relaxed atomic here. #[ignore_heap_size_of = "Pure stack type"] root_font_size: AtomicIsize, + /// Whether any styles computed in the document relied on the root font-size + /// by using rem units. + #[ignore_heap_size_of = "Pure stack type"] + used_root_font_size: AtomicBool, } impl Device { @@ -52,6 +56,7 @@ impl Device { media_type: media_type, viewport_size: viewport_size, root_font_size: AtomicIsize::new(font_size::get_initial_value().0 as isize), // FIXME(bz): Seems dubious? + used_root_font_size: AtomicBool::new(false), } } @@ -65,6 +70,7 @@ impl Device { /// Get the font size of the root element (for rem) pub fn root_font_size(&self) -> Au { + self.used_root_font_size.store(true, Ordering::Relaxed); Au::new(self.root_font_size.load(Ordering::Relaxed) as i32) } @@ -73,6 +79,11 @@ impl Device { self.root_font_size.store(size.0 as isize, Ordering::Relaxed) } + /// Returns whether we ever looked up the root font size of the Device. + pub fn used_root_font_size(&self) -> bool { + self.used_root_font_size.load(Ordering::Relaxed) + } + /// Returns the viewport size of the current device in app units, needed, /// among other things, to resolve viewport units. #[inline] diff --git a/components/style/traversal.rs b/components/style/traversal.rs index a21b83be2e1..820bc41996e 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -9,7 +9,8 @@ use context::{SharedStyleContext, StyleContext, ThreadLocalStyleContext}; use data::{ElementData, ElementStyles, StoredRestyleHint}; use dom::{DirtyDescendants, NodeInfo, OpaqueNode, TElement, TNode}; use matching::{ChildCascadeRequirement, MatchMethods}; -use restyle_hints::{HintComputationContext, RestyleHint}; +use restyle_hints::{CascadeHint, HintComputationContext, RECASCADE_SELF}; +use restyle_hints::{RECASCADE_DESCENDANTS, RestyleHint}; use selector_parser::RestyleDamage; use sharing::{StyleSharingBehavior, StyleSharingTarget}; #[cfg(feature = "servo")] use servo_config::opts; @@ -672,7 +673,7 @@ pub fn recalc_style_at<E, D>(traversal: &D, }), "Should've computed the final hint and handled later_siblings already"); let compute_self = !element.has_current_styles(data); - let mut inherited_style_changed = false; + let mut cascade_hint = CascadeHint::empty(); debug!("recalc_style_at: {:?} (compute_self={:?}, dirty_descendants={:?}, data={:?})", element, compute_self, element.has_dirty_descendants(), data); @@ -680,8 +681,11 @@ pub fn recalc_style_at<E, D>(traversal: &D, // Compute style for this element if necessary. if compute_self { match compute_style(traversal, traversal_data, context, element, data) { - ChildCascadeRequirement::MustCascade => { - inherited_style_changed = true; + ChildCascadeRequirement::MustCascadeChildren => { + cascade_hint |= RECASCADE_SELF; + } + ChildCascadeRequirement::MustCascadeDescendants => { + cascade_hint |= RECASCADE_SELF | RECASCADE_DESCENDANTS; } ChildCascadeRequirement::CanSkipCascade => {} }; @@ -708,15 +712,13 @@ pub fn recalc_style_at<E, D>(traversal: &D, }, }; - if inherited_style_changed { - // FIXME(bholley): Need to handle explicitly-inherited reset properties - // somewhere. - propagated_hint.insert(StoredRestyleHint::recascade_self()); - } + // FIXME(bholley): Need to handle explicitly-inherited reset properties + // somewhere. + propagated_hint.insert_cascade_hint(cascade_hint); - trace!("propagated_hint={:?}, inherited_style_changed={:?}, \ + trace!("propagated_hint={:?}, cascade_hint={:?}, \ is_display_none={:?}, implementing_pseudo={:?}", - propagated_hint, inherited_style_changed, + propagated_hint, cascade_hint, data.styles().is_display_none(), element.implemented_pseudo_element()); debug_assert!(element.has_current_styles(data) || |