aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/layout_thread/lib.rs6
-rw-r--r--components/style/data.rs131
-rw-r--r--components/style/gecko/generated/bindings.rs4
-rw-r--r--components/style/gecko/values.rs8
-rw-r--r--components/style/invalidation/element/restyle_hints.rs47
-rw-r--r--components/style/invalidation/stylesheets.rs6
-rw-r--r--components/style/matching.rs4
-rw-r--r--components/style/properties/gecko.mako.rs15
-rw-r--r--components/style/properties/helpers.mako.rs5
-rw-r--r--components/style/traversal.rs47
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);
}
}