diff --git a/servo/components/layout/css/matching.rs b/servo/components/layout/css/matching.rs index 7036038369c1..ae136aea5ff7 100644 --- a/servo/components/layout/css/matching.rs +++ b/servo/components/layout/css/matching.rs @@ -11,7 +11,6 @@ use context::SharedLayoutContext; use data::LayoutDataWrapper; use incremental::{self, RestyleDamage}; use msg::ParseErrorReporter; -use script::dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId}; use script::layout_interface::Animation; use selectors::bloom::BloomFilter; use selectors::matching::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes}; @@ -724,49 +723,46 @@ impl<'ln, ConcreteLayoutNode> MatchMethods<'ln, ConcreteLayoutNode> match *layout_data_ref { None => panic!("no layout data"), Some(ref mut layout_data) => { - match self.type_id() { - NodeTypeId::CharacterData(CharacterDataTypeId::Text) => { - // Text nodes get a copy of the parent style. This ensures - // that during fragment construction any non-inherited - // CSS properties (such as vertical-align) are correctly - // set on the fragment(s). - let cloned_parent_style = parent_style.unwrap().clone(); - layout_data.shared_data.style = Some(cloned_parent_style); - } - _ => { - let mut damage = self.cascade_node_pseudo_element( + if self.is_text_node() { + // Text nodes get a copy of the parent style. This ensures + // that during fragment construction any non-inherited + // CSS properties (such as vertical-align) are correctly + // set on the fragment(s). + let cloned_parent_style = parent_style.unwrap().clone(); + layout_data.shared_data.style = Some(cloned_parent_style); + } else { + let mut damage = self.cascade_node_pseudo_element( + layout_context, + parent_style, + &applicable_declarations.normal, + &mut layout_data.shared_data.style, + applicable_declarations_cache, + new_animations_sender, + applicable_declarations.normal_shareable, + true); + if !applicable_declarations.before.is_empty() { + damage = damage | self.cascade_node_pseudo_element( layout_context, - parent_style, - &applicable_declarations.normal, - &mut layout_data.shared_data.style, + Some(layout_data.shared_data.style.as_ref().unwrap()), + &*applicable_declarations.before, + &mut layout_data.data.before_style, applicable_declarations_cache, new_animations_sender, - applicable_declarations.normal_shareable, - true); - if applicable_declarations.before.len() > 0 { - damage = damage | self.cascade_node_pseudo_element( - layout_context, - Some(layout_data.shared_data.style.as_ref().unwrap()), - &*applicable_declarations.before, - &mut layout_data.data.before_style, - applicable_declarations_cache, - new_animations_sender, - false, - false); - } - if applicable_declarations.after.len() > 0 { - damage = damage | self.cascade_node_pseudo_element( - layout_context, - Some(layout_data.shared_data.style.as_ref().unwrap()), - &*applicable_declarations.after, - &mut layout_data.data.after_style, - applicable_declarations_cache, - new_animations_sender, - false, - false); - } - layout_data.data.restyle_damage = damage; + false, + false); } + if !applicable_declarations.after.is_empty() { + damage = damage | self.cascade_node_pseudo_element( + layout_context, + Some(layout_data.shared_data.style.as_ref().unwrap()), + &*applicable_declarations.after, + &mut layout_data.data.after_style, + applicable_declarations_cache, + new_animations_sender, + false, + false); + } + layout_data.data.restyle_damage = damage; } } } diff --git a/servo/components/layout/wrapper.rs b/servo/components/layout/wrapper.rs index 5ad91dbcbc04..ddb899b9db56 100644 --- a/servo/components/layout/wrapper.rs +++ b/servo/components/layout/wrapper.rs @@ -93,16 +93,33 @@ pub trait LayoutNode<'ln> : Sized + Copy + Clone { /// Returns the type ID of this node. fn type_id(&self) -> NodeTypeId; + /// Returns whether this is a text node. It turns out that this is all the style system cares + /// about, and thus obviates the need to compute the full type id, which would be expensive in + /// Gecko. + fn is_text_node(&self) -> bool; + fn is_element(&self) -> bool; fn dump(self); - fn traverse_preorder(self) -> LayoutTreeIterator<'ln, Self>; + fn traverse_preorder(self) -> LayoutTreeIterator<'ln, Self> { + LayoutTreeIterator::new(self) + } /// Returns an iterator over this node's children. - fn children(self) -> LayoutNodeChildrenIterator<'ln, Self>; + fn children(self) -> LayoutNodeChildrenIterator<'ln, Self> { + LayoutNodeChildrenIterator { + current: self.first_child(), + phantom: PhantomData, + } + } - fn rev_children(self) -> LayoutNodeReverseChildrenIterator<'ln, Self>; + fn rev_children(self) -> LayoutNodeReverseChildrenIterator<'ln, Self> { + LayoutNodeReverseChildrenIterator { + current: self.last_child(), + phantom: PhantomData, + } + } /// Converts self into an `OpaqueNode`. fn opaque(&self) -> OpaqueNode; @@ -304,6 +321,10 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> { } } + fn is_text_node(&self) -> bool { + self.type_id() == NodeTypeId::CharacterData(CharacterDataTypeId::Text) + } + fn is_element(&self) -> bool { unsafe { self.node.is_element_for_layout() @@ -314,24 +335,6 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> { self.dump_indent(0); } - fn traverse_preorder(self) -> LayoutTreeIterator<'ln, Self> { - LayoutTreeIterator::new(self) - } - - fn children(self) -> LayoutNodeChildrenIterator<'ln, Self> { - LayoutNodeChildrenIterator { - current: self.first_child(), - phantom: PhantomData, - } - } - - fn rev_children(self) -> LayoutNodeReverseChildrenIterator<'ln, Self> { - LayoutNodeReverseChildrenIterator { - current: self.last_child(), - phantom: PhantomData, - } - } - fn opaque(&self) -> OpaqueNode { OpaqueNodeMethods::from_jsmanaged(unsafe { self.get_jsmanaged() }) } @@ -835,6 +838,10 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized { type ConcreteThreadSafeLayoutElement: ThreadSafeLayoutElement<'ln, ConcreteThreadSafeLayoutNode = Self>; type ChildrenIterator: Iterator + Sized; + /// Creates a new `ThreadSafeLayoutNode` for the same `LayoutNode` + /// with a different pseudo-element type. + fn with_pseudo(&self, pseudo: PseudoElementType) -> Self; + /// Converts self into an `OpaqueNode`. fn opaque(&self) -> OpaqueNode; @@ -857,10 +864,22 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized { fn get_pseudo_element_type(&self) -> PseudoElementType; #[inline] - fn get_before_pseudo(&self) -> Option; + fn get_before_pseudo(&self) -> Option { + let layout_data_ref = self.borrow_layout_data(); + let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap(); + node_layout_data_wrapper.data.before_style.as_ref().map(|style| { + self.with_pseudo(PseudoElementType::Before(style.get_box().display)) + }) + } #[inline] - fn get_after_pseudo(&self) -> Option; + fn get_after_pseudo(&self) -> Option { + let layout_data_ref = self.borrow_layout_data(); + let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap(); + node_layout_data_wrapper.data.after_style.as_ref().map(|style| { + self.with_pseudo(PseudoElementType::After(style.get_box().display)) + }) + } /// Borrows the layout data immutably. Fails on a conflicting borrow. /// @@ -975,8 +994,9 @@ pub trait ThreadSafeLayoutNode<'ln> : Clone + Copy + Sized { fn get_colspan(&self) -> u32; } -// These can violate the thread-safety and therefore are not public. -trait DangerousThreadSafeLayoutNode<'ln> : ThreadSafeLayoutNode<'ln> { +// This trait is only public so that it can be implemented by the gecko wrapper. +// It can be used to violate thread-safety, so don't use it elsewhere in layout! +pub trait DangerousThreadSafeLayoutNode<'ln> : ThreadSafeLayoutNode<'ln> { unsafe fn dangerous_first_child(&self) -> Option; unsafe fn dangerous_next_sibling(&self) -> Option; } @@ -1024,15 +1044,6 @@ impl<'ln> ServoThreadSafeLayoutNode<'ln> { } } - /// Creates a new `ServoThreadSafeLayoutNode` for the same `LayoutNode` - /// with a different pseudo-element type. - fn with_pseudo(&self, pseudo: PseudoElementType) -> ServoThreadSafeLayoutNode<'ln> { - ServoThreadSafeLayoutNode { - node: self.node.clone(), - pseudo: pseudo, - } - } - /// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to /// call and as such is marked `unsafe`. unsafe fn get_jsmanaged(&self) -> &LayoutJS { @@ -1052,6 +1063,13 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> { type ConcreteThreadSafeLayoutElement = ServoThreadSafeLayoutElement<'ln>; type ChildrenIterator = ThreadSafeLayoutNodeChildrenIterator<'ln, Self>; + fn with_pseudo(&self, pseudo: PseudoElementType) -> ServoThreadSafeLayoutNode<'ln> { + ServoThreadSafeLayoutNode { + node: self.node.clone(), + pseudo: pseudo, + } + } + fn opaque(&self) -> OpaqueNode { OpaqueNodeMethods::from_jsmanaged(unsafe { self.get_jsmanaged() }) } @@ -1094,22 +1112,6 @@ impl<'ln> ThreadSafeLayoutNode<'ln> for ServoThreadSafeLayoutNode<'ln> { self.pseudo } - fn get_before_pseudo(&self) -> Option> { - let layout_data_ref = self.borrow_layout_data(); - let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap(); - node_layout_data_wrapper.data.before_style.as_ref().map(|style| { - self.with_pseudo(PseudoElementType::Before(style.get_box().display)) - }) - } - - fn get_after_pseudo(&self) -> Option> { - let layout_data_ref = self.borrow_layout_data(); - let node_layout_data_wrapper = layout_data_ref.as_ref().unwrap(); - node_layout_data_wrapper.data.after_style.as_ref().map(|style| { - self.with_pseudo(PseudoElementType::After(style.get_box().display)) - }) - } - fn borrow_layout_data(&self) -> Ref> { self.node.borrow_layout_data() } @@ -1244,7 +1246,7 @@ pub struct ThreadSafeLayoutNodeChildrenIterator<'ln, ConcreteNode: ThreadSafeLay impl<'ln, ConcreteNode> ThreadSafeLayoutNodeChildrenIterator<'ln, ConcreteNode> where ConcreteNode: DangerousThreadSafeLayoutNode<'ln> { - fn new(parent: ConcreteNode) -> Self { + pub fn new(parent: ConcreteNode) -> Self { let first_child: Option = match parent.get_pseudo_element_type() { PseudoElementType::Normal => { parent.get_before_pseudo().or_else(|| {