diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 95d07afec6f..ba9f077c785 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -1250,22 +1250,28 @@ impl<'a> FlowConstructor<'a> { return false } - match node.swap_out_construction_result() { - ConstructionResult::None => true, - ConstructionResult::Flow(mut flow, _) => { + let mut layout_data_ref = node.mutate_layout_data(); + let layout_data = layout_data_ref.as_mut().expect("no layout data"); + let style = (*node.get_style(&layout_data)).clone(); + let damage = layout_data.data.restyle_damage; + match node.get_construction_result(layout_data) { + &mut ConstructionResult::None => true, + &mut ConstructionResult::Flow(ref mut flow, _) => { // The node's flow is of the same type and has the same set of children and can // therefore be repaired by simply propagating damage and style to the flow. - flow::mut_base(&mut *flow).restyle_damage.insert(node.restyle_damage()); - flow.repair_style_and_bubble_inline_sizes(node.style()); + if !flow.is_block_flow() { + return false + } + flow::mut_base(&mut **flow).restyle_damage.insert(damage); + flow.repair_style_and_bubble_inline_sizes(&style); true } - ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( - mut inline_fragments_construction_result)) => { + &mut ConstructionResult::ConstructionItem(ConstructionItem::InlineFragments( + ref mut inline_fragments_construction_result)) => { if !inline_fragments_construction_result.splits.is_empty() { return false } - let damage = node.restyle_damage(); for fragment in inline_fragments_construction_result.fragments .fragments .iter_mut() { @@ -1274,17 +1280,34 @@ impl<'a> FlowConstructor<'a> { flow::mut_base(&mut *inline_block_fragment.flow_ref).restyle_damage .insert(damage); // FIXME(pcwalton): Fragment restyle damage too? - inline_block_fragment.flow_ref.repair_style_and_bubble_inline_sizes( - node.style()); + inline_block_fragment.flow_ref + .repair_style_and_bubble_inline_sizes(&style); + } + SpecificFragmentInfo::InlineAbsoluteHypothetical( + ref mut inline_absolute_hypothetical_fragment) => { + flow::mut_base(&mut *inline_absolute_hypothetical_fragment.flow_ref) + .restyle_damage.insert(damage); + // FIXME(pcwalton): Fragment restyle damage too? + inline_absolute_hypothetical_fragment + .flow_ref + .repair_style_and_bubble_inline_sizes(&style); + } + SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { + flow::mut_base(&mut *inline_absolute_fragment.flow_ref).restyle_damage + .insert(damage); + // FIXME(pcwalton): Fragment restyle damage too? + inline_absolute_fragment.flow_ref + .repair_style_and_bubble_inline_sizes(&style); } _ => { - return false + fragment.repair_style(&style); + return true } } } true } - ConstructionResult::ConstructionItem(_) => { + &mut ConstructionResult::ConstructionItem(_) => { false } } @@ -1450,7 +1473,8 @@ trait NodeUtils { /// Returns true if this node doesn't render its kids and false otherwise. fn is_replaced_content(&self) -> bool; - fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper) -> &'a mut ConstructionResult; + fn get_construction_result<'a>(self, layout_data: &'a mut LayoutDataWrapper) + -> &'a mut ConstructionResult; /// Sets the construction result of a flow. fn set_flow_construction_result(self, result: ConstructionResult); diff --git a/components/layout/css/node_style.rs b/components/layout/css/node_style.rs index 5b33d8d4c2d..5f513a19399 100644 --- a/components/layout/css/node_style.rs +++ b/components/layout/css/node_style.rs @@ -4,6 +4,7 @@ //! Style retrieval from DOM elements. +use data::LayoutDataWrapper; use wrapper::{PseudoElementType, ThreadSafeLayoutNode}; use std::mem; @@ -12,6 +13,7 @@ use std::sync::Arc; /// Node mixin providing `style` method that returns a `NodeStyle` pub trait StyledNode { + fn get_style<'a>(&'a self, layout_data_ref: &'a LayoutDataWrapper) -> &'a Arc; /// Returns the style results for the given node. If CSS selector matching has not yet been /// performed, fails. fn style<'a>(&'a self) -> &'a Arc; @@ -22,37 +24,23 @@ pub trait StyledNode { } impl<'ln> StyledNode for ThreadSafeLayoutNode<'ln> { + #[inline] + fn get_style<'a>(&self, layout_data_ref: &'a LayoutDataWrapper) -> &'a Arc { + match self.get_pseudo_element_type() { + PseudoElementType::Before(_) => layout_data_ref.data.before_style.as_ref().unwrap(), + PseudoElementType::After(_) => layout_data_ref.data.after_style.as_ref().unwrap(), + PseudoElementType::Normal => layout_data_ref.shared_data.style.as_ref().unwrap(), + } + } + #[inline] #[allow(unsafe_code)] fn style<'a>(&'a self) -> &'a Arc { unsafe { let layout_data_ref = self.borrow_layout_data(); - match self.get_pseudo_element_type() { - PseudoElementType::Before(_) => { - mem::transmute(layout_data_ref.as_ref() - .unwrap() - .data - .before_style - .as_ref() - .unwrap()) - } - PseudoElementType::After(_) => { - mem::transmute(layout_data_ref.as_ref() - .unwrap() - .data - .after_style - .as_ref() - .unwrap()) - } - PseudoElementType::Normal => { - mem::transmute(layout_data_ref.as_ref() - .unwrap() - .shared_data - .style - .as_ref() - .unwrap()) - } - } + let layout_data = layout_data_ref.as_ref().expect("no layout data"); + mem::transmute::<&Arc, + &'a Arc>(self.get_style(&layout_data)) } } diff --git a/components/layout/incremental.rs b/components/layout/incremental.rs index f9fda729cfe..9a8cbd822f5 100644 --- a/components/layout/incremental.rs +++ b/components/layout/incremental.rs @@ -184,7 +184,6 @@ pub fn compute_damage(old: &Option>, new: &ComputedValues) - [ get_box.float, get_box.display, get_box.position ]); // FIXME: test somehow that we checked every CSS property - damage } diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 9ac33d0d267..7b30e10e727 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -887,7 +887,8 @@ impl LayoutTask { // let the constellation know about the viewport constraints let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; - constellation_chan.send(ConstellationMsg::ViewportConstrained(self.id, constraints)).unwrap(); + constellation_chan.send(ConstellationMsg::ViewportConstrained( + self.id, constraints)).unwrap(); } } @@ -1074,6 +1075,7 @@ impl LayoutTask { } fn reflow_all_nodes(flow: &mut Flow) { + debug!("reflowing all nodes!"); flow::mut_base(flow).restyle_damage.insert(REFLOW | REPAINT); for child in flow::child_iter(flow) { diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index b362ac6975f..39169787cad 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -170,7 +170,7 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> { &some_bf, &mut applicable_declarations, &mut shareable); - } else { + } else if node.has_changed() { ThreadSafeLayoutNode::new(&node).set_restyle_damage( incremental::rebuild_and_reflow()) } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index f7401c99b11..789d2920832 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -629,7 +629,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { fn set_hover_state(self, state: bool) { self.set_flag(IN_HOVER_STATE, state); - self.dirty(NodeDamage::OtherNodeDamage); + self.dirty(NodeDamage::NodeStyleDamaged); } fn get_focus_state(self) -> bool { @@ -638,7 +638,7 @@ impl<'a> NodeHelpers for JSRef<'a, Node> { fn set_focus_state(self, state: bool) { self.set_flag(IN_FOCUS_STATE, state); - self.dirty(NodeDamage::OtherNodeDamage); + self.dirty(NodeDamage::NodeStyleDamaged); } fn get_disabled_state(self) -> bool {