diff --git a/components/layout/block.rs b/components/layout/block.rs index f42b749e7a3..e5ef740132c 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -36,9 +36,8 @@ use floats::{ClearType, FloatKind, Floats, PlacementInfo}; use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag}; use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT}; use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, INLINE_POSITION_IS_STATIC}; -use flow::{FragmentationContext, MARGINS_CANNOT_COLLAPSE, PreorderFlowTraversal}; -use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow}; -use flow::IS_ABSOLUTELY_POSITIONED; +use flow::{IS_ABSOLUTELY_POSITIONED, FragmentationContext, MARGINS_CANNOT_COLLAPSE}; +use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, OpaqueFlow}; use flow_list::FlowList; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM}; @@ -57,9 +56,10 @@ use style::computed_values::{position, text_align}; use style::context::SharedStyleContext; use style::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize, WritingMode}; use style::properties::ComputedValues; -use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPOSITION}; +use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW}; use style::values::computed::{LengthOrPercentageOrNone, LengthOrPercentage}; use style::values::computed::LengthOrPercentageOrAuto; +use traversal::PreorderFlowTraversal; /// Information specific to floated blocks. #[derive(Clone, Serialize)] @@ -1065,8 +1065,8 @@ impl BlockFlow { // Assign block-sizes for all flows in this absolute flow tree. // This is preorder because the block-size of an absolute flow may depend on // the block-size of its containing block, which may also be an absolute flow. - (&mut *self as &mut Flow).traverse_preorder_absolute_flows( - &mut AbsoluteAssignBSizesTraversal(layout_context.shared_context())); + let assign_abs_b_sizes = AbsoluteAssignBSizesTraversal(layout_context.shared_context()); + assign_abs_b_sizes.traverse_absolute_flows(&mut *self); } // Don't remove the dirty bits yet if we're absolutely-positioned, since our final size @@ -1551,7 +1551,7 @@ impl BlockFlow { self.assign_inline_sizes(layout_context); // Re-run layout on our children. for child in flow::mut_base(self).children.iter_mut() { - sequential::traverse_flow_tree_preorder(child, layout_context, RelayoutMode::Force); + sequential::reflow(child, layout_context, RelayoutMode::Force); } // Assign our final-final block size. self.assign_block_size(layout_context); @@ -1944,7 +1944,7 @@ impl Flow for BlockFlow { } } - fn compute_absolute_position(&mut self, _layout_context: &LayoutContext) { + fn compute_stacking_relative_position(&mut self, _layout_context: &LayoutContext) { // FIXME (mbrubeck): Get the real container size, taking the container writing mode into // account. Must handle vertical writing modes. let container_size = Size2D::new(self.base.block_container_inline_size, Au(0)); @@ -2084,8 +2084,6 @@ impl Flow for BlockFlow { flow::mut_base(kid).late_absolute_position_info = late_absolute_position_info_for_children; } - - self.base.restyle_damage.remove(REPOSITION) } fn mark_as_root(&mut self) { diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 577e9a167de..b1aa4e3dfe4 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -949,8 +949,8 @@ impl Flow for FlexFlow { } } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 3ce36ad1a7c..e40b1b3cdc2 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -54,7 +54,7 @@ use style::context::SharedStyleContext; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; use style::properties::ComputedValues; use style::selector_parser::RestyleDamage; -use style::servo::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION}; +use style::servo::restyle_damage::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT}; use style::values::computed::LengthOrPercentageOrAuto; use table::TableFlow; use table_caption::TableCaptionFlow; @@ -339,10 +339,10 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { mut_base(self).overflow = overflow } - /// Phase 4 of reflow: computes absolute positions. - fn compute_absolute_position(&mut self, _: &LayoutContext) { + /// Phase 4 of reflow: Compute the stacking-relative position (origin of the content box, + /// in coordinates relative to the nearest ancestor stacking context). + fn compute_stacking_relative_position(&mut self, _: &LayoutContext) { // The default implementation is a no-op. - mut_base(self).restyle_damage.remove(REPOSITION) } /// Phase 5 of reflow: builds display lists. @@ -534,31 +534,6 @@ pub trait ImmutableFlowUtils { } pub trait MutableFlowUtils { - // Traversals - - /// Traverses the tree in preorder. - fn traverse_preorder(self, traversal: &T); - - /// Traverses the tree in postorder. - fn traverse_postorder(self, traversal: &T); - - /// Traverse the Absolute flow tree in preorder. - /// - /// Traverse all your direct absolute descendants, who will then traverse - /// their direct absolute descendants. - /// - /// Return true if the traversal is to continue or false to stop. - fn traverse_preorder_absolute_flows(&mut self, traversal: &mut T) - where T: PreorderFlowTraversal; - - /// Traverse the Absolute flow tree in postorder. - /// - /// Return true if the traversal is to continue or false to stop. - fn traverse_postorder_absolute_flows(&mut self, traversal: &mut T) - where T: PostorderFlowTraversal; - - // Mutators - /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// calling them individually, since there is no reason not to perform both operations. fn repair_style_and_bubble_inline_sizes(self, style: &::ServoArc); @@ -610,42 +585,6 @@ impl FlowClass { } } -/// A top-down traversal. -pub trait PreorderFlowTraversal { - /// The operation to perform. Return true to continue or false to stop. - fn process(&self, flow: &mut Flow); - - /// Returns true if this node must be processed in-order. If this returns false, - /// we skip the operation for this node, but continue processing the descendants. - /// This is called *after* parent nodes are visited. - fn should_process(&self, _flow: &mut Flow) -> bool { - true - } -} - -/// A bottom-up traversal, with a optional in-order pass. -pub trait PostorderFlowTraversal { - /// The operation to perform. Return true to continue or false to stop. - fn process(&self, flow: &mut Flow); - - /// Returns false if this node must be processed in-order. If this returns false, we skip the - /// operation for this node, but continue processing the ancestors. This is called *after* - /// child nodes are visited. - fn should_process(&self, _flow: &mut Flow) -> bool { - true - } -} - -/// An in-order (sequential only) traversal. -pub trait InorderFlowTraversal { - /// The operation to perform. Returns the level of the tree we're at. - fn process(&mut self, flow: &mut Flow, level: u32); - - /// Returns true if this node should be processed and false if neither this node nor its - /// descendants should be processed. - fn should_process(&mut self, flow: &mut Flow) -> bool; -} - bitflags! { #[doc = "Flags used in flows."] pub flags FlowFlags: u32 { @@ -1356,29 +1295,6 @@ impl<'a> ImmutableFlowUtils for &'a Flow { } impl<'a> MutableFlowUtils for &'a mut Flow { - /// Traverses the tree in preorder. - fn traverse_preorder(self, traversal: &T) { - if traversal.should_process(self) { - traversal.process(self); - } - - for kid in child_iter_mut(self) { - kid.traverse_preorder(traversal); - } - } - - /// Traverses the tree in postorder. - fn traverse_postorder(self, traversal: &T) { - for kid in child_iter_mut(self) { - kid.traverse_postorder(traversal); - } - - if traversal.should_process(self) { - traversal.process(self) - } - } - - /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// calling them individually, since there is no reason not to perform both operations. fn repair_style_and_bubble_inline_sizes(self, style: &::ServoArc) { @@ -1386,34 +1302,6 @@ impl<'a> MutableFlowUtils for &'a mut Flow { mut_base(self).update_flags_if_needed(style); self.bubble_inline_sizes(); } - - /// Traverse the Absolute flow tree in preorder. - /// - /// Traverse all your direct absolute descendants, who will then traverse - /// their direct absolute descendants. - /// - /// Return true if the traversal is to continue or false to stop. - fn traverse_preorder_absolute_flows(&mut self, traversal: &mut T) - where T: PreorderFlowTraversal { - traversal.process(*self); - - let descendant_offset_iter = mut_base(*self).abs_descendants.iter(); - for ref mut descendant_link in descendant_offset_iter { - descendant_link.traverse_preorder_absolute_flows(traversal) - } - } - - /// Traverse the Absolute flow tree in postorder. - /// - /// Return true if the traversal is to continue or false to stop. - fn traverse_postorder_absolute_flows(&mut self, traversal: &mut T) - where T: PostorderFlowTraversal { - for mut descendant_link in mut_base(*self).abs_descendants.iter() { - descendant_link.traverse_postorder_absolute_flows(traversal); - } - - traversal.process(*self) - } } impl MutableOwnedFlowUtils for FlowRef { diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index 21fce5a03c4..d9adfabb832 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -10,7 +10,6 @@ use context::{LayoutContext, with_thread_local_font_context}; use flow::{self, AFFECTS_COUNTERS, Flow, HAS_COUNTER_AFFECTING_CHILDREN, ImmutableFlowUtils}; -use flow::InorderFlowTraversal; use fragment::{Fragment, GeneratedContentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; use gfx::display_list::OpaqueNode; use script_layout_interface::wrapper_traits::PseudoElementType; @@ -22,6 +21,7 @@ use style::properties::ComputedValues; use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::RESOLVE_GENERATED_CONTENT; use text::TextRunScanner; +use traversal::InorderFlowTraversal; // Decimal styles per CSS-COUNTER-STYLES ยง 6.1: static DECIMAL: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; @@ -130,7 +130,7 @@ impl<'a> InorderFlowTraversal for ResolveGeneratedContent<'a> { } #[inline] - fn should_process(&mut self, flow: &mut Flow) -> bool { + fn should_process_subtree(&mut self, flow: &mut Flow) -> bool { flow::base(flow).restyle_damage.intersects(RESOLVE_GENERATED_CONTENT) || flow::base(flow).flags.intersects(AFFECTS_COUNTERS | HAS_COUNTER_AFFECTING_CHILDREN) } diff --git a/components/layout/inline.rs b/components/layout/inline.rs index d5813d9bea2..c78f93fc318 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -12,8 +12,7 @@ use display_list_builder::{DisplayListBuildState, InlineFlowDisplayListBuilding} use euclid::{Point2D, Size2D}; use floats::{FloatKind, Floats, PlacementInfo}; use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag}; -use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, EarlyAbsolutePositionInfo, MutableFlowUtils}; -use flow::OpaqueFlow; +use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, EarlyAbsolutePositionInfo, OpaqueFlow}; use flow_ref::FlowRef; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::IS_ELLIPSIS; @@ -34,8 +33,9 @@ use style::computed_values::{display, overflow_x, position, text_align, text_jus use style::computed_values::{vertical_align, white_space}; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; use style::properties::{longhands, ComputedValues}; -use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPOSITION, RESOLVE_GENERATED_CONTENT}; +use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT}; use text; +use traversal::PreorderFlowTraversal; use unicode_bidi as bidi; /// `Line`s are represented as offsets into the child list, rather than @@ -1490,8 +1490,8 @@ impl Flow for InlineFlow { // Assign block-sizes for all flows in this absolute flow tree. // This is preorder because the block-size of an absolute flow may depend on // the block-size of its containing block, which may also be an absolute flow. - (&mut *self as &mut Flow).traverse_preorder_absolute_flows( - &mut AbsoluteAssignBSizesTraversal(layout_context.shared_context())); + let assign_abs_b_sizes = AbsoluteAssignBSizesTraversal(layout_context.shared_context()); + assign_abs_b_sizes.traverse_absolute_flows(&mut *self); } self.base.position.size.block = match self.last_line_containing_real_fragments() { @@ -1534,7 +1534,7 @@ impl Flow for InlineFlow { } } - fn compute_absolute_position(&mut self, _: &LayoutContext) { + fn compute_stacking_relative_position(&mut self, _: &LayoutContext) { // First, gather up the positions of all the containing blocks (if any). // // FIXME(pcwalton): This will get the absolute containing blocks inside `...` wrong in the @@ -1649,8 +1649,6 @@ impl Flow for InlineFlow { _ => {} } } - - self.base.restyle_damage.remove(REPOSITION) } fn update_late_computed_inline_position_if_necessary(&mut self, _: Au) {} diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 007c7ab0eda..8f3f017f513 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -119,8 +119,8 @@ impl Flow for ListItemFlow { } } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 8a1b3bee6ee..6ebe48d78d0 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -166,8 +166,8 @@ impl Flow for MulticolFlow { } } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context); + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context); let pitch = LogicalSize::new(self.block_flow.base.writing_mode, self.column_pitch, Au(0)); let pitch = pitch.to_physical(self.block_flow.base.writing_mode); for (i, child) in self.block_flow.base.children.iter_mut().enumerate() { @@ -254,8 +254,8 @@ impl Flow for MulticolColumnFlow { Flow::fragment(&mut self.block_flow, layout_context, fragmentation_context) } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index bdc178b74c4..6b8cb3ef2cc 100644 --- a/components/layout/parallel.rs +++ b/components/layout/parallel.rs @@ -9,7 +9,7 @@ #![allow(unsafe_code)] use context::LayoutContext; -use flow::{self, Flow, MutableFlowUtils, PostorderFlowTraversal, PreorderFlowTraversal}; +use flow::{self, Flow}; use flow_ref::FlowRef; use profile_traits::time::{self, TimerMetadata, profile}; use rayon; @@ -18,8 +18,8 @@ use smallvec::SmallVec; use std::mem; use std::sync::atomic::{AtomicIsize, Ordering}; use style::dom::UnsafeNode; -use traversal::{AssignISizes, BubbleISizes}; -use traversal::AssignBSizes; +use traversal::{AssignBSizes, AssignISizes, BubbleISizes}; +use traversal::{PostorderFlowTraversal, PreorderFlowTraversal}; pub use style::parallel::traverse_dom; @@ -82,7 +82,7 @@ impl FlowParallelInfo { /// /// The only communication between siblings is that they both /// fetch-and-subtract the parent's children count. -fn buttom_up_flow(mut unsafe_flow: UnsafeFlow, +fn bottom_up_flow(mut unsafe_flow: UnsafeFlow, assign_bsize_traversal: &AssignBSizes) { loop { // Get a real flow. @@ -156,7 +156,7 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], // If there were no more children, start assigning block-sizes. if !had_children { - buttom_up_flow(*unsafe_flow, &assign_bsize_traversal) + bottom_up_flow(*unsafe_flow, &assign_bsize_traversal) } } @@ -187,7 +187,8 @@ fn top_down_flow<'scope>(unsafe_flows: &[UnsafeFlow], } } -pub fn traverse_flow_tree_preorder( +/// Run the main layout passes in parallel. +pub fn reflow( root: &mut Flow, profiler_metadata: Option, time_profiler_chan: time::ProfilerChan, @@ -195,7 +196,7 @@ pub fn traverse_flow_tree_preorder( queue: &rayon::ThreadPool) { if opts::get().bubble_inline_sizes_separately { let bubble_inline_sizes = BubbleISizes { layout_context: &context }; - root.traverse_postorder(&bubble_inline_sizes); + bubble_inline_sizes.traverse(root); } let assign_isize_traversal = &AssignISizes { layout_context: &context }; diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index f6f8ce429e4..f0f0a0e7c79 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -9,36 +9,23 @@ use context::LayoutContext; use display_list_builder::DisplayListBuildState; use euclid::{Point2D, Vector2D}; use floats::SpeculatedFloatPlacement; -use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils}; -use flow::{PostorderFlowTraversal, PreorderFlowTraversal}; -use flow::IS_ABSOLUTELY_POSITIONED; +use flow::{self, Flow, ImmutableFlowUtils, IS_ABSOLUTELY_POSITIONED}; use fragment::{FragmentBorderBoxIterator, CoordinateSystem}; use generated_content::ResolveGeneratedContent; use incremental::RelayoutMode; use servo_config::opts; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, STORE_OVERFLOW}; use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList}; +use traversal::{InorderFlowTraversal, PostorderFlowTraversal, PreorderFlowTraversal}; pub use style::sequential::traverse_dom; pub fn resolve_generated_content(root: &mut Flow, layout_context: &LayoutContext) { - fn doit(flow: &mut Flow, level: u32, traversal: &mut ResolveGeneratedContent) { - if !traversal.should_process(flow) { - return; - } - - traversal.process(flow, level); - - for kid in flow::mut_base(flow).children.iter_mut() { - doit(kid, level + 1, traversal) - } - } - - let mut traversal = ResolveGeneratedContent::new(&layout_context); - doit(root, 0, &mut traversal) + ResolveGeneratedContent::new(&layout_context).traverse(root, 0); } -pub fn traverse_flow_tree_preorder(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: RelayoutMode) { +/// Run the main layout passes sequentially. +pub fn reflow(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: RelayoutMode) { fn doit(flow: &mut Flow, assign_inline_sizes: AssignISizes, assign_block_sizes: AssignBSizes, @@ -68,10 +55,7 @@ pub fn traverse_flow_tree_preorder(root: &mut Flow, layout_context: &LayoutConte let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context, }; - { - let root: &mut Flow = root; - root.traverse_postorder(&bubble_inline_sizes); - } + bubble_inline_sizes.traverse(root); } let assign_inline_sizes = AssignISizes { diff --git a/components/layout/table.rs b/components/layout/table.rs index dea2b590b27..db221518cf7 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -473,8 +473,8 @@ impl Flow for TableFlow { self.block_flow.assign_block_size_for_table_like_flow(vertical_spacing) } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize { diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index c421b4a8e91..6fc188ce71a 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -62,8 +62,8 @@ impl Flow for TableCaptionFlow { self.block_flow.assign_block_size(layout_context); } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 7ef02e28db6..ec1cfe5c9af 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -230,8 +230,8 @@ impl Flow for TableCellFlow { self.assign_block_size_table_cell_base(layout_context); } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index 06040446ddc..3c2eaf25d62 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -452,8 +452,8 @@ impl Flow for TableRowFlow { self.assign_block_size_table_row_base(layout_context); } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index 02c1b49da2b..2ca1862004a 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -165,8 +165,8 @@ impl Flow for TableRowGroupFlow { self.block_flow.assign_block_size_for_table_like_flow(self.spacing.vertical.0) } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) { diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index eec409c8e99..6d08df8d3fa 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -428,8 +428,8 @@ impl Flow for TableWrapperFlow { debug_assert!(remaining.is_none()); } - fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { - self.block_flow.compute_absolute_position(layout_context) + fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) { + self.block_flow.compute_stacking_relative_position(layout_context) } fn place_float_if_applicable<'a>(&mut self) { diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 7ca56d22f9a..dfe79b9d178 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -7,15 +7,14 @@ use construct::FlowConstructor; use context::LayoutContext; use display_list_builder::DisplayListBuildState; -use flow::{self, PreorderFlowTraversal}; -use flow::{CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils, PostorderFlowTraversal}; +use flow::{self, CAN_BE_FRAGMENTED, Flow, ImmutableFlowUtils}; use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; use servo_config::opts; use style::context::{SharedStyleContext, StyleContext}; use style::data::ElementData; use style::dom::{NodeInfo, TElement, TNode}; use style::selector_parser::RestyleDamage; -use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT}; +use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION}; use style::traversal::{DomTraversal, TraversalDriver, recalc_style_at}; use style::traversal::PerLevelTraversalData; use wrapper::{GetRawData, LayoutNodeLayoutData}; @@ -92,6 +91,99 @@ impl<'a, E> DomTraversal for RecalcStyleAndConstructFlows<'a> } } +/// A top-down traversal. +pub trait PreorderFlowTraversal { + /// The operation to perform. Return true to continue or false to stop. + fn process(&self, flow: &mut Flow); + + /// Returns true if this node should be processed and false if neither this node nor its + /// descendants should be processed. + fn should_process_subtree(&self, _flow: &mut Flow) -> bool { + true + } + + /// Returns true if this node must be processed in-order. If this returns false, + /// we skip the operation for this node, but continue processing the descendants. + /// This is called *after* parent nodes are visited. + fn should_process(&self, _flow: &mut Flow) -> bool { + true + } + + /// Traverses the tree in preorder. + fn traverse(&self, flow: &mut Flow) { + if !self.should_process_subtree(flow) { + return; + } + if self.should_process(flow) { + self.process(flow); + } + for kid in flow::child_iter_mut(flow) { + self.traverse(kid); + } + } + + /// Traverse the Absolute flow tree in preorder. + /// + /// Traverse all your direct absolute descendants, who will then traverse + /// their direct absolute descendants. + /// + /// Return true if the traversal is to continue or false to stop. + fn traverse_absolute_flows(&self, flow: &mut Flow) { + if self.should_process(flow) { + self.process(flow); + } + for descendant_link in flow::mut_base(flow).abs_descendants.iter() { + self.traverse_absolute_flows(descendant_link) + } + } +} + +/// A bottom-up traversal, with a optional in-order pass. +pub trait PostorderFlowTraversal { + /// The operation to perform. Return true to continue or false to stop. + fn process(&self, flow: &mut Flow); + + /// Returns false if this node must be processed in-order. If this returns false, we skip the + /// operation for this node, but continue processing the ancestors. This is called *after* + /// child nodes are visited. + fn should_process(&self, _flow: &mut Flow) -> bool { + true + } + + /// Traverses the tree in postorder. + fn traverse(&self, flow: &mut Flow) { + for kid in flow::child_iter_mut(flow) { + self.traverse(kid); + } + if self.should_process(flow) { + self.process(flow); + } + } +} + +/// An in-order (sequential only) traversal. +pub trait InorderFlowTraversal { + /// The operation to perform. Returns the level of the tree we're at. + fn process(&mut self, flow: &mut Flow, level: u32); + + /// Returns true if this node should be processed and false if neither this node nor its + /// descendants should be processed. + fn should_process_subtree(&mut self, _flow: &mut Flow) -> bool { + true + } + + /// Traverses the tree in-order. + fn traverse(&mut self, flow: &mut Flow, level: u32) { + if !self.should_process_subtree(flow) { + return; + } + self.process(flow, level); + for kid in flow::child_iter_mut(flow) { + self.traverse(kid, level + 1); + } + } +} + /// A bottom-up, parallelizable traversal. pub trait PostorderNodeMutTraversal { /// The operation to perform. Return true to continue or false to stop. @@ -200,15 +292,20 @@ impl<'a> PostorderFlowTraversal for AssignBSizes<'a> { } } -#[derive(Copy, Clone)] -pub struct ComputeAbsolutePositions<'a> { +pub struct ComputeStackingRelativePositions<'a> { pub layout_context: &'a LayoutContext<'a>, } -impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> { +impl<'a> PreorderFlowTraversal for ComputeStackingRelativePositions<'a> { + #[inline] + fn should_process_subtree(&self, flow: &mut Flow) -> bool { + flow::base(flow).restyle_damage.contains(REPOSITION) + } + #[inline] fn process(&self, flow: &mut Flow) { - flow.compute_absolute_position(self.layout_context); + flow.compute_stacking_relative_position(self.layout_context); + flow::mut_base(flow).restyle_damage.remove(REPOSITION) } } @@ -226,10 +323,8 @@ impl<'a> BuildDisplayList<'a> { self.state.current_clip_and_scroll_info = flow.clip_and_scroll_info(self.state.layout_context.id); - if self.should_process() { - flow.build_display_list(&mut self.state); - flow::mut_base(flow).restyle_damage.remove(REPAINT); - } + flow.build_display_list(&mut self.state); + flow::mut_base(flow).restyle_damage.remove(REPAINT); for kid in flow::child_iter_mut(flow) { self.traverse(kid); @@ -238,9 +333,4 @@ impl<'a> BuildDisplayList<'a> { self.state.current_stacking_context_id = parent_stacking_context_id; self.state.current_clip_and_scroll_info = parent_clip_and_scroll_info; } - - #[inline] - fn should_process(&self) -> bool { - true - } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index ecfa17ff1d2..baa5ff0a35b 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -71,7 +71,7 @@ use layout::context::RegisteredPainter; use layout::context::RegisteredPainters; use layout::context::heap_size_of_persistent_local_context; use layout::display_list_builder::ToGfxColor; -use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; +use layout::flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT, RelayoutMode}; use layout::layout_debug; @@ -82,7 +82,7 @@ use layout::query::{process_margin_style_query, process_node_overflow_request, p use layout::query::{process_node_geometry_request, process_node_scroll_area_request}; use layout::query::{process_node_scroll_root_id_request, process_offset_parent_query}; use layout::sequential; -use layout::traversal::{ComputeAbsolutePositions, RecalcStyleAndConstructFlows}; +use layout::traversal::{ComputeStackingRelativePositions, PreorderFlowTraversal, RecalcStyleAndConstructFlows}; use layout::webrender_helpers::WebRenderDisplayListConverter; use layout::wrapper::LayoutNodeLayoutData; use layout_traits::LayoutThreadFactory; @@ -929,7 +929,7 @@ impl LayoutThread { fn solve_constraints(layout_root: &mut Flow, layout_context: &LayoutContext) { let _scope = layout_debug_scope!("solve_constraints"); - sequential::traverse_flow_tree_preorder(layout_root, layout_context, RelayoutMode::Incremental); + sequential::reflow(layout_root, layout_context, RelayoutMode::Incremental); } /// Performs layout constraint solving in parallel. @@ -946,11 +946,11 @@ impl LayoutThread { // NOTE: this currently computes borders, so any pruning should separate that // operation out. - parallel::traverse_flow_tree_preorder(layout_root, - profiler_metadata, - time_profiler_chan, - layout_context, - traversal); + parallel::reflow(layout_root, + profiler_metadata, + time_profiler_chan, + layout_context, + traversal); } /// Computes the stacking-relative positions of all flows and, if the painting is dirty and the @@ -974,11 +974,8 @@ impl LayoutThread { flow::mut_base(layout_root).clip = data.page_clip_rect; - if flow::base(layout_root).restyle_damage.contains(REPOSITION) { - layout_root.traverse_preorder(&ComputeAbsolutePositions { - layout_context: layout_context - }); - } + let traversal = ComputeStackingRelativePositions { layout_context: layout_context }; + traversal.traverse(layout_root); if flow::base(layout_root).restyle_damage.contains(REPAINT) || rw_data.display_list.is_none() {