diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs index b38bdc1e1c6..43deb7ffd92 100644 --- a/src/components/main/css/matching.rs +++ b/src/components/main/css/matching.rs @@ -12,24 +12,48 @@ use layout::wrapper::LayoutNode; use extra::arc::Arc; use script::layout_interface::LayoutChan; -use servo_util::smallvec::SmallVec; -use style::{TNode, Stylist, cascade}; -use style::{Before, After}; +use servo_util::smallvec::{SmallVec, SmallVec0, SmallVec16}; +use style::{After, Before, PropertyDeclaration, Stylist, TNode, cascade}; + +pub struct ApplicableDeclarations { + normal: SmallVec16>, + before: SmallVec0>, + after: SmallVec0>, +} + +impl ApplicableDeclarations { + pub fn new() -> ApplicableDeclarations { + ApplicableDeclarations { + normal: SmallVec16::new(), + before: SmallVec0::new(), + after: SmallVec0::new(), + } + } + + pub fn clear(&mut self) { + self.normal = SmallVec16::new(); + self.before = SmallVec0::new(); + self.after = SmallVec0::new(); + } +} pub trait MatchMethods { - fn match_node(&self, stylist: &Stylist); - /// Performs aux initialization, selector matching, and cascading sequentially. fn match_and_cascade_subtree(&self, stylist: &Stylist, layout_chan: &LayoutChan, + applicable_declarations: &mut ApplicableDeclarations, parent: Option); - unsafe fn cascade_node(&self, parent: Option); + fn match_node(&self, stylist: &Stylist, applicable_declarations: &mut ApplicableDeclarations); + + unsafe fn cascade_node(&self, + parent: Option, + applicable_declarations: &ApplicableDeclarations); } impl<'ln> MatchMethods for LayoutNode<'ln> { - fn match_node(&self, stylist: &Stylist) { + fn match_node(&self, stylist: &Stylist, applicable_declarations: &mut ApplicableDeclarations) { let style_attribute = self.with_element(|element| { match *element.style_attribute() { None => None, @@ -37,55 +61,50 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { } }); - let mut layout_data_ref = self.mutate_layout_data(); - match *layout_data_ref.get() { - Some(ref mut layout_data) => { - //FIXME To implement a clear() on SmallVec and use it(init_applicable_declarations). - layout_data.data.init_applicable_declarations(); - - stylist.push_applicable_declarations(self, - style_attribute, - None, - &mut layout_data.data.applicable_declarations); - stylist.push_applicable_declarations(self, - None, - Some(Before), - &mut layout_data - .data - .before_applicable_declarations); - stylist.push_applicable_declarations(self, - None, - Some(After), - &mut layout_data - .data - .after_applicable_declarations); - } - None => fail!("no layout data") - } + stylist.push_applicable_declarations(self, + style_attribute, + None, + &mut applicable_declarations.normal); + stylist.push_applicable_declarations(self, + None, + Some(Before), + &mut applicable_declarations.before); + stylist.push_applicable_declarations(self, + None, + Some(After), + &mut applicable_declarations.after); } fn match_and_cascade_subtree(&self, stylist: &Stylist, layout_chan: &LayoutChan, + applicable_declarations: &mut ApplicableDeclarations, parent: Option) { self.initialize_layout_data((*layout_chan).clone()); if self.is_element() { - self.match_node(stylist); + self.match_node(stylist, applicable_declarations); } unsafe { - self.cascade_node(parent) + self.cascade_node(parent, applicable_declarations) } + applicable_declarations.clear(); + for kid in self.children() { - kid.match_and_cascade_subtree(stylist, layout_chan, Some(*self)) + kid.match_and_cascade_subtree(stylist, + layout_chan, + applicable_declarations, + Some(*self)) } } - unsafe fn cascade_node(&self, parent: Option) { + unsafe fn cascade_node(&self, + parent: Option, + applicable_declarations: &ApplicableDeclarations) { macro_rules! cascade_node( - ($applicable_declarations: ident, $style: ident) => {{ + ($applicable_declarations: expr, $style: ident) => {{ // Get our parent's style. This must be unsafe so that we don't touch the parent's // borrow flags. // @@ -100,18 +119,19 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { Some(ref parent_layout_data) => { match parent_layout_data.data.style { None => fail!("parent hasn't been styled yet?!"), - Some(ref style) => Some(style.get()), + Some(ref style) => Some(style), } } } } }; - let computed_values = { - let layout_data_ref = self.borrow_layout_data(); - let layout_data = layout_data_ref.get().as_ref().unwrap(); - Arc::new(cascade(layout_data.data.$applicable_declarations.as_slice(), - parent_style)) + let computed_values = match parent_style { + Some(ref style) => { + Arc::new(cascade($applicable_declarations.as_slice(), + Some(style.get()))) + } + None => Arc::new(cascade($applicable_declarations.as_slice(), None)), }; let mut layout_data_ref = self.mutate_layout_data(); @@ -132,24 +152,12 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { }} ); - { - let before_len = { - let layout_data_ref = self.borrow_layout_data(); - layout_data_ref.get().as_ref().unwrap().data.before_applicable_declarations.len() - }; - if before_len > 0 { - cascade_node!(before_applicable_declarations, before_style); - } + cascade_node!(applicable_declarations.normal, style); + if applicable_declarations.before.len() > 0 { + cascade_node!(applicable_declarations.before, before_style); } - cascade_node!(applicable_declarations, style); - { - let after_len = { - let layout_data_ref = self.borrow_layout_data(); - layout_data_ref.get().as_ref().unwrap().data.after_applicable_declarations.len() - }; - if after_len > 0 { - cascade_node!(after_applicable_declarations, after_style); - } + if applicable_declarations.after.len() > 0 { + cascade_node!(applicable_declarations.after, after_style); } } } diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 733ca093fb8..7868f57c68c 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -5,7 +5,7 @@ //! The layout task. Performs layout on the DOM, builds display lists and sends them to be /// rendered. -use css::matching::MatchMethods; +use css::matching::{ApplicableDeclarations, MatchMethods}; use css::select::new_stylist; use css::node_style::StyledNode; use layout::construct::{FlowConstructionResult, FlowConstructor, NoConstructionResult}; @@ -561,8 +561,10 @@ impl LayoutTask { profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone(), || { match self.parallel_traversal { None => { + let mut applicable_declarations = ApplicableDeclarations::new(); node.match_and_cascade_subtree(self.stylist, &layout_ctx.layout_chan, + &mut applicable_declarations, None) } Some(ref mut traversal) => { diff --git a/src/components/main/layout/parallel.rs b/src/components/main/layout/parallel.rs index 589224bae4c..8a08416b8c6 100644 --- a/src/components/main/layout/parallel.rs +++ b/src/components/main/layout/parallel.rs @@ -6,7 +6,7 @@ //! //! This code is highly unsafe. Keep this file small and easy to audit. -use css::matching::MatchMethods; +use css::matching::{ApplicableDeclarations, MatchMethods}; use layout::context::LayoutContext; use layout::extra::LayoutAuxMethods; use layout::flow::{Flow, FlowLeafSet, PostorderFlowTraversal}; @@ -149,10 +149,12 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, // parser. node.initialize_layout_data(layout_context.layout_chan.clone()); + let mut applicable_declarations = ApplicableDeclarations::new(); + if node.is_element() { // Perform the CSS selector matching. let stylist: &Stylist = cast::transmute(layout_context.stylist); - node.match_node(stylist); + node.match_node(stylist, &mut applicable_declarations); } // Perform the CSS cascade. @@ -161,7 +163,7 @@ fn match_and_cascade_node(unsafe_layout_node: UnsafeLayoutNode, } else { node.parent_node() }; - node.cascade_node(parent_opt); + node.cascade_node(parent_opt, &applicable_declarations); // Enqueue kids. let mut child_count = 0; diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs index 8b0f075b1f6..7c1b0ad567c 100644 --- a/src/components/main/layout/util.rs +++ b/src/components/main/layout/util.rs @@ -12,13 +12,12 @@ use script::dom::bindings::utils::Reflectable; use script::dom::node::AbstractNode; use script::layout_interface::{LayoutChan, UntrustedNodeAddress}; use servo_util::range::Range; -use servo_util::smallvec::{SmallVec0, SmallVec16}; use std::cast; use std::cell::{Ref, RefMut}; use std::iter::Enumerate; use std::libc::uintptr_t; use std::vec::VecIterator; -use style::{ComputedValues, PropertyDeclaration}; +use style::ComputedValues; /// A range of nodes. pub struct NodeRange { @@ -130,13 +129,6 @@ impl ElementMapping { /// Data that layout associates with a node. pub struct PrivateLayoutData { - /// The results of CSS matching for this node. - applicable_declarations: SmallVec16>, - - before_applicable_declarations: SmallVec0>, - - after_applicable_declarations: SmallVec0>, - /// The results of CSS styling for this node. before_style: Option>, @@ -159,9 +151,6 @@ impl PrivateLayoutData { /// Creates new layout data. pub fn new() -> PrivateLayoutData { PrivateLayoutData { - applicable_declarations: SmallVec16::new(), - before_applicable_declarations: SmallVec0::new(), - after_applicable_declarations: SmallVec0::new(), before_style: None, style: None, after_style: None, @@ -170,14 +159,6 @@ impl PrivateLayoutData { parallel: DomParallelInfo::new(), } } - - /// Initialize the function for applicable_declarations. - pub fn init_applicable_declarations(&mut self) { - //FIXME To implement a clear() on SmallVec and use it(init_applicable_declarations). - self.applicable_declarations = SmallVec16::new(); - self.before_applicable_declarations = SmallVec0::new(); - self.after_applicable_declarations = SmallVec0::new(); - } } pub struct LayoutDataWrapper {