diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_thread/lib.rs | 6 | ||||
-rw-r--r-- | components/style/data.rs | 131 | ||||
-rw-r--r-- | components/style/gecko/generated/bindings.rs | 4 | ||||
-rw-r--r-- | components/style/gecko/values.rs | 8 | ||||
-rw-r--r-- | components/style/invalidation/element/restyle_hints.rs | 47 | ||||
-rw-r--r-- | components/style/invalidation/stylesheets.rs | 6 | ||||
-rw-r--r-- | components/style/matching.rs | 4 | ||||
-rw-r--r-- | components/style/properties/gecko.mako.rs | 15 | ||||
-rw-r--r-- | components/style/properties/helpers.mako.rs | 5 | ||||
-rw-r--r-- | components/style/traversal.rs | 47 |
10 files changed, 96 insertions, 177 deletions
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 364ce2745ac..f381caed992 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -111,9 +111,9 @@ use std::thread; use style::animation::Animation; use style::context::{QuirksMode, ReflowGoal, SharedStyleContext}; use style::context::{StyleSystemOptions, ThreadLocalStyleContextCreationInfo}; -use style::data::StoredRestyleHint; use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::error_reporting::{NullReporter, RustLogReporter}; +use style::invalidation::element::restyle_hints::RestyleHint; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaList, MediaType}; use style::selector_parser::SnapshotMap; @@ -1119,7 +1119,7 @@ impl LayoutThread { let el = node.as_element().unwrap(); if let Some(mut d) = element.mutate_data() { if d.has_styles() { - d.ensure_restyle().hint.insert(StoredRestyleHint::subtree()); + d.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); } } if let Some(p) = el.parent_element() { @@ -1155,7 +1155,7 @@ impl LayoutThread { if needs_dirtying { if let Some(mut d) = element.mutate_data() { if d.has_styles() { - d.ensure_restyle().hint.insert(StoredRestyleHint::subtree()); + d.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); } } } diff --git a/components/style/data.rs b/components/style/data.rs index d96cfafa9fe..46d9fe8afe0 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -16,7 +16,6 @@ use selectors::matching::VisitedHandlingMode; use shared_lock::{Locked, StylesheetGuards}; use std::fmt; use stylearc::Arc; -use traversal::TraversalFlags; /// The structure that represents the result of style computation. This is /// effectively a tuple of rules and computed values, that is, the rule node, @@ -349,97 +348,6 @@ impl ElementStyles { } } -/// Restyle hint for storing on ElementData. -/// -/// We wrap it in a newtype to force the encapsulation of the complexity of -/// handling the correct invalidations in this file. -/// -/// TODO(emilio): This will probably be a non-issue in a bit. -#[derive(Clone, Copy, Debug)] -pub struct StoredRestyleHint(pub RestyleHint); - -impl StoredRestyleHint { - /// Propagates this restyle hint to a child element. - pub fn propagate(&mut self, traversal_flags: &TraversalFlags) -> Self { - use std::mem; - - // In the middle of an animation only restyle, we don't need to - // propagate any restyle hints, and we need to remove ourselves. - if traversal_flags.for_animation_only() { - self.0.remove_animation_hints(); - return Self::empty(); - } - - debug_assert!(!self.0.has_animation_hint(), - "There should not be any animation restyle hints \ - during normal traversal"); - - // Else we should clear ourselves, and return the propagated hint. - let new_hint = mem::replace(&mut self.0, RestyleHint::empty()) - .propagate_for_non_animation_restyle(); - StoredRestyleHint(new_hint) - } - - /// Creates an empty `StoredRestyleHint`. - pub fn empty() -> Self { - StoredRestyleHint(RestyleHint::empty()) - } - - /// Creates a restyle hint that forces the whole subtree to be restyled, - /// including the element. - pub fn subtree() -> Self { - StoredRestyleHint(RestyleHint::restyle_subtree()) - } - - /// Creates a restyle hint that indicates the element must be recascaded. - pub fn recascade_self() -> Self { - StoredRestyleHint(RestyleHint::recascade_self()) - } - - /// Returns true if the hint indicates that our style may be invalidated. - pub fn has_self_invalidations(&self) -> bool { - self.0.affects_self() - } - - /// Whether the restyle hint is empty (nothing requires to be restyled). - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Insert another restyle hint, effectively resulting in the union of both. - pub fn insert(&mut self, other: Self) { - self.0.insert(other.0) - } - - /// Contains whether the whole subtree is invalid. - pub fn contains_subtree(&self) -> bool { - self.0.contains(RestyleHint::restyle_subtree()) - } - - /// Returns true if the hint has animation-only restyle. - pub fn has_animation_hint(&self) -> bool { - self.0.has_animation_hint() - } - - /// Returns true if the hint indicates the current element must be - /// recascaded. - pub fn has_recascade_self(&self) -> bool { - self.0.has_recascade_self() - } -} - -impl Default for StoredRestyleHint { - fn default() -> Self { - Self::empty() - } -} - -impl From<RestyleHint> for StoredRestyleHint { - fn from(hint: RestyleHint) -> Self { - StoredRestyleHint(hint) - } -} - /// Transient data used by the restyle algorithm. This structure is instantiated /// either before or during restyle traversal, and is cleared at the end of node /// processing. @@ -447,21 +355,14 @@ impl From<RestyleHint> for StoredRestyleHint { pub struct RestyleData { /// The restyle hint, which indicates whether selectors need to be rematched /// for this element, its children, and its descendants. - pub hint: StoredRestyleHint, + pub hint: RestyleHint, + + /// Whether we reframed/reconstructed any ancestor or self. + pub reconstructed_ancestor: bool, /// The restyle damage, indicating what kind of layout changes are required /// afte restyling. pub damage: RestyleDamage, - - /// The restyle damage that has already been handled by our ancestors, and does - /// not need to be applied again at this element. Only non-empty during the - /// traversal, once ancestor damage has been calculated. - /// - /// Note that this optimization mostly makes sense in terms of Gecko's top-down - /// frame constructor and change list processing model. We don't bother with it - /// for Servo for now. - #[cfg(feature = "gecko")] - pub damage_handled: RestyleDamage, } impl RestyleData { @@ -469,28 +370,6 @@ impl RestyleData { pub fn has_invalidations(&self) -> bool { self.hint.has_self_invalidations() } - - /// Returns damage handled. - #[cfg(feature = "gecko")] - pub fn damage_handled(&self) -> RestyleDamage { - self.damage_handled - } - - /// Returns damage handled (always empty for servo). - #[cfg(feature = "servo")] - pub fn damage_handled(&self) -> RestyleDamage { - RestyleDamage::empty() - } - - /// Sets damage handled. - #[cfg(feature = "gecko")] - pub fn set_damage_handled(&mut self, d: RestyleDamage) { - self.damage_handled = d; - } - - /// Sets damage handled. No-op for Servo. - #[cfg(feature = "servo")] - pub fn set_damage_handled(&mut self, _: RestyleDamage) {} } /// Style system data associated with an Element. @@ -588,8 +467,8 @@ impl ElementData { debug_assert!(self.restyle.is_some()); let restyle_data = self.restyle.as_ref().unwrap(); - let hint = restyle_data.hint.0; + let hint = restyle_data.hint; if shared_context.traversal_flags.for_animation_only() { // return either CascadeWithReplacements or CascadeOnly in case of // animation-only restyle. diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs index c6e85dff304..38b86d87c3b 100644 --- a/components/style/gecko/generated/bindings.rs +++ b/components/style/gecko/generated/bindings.rs @@ -906,7 +906,9 @@ extern "C" { } extern "C" { pub fn Gecko_SetCounterStyleToName(ptr: *mut CounterStylePtr, - name: *mut nsIAtom); + name: *mut nsIAtom, + pres_context: + RawGeckoPresContextBorrowed); } extern "C" { pub fn Gecko_SetCounterStyleToSymbols(ptr: *mut CounterStylePtr, diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 041387dd54c..aacf5373077 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -12,6 +12,7 @@ use cssparser::RGBA; use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord}; use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius}; use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; +use media_queries::Device; use nsstring::{nsACString, nsCString}; use std::cmp::max; use values::{Auto, Either, ExtremumLength, None_, Normal}; @@ -397,15 +398,16 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au { impl CounterStyleOrNone { /// Convert this counter style to a Gecko CounterStylePtr. - pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) { + pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr, device: &Device) { use gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name; use gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols; + let pres_context = unsafe { &*device.pres_context }; match self { CounterStyleOrNone::None => unsafe { - set_name(gecko_value, atom!("none").into_addrefed()); + set_name(gecko_value, atom!("none").into_addrefed(), pres_context); }, CounterStyleOrNone::Name(name) => unsafe { - set_name(gecko_value, name.0.into_addrefed()); + set_name(gecko_value, name.0.into_addrefed(), pres_context); }, CounterStyleOrNone::Symbols(symbols_type, symbols) => { let symbols: Vec<_> = symbols.0.iter().map(|symbol| match *symbol { diff --git a/components/style/invalidation/element/restyle_hints.rs b/components/style/invalidation/element/restyle_hints.rs index 786c267f203..4b968da031f 100644 --- a/components/style/invalidation/element/restyle_hints.rs +++ b/components/style/invalidation/element/restyle_hints.rs @@ -6,6 +6,7 @@ #[cfg(feature = "gecko")] use gecko_bindings::structs::nsRestyleHint; +use traversal::TraversalFlags; bitflags! { /// The kind of restyle we need to do for a given element. @@ -57,9 +58,40 @@ impl RestyleHint { RECASCADE_SELF | RECASCADE_DESCENDANTS } + /// Returns whether this hint invalidates the element and all its + /// descendants. + pub fn contains_subtree(&self) -> bool { + self.contains(RESTYLE_SELF | RESTYLE_DESCENDANTS) + } + + /// Returns whether we need to restyle this element. + pub fn has_self_invalidations(&self) -> bool { + self.intersects(RESTYLE_SELF | RECASCADE_SELF | Self::replacements()) + } + + /// Propagates this restyle hint to a child element. + pub fn propagate(&mut self, traversal_flags: &TraversalFlags) -> Self { + use std::mem; + + // In the middle of an animation only restyle, we don't need to + // propagate any restyle hints, and we need to remove ourselves. + if traversal_flags.for_animation_only() { + self.remove_animation_hints(); + return Self::empty(); + } + + debug_assert!(!self.has_animation_hint(), + "There should not be any animation restyle hints \ + during normal traversal"); + + // Else we should clear ourselves, and return the propagated hint. + mem::replace(self, Self::empty()) + .propagate_for_non_animation_restyle() + } + /// Returns a new `CascadeHint` appropriate for children of the current /// element. - pub fn propagate_for_non_animation_restyle(&self) -> Self { + fn propagate_for_non_animation_restyle(&self) -> Self { if self.contains(RESTYLE_DESCENDANTS) { return Self::restyle_subtree() } @@ -86,13 +118,6 @@ impl RestyleHint { RESTYLE_SMIL | RESTYLE_CSS_ANIMATIONS | RESTYLE_CSS_TRANSITIONS } - /// Returns whether the hint specifies that some work must be performed on - /// the current element. - #[inline] - pub fn affects_self(&self) -> bool { - self.intersects(RESTYLE_SELF | RECASCADE_SELF | Self::replacements()) - } - /// Returns whether the hint specifies that the currently element must be /// recascaded. pub fn has_recascade_self(&self) -> bool { @@ -145,6 +170,12 @@ impl RestyleHint { } } +impl Default for RestyleHint { + fn default() -> Self { + Self::empty() + } +} + #[cfg(feature = "gecko")] impl From<nsRestyleHint> for RestyleHint { fn from(raw: nsRestyleHint) -> Self { diff --git a/components/style/invalidation/stylesheets.rs b/components/style/invalidation/stylesheets.rs index 4ac69f8fa02..c72a733467c 100644 --- a/components/style/invalidation/stylesheets.rs +++ b/components/style/invalidation/stylesheets.rs @@ -8,9 +8,9 @@ #![deny(unsafe_code)] use Atom; -use data::StoredRestyleHint; use dom::{TElement, TNode}; use fnv::FnvHashSet; +use invalidation::element::restyle_hints::RestyleHint; use selector_parser::SelectorImpl; use selectors::attr::CaseSensitivity; use selectors::parser::{Component, Selector}; @@ -134,7 +134,7 @@ impl StylesheetInvalidationSet { if self.fully_invalid { debug!("process_invalidations: fully_invalid({:?})", element); - data.ensure_restyle().hint.insert(StoredRestyleHint::subtree()); + data.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); return true; } } @@ -177,7 +177,7 @@ impl StylesheetInvalidationSet { if scope.matches(element) { debug!("process_invalidations_in_subtree: {:?} matched {:?}", element, scope); - data.ensure_restyle().hint.insert(StoredRestyleHint::subtree()); + data.ensure_restyle().hint.insert(RestyleHint::restyle_subtree()); return true; } } diff --git a/components/style/matching.rs b/components/style/matching.rs index 7866aea0a22..e10c19baaca 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -697,8 +697,8 @@ trait PrivateMatchMethods: TElement { // for followup work to make the optimization here more optimal by considering // each bit individually. let skip_applying_damage = - restyle.damage_handled.contains(RestyleDamage::reconstruct()) || - restyle.damage.contains(RestyleDamage::reconstruct()); + restyle.damage.contains(RestyleDamage::reconstruct()) || + restyle.reconstructed_ancestor; let difference = self.compute_style_difference(&old_values, &new_values, diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 847b189bf25..8c4cdb4a063 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3202,12 +3202,12 @@ fn static_assert() { unsafe { Gecko_CopyListStyleImageFrom(&mut self.gecko, &other.gecko); } } - pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) { + pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T, device: &Device) { use gecko_bindings::bindings::Gecko_SetCounterStyleToString; use nsstring::{nsACString, nsCString}; use self::longhands::list_style_type::computed_value::T; match v { - T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle), + T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle, device), T::String(s) => unsafe { Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle, &nsCString::from(s) as &nsACString) @@ -4254,7 +4254,7 @@ clip-path self.gecko.mContents.is_empty() } - pub fn set_content(&mut self, v: longhands::content::computed_value::T) { + pub fn set_content(&mut self, v: longhands::content::computed_value::T, device: &Device) { use properties::longhands::content::computed_value::T; use properties::longhands::content::computed_value::ContentItem; use values::generics::CounterStyleOrNone; @@ -4275,7 +4275,8 @@ clip-path fn set_counter_function(data: &mut nsStyleContentData, content_type: nsStyleContentType, - name: &str, sep: &str, style: CounterStyleOrNone) { + name: &str, sep: &str, + style: CounterStyleOrNone, device: &Device) { debug_assert!(content_type == eStyleContentType_Counter || content_type == eStyleContentType_Counters); let counter_func = unsafe { @@ -4285,7 +4286,7 @@ clip-path if content_type == eStyleContentType_Counters { counter_func.mSeparator.assign_utf8(sep); } - style.to_gecko_value(&mut counter_func.mCounterStyle); + style.to_gecko_value(&mut counter_func.mCounterStyle, device); } match v { @@ -4349,11 +4350,11 @@ clip-path => self.gecko.mContents[i].mType = eStyleContentType_NoCloseQuote, ContentItem::Counter(name, style) => { set_counter_function(&mut self.gecko.mContents[i], - eStyleContentType_Counter, &name, "", style); + eStyleContentType_Counter, &name, "", style, device); } ContentItem::Counters(name, sep, style) => { set_counter_function(&mut self.gecko.mContents[i], - eStyleContentType_Counters, &name, &sep, style); + eStyleContentType_Counters, &name, &sep, style, device); } ContentItem::Url(ref url) => { unsafe { diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index c8502551a0e..f2c0e818b37 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -344,6 +344,8 @@ <% maybe_wm = ", wm" if property.logical else "" maybe_cacheable = ", cacheable" if property.has_uncacheable_values == "True" else "" + props_need_device = "content list_style_type".split() if product == "gecko" else [] + maybe_device = ", context.device" if property.ident in props_need_device else "" %> match *value { DeclaredValue::Value(ref specified_value) => { @@ -375,7 +377,8 @@ inherited_style.get_font()); % else: context.mutate_style().mutate_${data.current_style_struct.name_lower}() - .set_${property.ident}(computed ${maybe_cacheable} ${maybe_wm}); + .set_${property.ident}(computed ${maybe_device} + ${maybe_cacheable} ${maybe_wm}); % endif % endif } diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 53e0dc38281..9f085cfe374 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -6,7 +6,7 @@ use atomic_refcell::AtomicRefCell; use context::{SharedStyleContext, StyleContext, ThreadLocalStyleContext}; -use data::{ElementData, ElementStyles, StoredRestyleHint}; +use data::{ElementData, ElementStyles}; use dom::{DirtyDescendants, NodeInfo, OpaqueNode, TElement, TNode}; use invalidation::element::restyle_hints::{RECASCADE_SELF, RECASCADE_DESCENDANTS, RestyleHint}; use matching::{ChildCascadeRequirement, MatchMethods}; @@ -297,8 +297,8 @@ pub trait DomTraversal<E: TElement> : Sync { if let Some(parent) = el.traversal_parent() { let parent_data = parent.borrow_data().unwrap(); let going_to_reframe = parent_data.get_restyle().map_or(false, |r| { - (r.damage | r.damage_handled()) - .contains(RestyleDamage::reconstruct()) + r.reconstructed_ancestor || + r.damage.contains(RestyleDamage::reconstruct()) }); let mut is_before_or_after_pseudo = false; @@ -691,7 +691,7 @@ pub fn recalc_style_at<E, D>(traversal: &D, // Now that matching and cascading is done, clear the bits corresponding to // those operations and compute the propagated restyle hint. let mut propagated_hint = match data.get_restyle_mut() { - None => StoredRestyleHint::empty(), + None => RestyleHint::empty(), Some(r) => { debug_assert!(context.shared.traversal_flags.for_animation_only() || !r.hint.has_animation_hint(), @@ -730,14 +730,16 @@ pub fn recalc_style_at<E, D>(traversal: &D, DontLog) && (has_dirty_descendants_for_this_restyle || !propagated_hint.is_empty()) { - let damage_handled = data.get_restyle().map_or(RestyleDamage::empty(), |r| { - r.damage_handled() | r.damage.handled_for_descendants() + let reconstructed_ancestor = data.get_restyle().map_or(false, |r| { + r.reconstructed_ancestor || + r.damage.contains(RestyleDamage::reconstruct()) }); - - preprocess_children::<E, D>(context, - element, - propagated_hint, - damage_handled); + preprocess_children::<E, D>( + context, + element, + propagated_hint, + reconstructed_ancestor, + ) } // If we are in a restyle for reconstruction, drop the existing restyle @@ -840,12 +842,15 @@ fn compute_style<E, D>(_traversal: &D, } } -fn preprocess_children<E, D>(context: &mut StyleContext<E>, - element: E, - propagated_hint: StoredRestyleHint, - damage_handled: RestyleDamage) - where E: TElement, - D: DomTraversal<E>, +fn preprocess_children<E, D>( + context: &mut StyleContext<E>, + element: E, + propagated_hint: RestyleHint, + reconstructed_ancestor: bool, +) +where + E: TElement, + D: DomTraversal<E>, { trace!("preprocess_children: {:?}", element); @@ -880,9 +885,7 @@ fn preprocess_children<E, D>(context: &mut StyleContext<E>, // If the child doesn't have pre-existing RestyleData and we don't have // any reason to create one, avoid the useless allocation and move on to // the next child. - if propagated_hint.is_empty() && - damage_handled.is_empty() && - !child_data.has_restyle() { + if !reconstructed_ancestor && propagated_hint.is_empty() && !child_data.has_restyle() { continue; } @@ -890,10 +893,8 @@ fn preprocess_children<E, D>(context: &mut StyleContext<E>, // Propagate the parent restyle hint, that may make us restyle the whole // subtree. + restyle_data.reconstructed_ancestor = reconstructed_ancestor; restyle_data.hint.insert(propagated_hint); - - // Store the damage already handled by ancestors. - restyle_data.set_damage_handled(damage_handled); } } |