diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 0440dcb52bb..4534061f3de 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -35,7 +35,7 @@ use flow_ref::{self, FlowRef, WeakFlowRef}; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use gfx::display_list::{ClippingRegion, DisplayList}; use gfx_traits::LayerId; -use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage}; +use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage}; use inline::InlineFlow; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo}; use msg::compositor_msg::LayerType; @@ -48,6 +48,7 @@ use std::sync::Arc; use std::sync::atomic::Ordering; use std::{fmt, mem, raw}; use style::computed_values::{clear, display, empty_cells, float, position, text_align}; +use style::dom::TRestyleDamage; use style::properties::{self, ComputedValues}; use style::values::computed::LengthOrPercentageOrAuto; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow}; @@ -1046,7 +1047,7 @@ impl BaseFlow { } // New flows start out as fully damaged. - let mut damage = incremental::rebuild_and_reflow(); + let mut damage = RestyleDamage::rebuild_and_reflow(); damage.remove(RECONSTRUCT_FLOW); BaseFlow { diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 828cdeabf8d..16082ad075a 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -18,7 +18,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode}; use gfx::text::glyph::CharIndex; use gfx::text::text_run::{TextRun, TextRunSlice}; use gfx_traits::LayerId; -use incremental::{self, RECONSTRUCT_FLOW, RestyleDamage}; +use incremental::{RECONSTRUCT_FLOW, RestyleDamage}; use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragmentContext, InlineFragmentNodeInfo}; use inline::{InlineMetrics, LAST_FRAGMENT_OF_ELEMENT}; use ipc_channel::ipc::IpcSender; @@ -40,6 +40,7 @@ use style::computed_values::content::ContentItem; use style::computed_values::{border_collapse, clear, display, mix_blend_mode, overflow_wrap}; use style::computed_values::{overflow_x, position, text_decoration, transform_style}; use style::computed_values::{white_space, word_break, z_index}; +use style::dom::TRestyleDamage; use style::properties::ComputedValues; use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; use style::values::computed::{LengthOrPercentageOrNone}; @@ -833,7 +834,7 @@ impl Fragment { self.border_box.start, size); - let mut restyle_damage = incremental::rebuild_and_reflow(); + let mut restyle_damage = RestyleDamage::rebuild_and_reflow(); restyle_damage.remove(RECONSTRUCT_FLOW); Fragment { diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index fd1f1d2f219..d6a2149237c 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -13,12 +13,13 @@ use flow::{InorderFlowTraversal}; use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils}; use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use gfx::display_list::OpaqueNode; -use incremental::{self, RESOLVE_GENERATED_CONTENT}; +use incremental::{RESOLVE_GENERATED_CONTENT, RestyleDamage}; use smallvec::SmallVec; use std::collections::{HashMap, LinkedList}; use std::sync::Arc; use style::computed_values::content::ContentItem; use style::computed_values::{display, list_style_type}; +use style::dom::TRestyleDamage; use style::properties::ComputedValues; use text::TextRunScanner; use wrapper::PseudoElementType; @@ -431,7 +432,7 @@ fn render_text(layout_context: &LayoutContext, fragments.push_back(Fragment::from_opaque_node_and_style(node, pseudo, style, - incremental::rebuild_and_reflow(), + RestyleDamage::rebuild_and_reflow(), info)); // FIXME(pcwalton): This should properly handle multiple marker fragments. This could happen // due to text run splitting. diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index d69610daa12..6865d037651 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -6,6 +6,7 @@ use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, IS_ABSO use std::fmt; use std::sync::Arc; use style::computed_values::float; +use style::dom::TRestyleDamage; use style::properties::ComputedValues; bitflags! { @@ -47,6 +48,18 @@ bitflags! { } } +impl TRestyleDamage for RestyleDamage { + fn compute(old: &Option>, new: &ComputedValues) -> RestyleDamage { compute_damage(old, new) } + + /// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed. + /// + /// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in + /// unnecessary sequential resolution of generated content. + fn rebuild_and_reflow() -> RestyleDamage { + REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW + } +} + impl RestyleDamage { /// Supposing a flow has the given `position` property and this damage, returns the damage that @@ -130,18 +143,10 @@ macro_rules! add_if_not_equal( }) ); -/// Returns a bitmask that represents a flow that needs to be rebuilt and reflowed. -/// -/// Use this instead of `RestyleDamage::all()` because `RestyleDamage::all()` will result in -/// unnecessary sequential resolution of generated content. -pub fn rebuild_and_reflow() -> RestyleDamage { - REPAINT | BUBBLE_ISIZES | REFLOW_OUT_OF_FLOW | REFLOW | RECONSTRUCT_FLOW -} - pub fn compute_damage(old: &Option>, new: &ComputedValues) -> RestyleDamage { let old: &ComputedValues = match old.as_ref() { - None => return rebuild_and_reflow(), + None => return RestyleDamage::rebuild_and_reflow(), Some(cv) => &**cv, }; @@ -195,7 +200,7 @@ pub fn compute_damage(old: &Option>, new: &ComputedValues) - // If the layer requirements of this flow have changed due to the value // of the transform, then reflow is required to rebuild the layers. if old.transform_requires_layer() != new.transform_requires_layer() { - damage.insert(rebuild_and_reflow()); + damage.insert(RestyleDamage::rebuild_and_reflow()); } // FIXME: test somehow that we checked every CSS property @@ -256,7 +261,7 @@ impl<'a> LayoutDamageComputation for &'a mut Flow { fn reflow_entire_document(self) { let self_base = flow::mut_base(self); - self_base.restyle_damage.insert(rebuild_and_reflow()); + self_base.restyle_damage.insert(RestyleDamage::rebuild_and_reflow()); self_base.restyle_damage.remove(RECONSTRUCT_FLOW); for kid in self_base.children.iter_mut() { kid.reflow_entire_document(); diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 6a0038053cb..e219a64f30d 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -10,13 +10,13 @@ use css::matching::{ElementMatchMethods, MatchMethods, StyleSharingResult}; use flow::{PostorderFlowTraversal, PreorderFlowTraversal}; use flow::{self, Flow}; use gfx::display_list::OpaqueNode; -use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage}; +use incremental::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, RestyleDamage}; use script::layout_interface::ReflowGoal; use selectors::bloom::BloomFilter; use std::cell::RefCell; use std::mem; use style::context::StyleContext; -use style::dom::UnsafeNode; +use style::dom::{TRestyleDamage, UnsafeNode}; use style::matching::ApplicableDeclarations; use util::opts; use util::tid::tid; @@ -209,8 +209,7 @@ fn recalc_style_at<'a, 'ln, N: LayoutNode<'ln>> (context: &'a DomTraversalContex }, None => { if node.has_changed() { - node.to_threadsafe().set_restyle_damage( - incremental::rebuild_and_reflow()) + node.set_restyle_damage(N::ConcreteRestyleDamage::rebuild_and_reflow()) } None }, diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 147fda916e3..4a3ca347848 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -132,6 +132,7 @@ impl<'ln> ServoLayoutNode<'ln> { impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> { type ConcreteElement = ServoLayoutElement<'ln>; type ConcreteDocument = ServoLayoutDocument<'ln>; + type ConcreteRestyleDamage = RestyleDamage; fn to_unsafe(&self) -> UnsafeNode { unsafe { @@ -237,6 +238,14 @@ impl<'ln> TNode<'ln> for ServoLayoutNode<'ln> { unsafe { self.mutate_layout_data().map(|d| transmute(d)) } } + fn restyle_damage(self) -> RestyleDamage { + self.borrow_layout_data().unwrap().restyle_damage + } + + fn set_restyle_damage(self, damage: RestyleDamage) { + self.mutate_layout_data().unwrap().restyle_damage = damage; + } + fn parent_node(&self) -> Option> { unsafe { self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(&node)) @@ -714,16 +723,9 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized { fn is_ignorable_whitespace(&self) -> bool; - /// Get the description of how to account for recent style changes. - /// This is a simple bitfield and fine to copy by value. - fn restyle_damage(self) -> RestyleDamage { - self.borrow_layout_data().unwrap().restyle_damage - } + fn restyle_damage(self) -> RestyleDamage; - /// Set the restyle damage field. - fn set_restyle_damage(self, damage: RestyleDamage) { - self.mutate_layout_data().unwrap().restyle_damage = damage; - } + fn set_restyle_damage(self, damage: RestyleDamage); /// Returns the layout data flags for this node. fn flags(self) -> LayoutDataFlags; @@ -909,6 +911,14 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> { } } + fn restyle_damage(self) -> RestyleDamage { + self.node.restyle_damage() + } + + fn set_restyle_damage(self, damage: RestyleDamage) { + self.node.set_restyle_damage(damage) + } + fn flags(self) -> LayoutDataFlags { unsafe { (*self.node.borrow_layout_data_unchecked().unwrap()).flags diff --git a/components/style/dom.rs b/components/style/dom.rs index 4567e986bae..40933b03a7e 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -5,13 +5,15 @@ #![allow(unsafe_code)] use data::PrivateStyleData; -use properties::{PropertyDeclaration, PropertyDeclarationBlock}; +use properties::{ComputedValues, PropertyDeclaration, PropertyDeclarationBlock}; use restyle_hints::{ElementSnapshot, RESTYLE_DESCENDANTS, RESTYLE_LATER_SIBLINGS, RESTYLE_SELF, RestyleHint}; use selectors::matching::DeclarationBlock; use selectors::states::ElementState; use smallvec::VecLike; use std::cell::{Ref, RefMut}; use std::marker::PhantomData; +use std::ops::BitOr; +use std::sync::Arc; use string_cache::{Atom, Namespace}; /// Opaque type stored in type-unsafe work queues for parallel layout. @@ -39,10 +41,15 @@ impl OpaqueNode { } } +pub trait TRestyleDamage : BitOr + Copy { + fn compute(old: &Option>, new: &ComputedValues) -> Self; + fn rebuild_and_reflow() -> Self; +} pub trait TNode<'ln> : Sized + Copy + Clone { type ConcreteElement: TElement<'ln, ConcreteNode = Self, ConcreteDocument = Self::ConcreteDocument>; type ConcreteDocument: TDocument<'ln, ConcreteNode = Self, ConcreteElement = Self::ConcreteElement>; + type ConcreteRestyleDamage: TRestyleDamage; fn to_unsafe(&self) -> UnsafeNode; unsafe fn from_unsafe(n: &UnsafeNode) -> Self; @@ -134,6 +141,12 @@ pub trait TNode<'ln> : Sized + Copy + Clone { #[inline(always)] fn mutate_data(&self) -> Option>; + /// Get the description of how to account for recent style changes. + fn restyle_damage(self) -> Self::ConcreteRestyleDamage; + + /// Set the restyle damage field. + fn set_restyle_damage(self, damage: Self::ConcreteRestyleDamage); + fn parent_node(&self) -> Option; fn first_child(&self) -> Option;