aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/style/data.rs7
-rw-r--r--components/style/gecko/media_queries.rs13
-rw-r--r--components/style/matching.rs34
-rw-r--r--components/style/restyle_hints.rs6
-rw-r--r--components/style/servo/media_queries.rs13
-rw-r--r--components/style/traversal.rs24
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) ||