From 0d36930727e6de009ceef81cf5e1dd98afab9011 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 12:40:21 -0700 Subject: [PATCH 1/7] Add a generic inorder traversal method --- components/layout/flow.rs | 17 ++++++++++++++++- components/layout/generated_content.rs | 2 +- components/layout/sequential.rs | 16 ++-------------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 3ce36ad1a7c..5bf08c2a92d 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -542,6 +542,9 @@ pub trait MutableFlowUtils { /// Traverses the tree in postorder. fn traverse_postorder(self, traversal: &T); + /// Traverses the tree in-order. + fn traverse_inorder(self, traversal: &mut T, level: u32); + /// Traverse the Absolute flow tree in preorder. /// /// Traverse all your direct absolute descendants, who will then traverse @@ -643,7 +646,7 @@ pub trait InorderFlowTraversal { /// 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; + fn should_process_subtree(&mut self, flow: &mut Flow) -> bool; } bitflags! { @@ -1378,6 +1381,18 @@ impl<'a> MutableFlowUtils for &'a mut Flow { } } + /// Traverses the tree in-order. + fn traverse_inorder(self, traversal: &mut T, level: u32) { + if !traversal.should_process_subtree(self) { + return; + } + + traversal.process(self, level); + + for kid in child_iter_mut(self) { + kid.traverse_inorder(traversal, level + 1); + } + } /// 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. diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index 21fce5a03c4..26e1754fad9 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -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/sequential.rs b/components/layout/sequential.rs index f6f8ce429e4..b97f0a4d357 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -9,7 +9,7 @@ use context::LayoutContext; use display_list_builder::DisplayListBuildState; use euclid::{Point2D, Vector2D}; use floats::SpeculatedFloatPlacement; -use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils}; +use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils}; use flow::{PostorderFlowTraversal, PreorderFlowTraversal}; use flow::IS_ABSOLUTELY_POSITIONED; use fragment::{FragmentBorderBoxIterator, CoordinateSystem}; @@ -22,20 +22,8 @@ use traversal::{AssignBSizes, AssignISizes, BubbleISizes, BuildDisplayList}; 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) + root.traverse_inorder(&mut traversal, 0); } pub fn traverse_flow_tree_preorder(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: RelayoutMode) { From 1f0e42e8fe721d896796205669f7265f2ed64b3e Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 12:50:15 -0700 Subject: [PATCH 2/7] Remove unused traverse_postorder_absolute_flows method --- components/layout/flow.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 5bf08c2a92d..a97ec1cb9ad 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -554,12 +554,6 @@ pub trait MutableFlowUtils { 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 @@ -1417,18 +1411,6 @@ impl<'a> MutableFlowUtils for &'a mut Flow { 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 { From a08bc13df96c70022e5ab0207419609a501d85dc Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 16:08:01 -0700 Subject: [PATCH 3/7] Rename compute_absolute_position to compute_stacking_relative_position --- components/layout/block.rs | 2 +- components/layout/flex.rs | 4 ++-- components/layout/flow.rs | 5 +++-- components/layout/inline.rs | 2 +- components/layout/list_item.rs | 4 ++-- components/layout/multicol.rs | 8 ++++---- components/layout/table.rs | 4 ++-- components/layout/table_caption.rs | 4 ++-- components/layout/table_cell.rs | 4 ++-- components/layout/table_row.rs | 4 ++-- components/layout/table_rowgroup.rs | 4 ++-- components/layout/table_wrapper.rs | 4 ++-- components/layout/traversal.rs | 6 +++--- components/layout_thread/lib.rs | 4 ++-- 14 files changed, 30 insertions(+), 29 deletions(-) diff --git a/components/layout/block.rs b/components/layout/block.rs index f42b749e7a3..9bd413a2725 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -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)); 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 a97ec1cb9ad..c6fc65407e5 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -339,8 +339,9 @@ 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) } diff --git a/components/layout/inline.rs b/components/layout/inline.rs index d5813d9bea2..d6c561de22a 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -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 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/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..d31be602ee8 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -201,14 +201,14 @@ 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 process(&self, flow: &mut Flow) { - flow.compute_absolute_position(self.layout_context); + flow.compute_stacking_relative_position(self.layout_context); } } diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index ecfa17ff1d2..8ee539d6f79 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -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, RecalcStyleAndConstructFlows}; use layout::webrender_helpers::WebRenderDisplayListConverter; use layout::wrapper::LayoutNodeLayoutData; use layout_traits::LayoutThreadFactory; @@ -975,7 +975,7 @@ 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_root.traverse_preorder(&ComputeStackingRelativePositions { layout_context: layout_context }); } From d1a37f1ea374b1ea9d4907f02402afbb89dc8df0 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 16:59:05 -0700 Subject: [PATCH 4/7] Code organization: Move all generic traversal code to layout::traversal --- components/layout/block.rs | 10 +-- components/layout/flow.rs | 109 ------------------------- components/layout/generated_content.rs | 2 +- components/layout/inline.rs | 8 +- components/layout/parallel.rs | 8 +- components/layout/sequential.rs | 13 +-- components/layout/traversal.rs | 87 +++++++++++++++++++- components/layout_thread/lib.rs | 9 +- 8 files changed, 107 insertions(+), 139 deletions(-) diff --git a/components/layout/block.rs b/components/layout/block.rs index 9bd413a2725..c677c9b659f 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}; @@ -60,6 +59,7 @@ use style::properties::ComputedValues; use style::servo::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, REPOSITION}; 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 diff --git a/components/layout/flow.rs b/components/layout/flow.rs index c6fc65407e5..e2d4e5cd99c 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -535,28 +535,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); - - /// Traverses the tree in-order. - fn traverse_inorder(self, traversal: &mut T, level: u32); - - /// 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; - - // 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); @@ -608,42 +586,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_subtree(&mut self, flow: &mut Flow) -> bool; -} - bitflags! { #[doc = "Flags used in flows."] pub flags FlowFlags: u32 { @@ -1354,41 +1296,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) - } - } - - /// Traverses the tree in-order. - fn traverse_inorder(self, traversal: &mut T, level: u32) { - if !traversal.should_process_subtree(self) { - return; - } - - traversal.process(self, level); - - for kid in child_iter_mut(self) { - kid.traverse_inorder(traversal, level + 1); - } - } - /// 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) { @@ -1396,22 +1303,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) - } - } } impl MutableOwnedFlowUtils for FlowRef { diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index 26e1754fad9..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' ]; diff --git a/components/layout/inline.rs b/components/layout/inline.rs index d6c561de22a..bcda03232c8 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; @@ -36,6 +35,7 @@ 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 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() { diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index bdc178b74c4..e1753d11803 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; @@ -195,7 +195,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 b97f0a4d357..9e6ea4c2fe6 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -9,21 +9,19 @@ use context::LayoutContext; use display_list_builder::DisplayListBuildState; use euclid::{Point2D, Vector2D}; use floats::SpeculatedFloatPlacement; -use flow::{self, Flow, ImmutableFlowUtils, 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) { - let mut traversal = ResolveGeneratedContent::new(&layout_context); - root.traverse_inorder(&mut traversal, 0); + ResolveGeneratedContent::new(&layout_context).traverse(root, 0); } pub fn traverse_flow_tree_preorder(root: &mut Flow, layout_context: &LayoutContext, relayout_mode: RelayoutMode) { @@ -56,10 +54,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/traversal.rs b/components/layout/traversal.rs index d31be602ee8..54e62b6d591 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -7,8 +7,7 @@ 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}; @@ -92,6 +91,90 @@ 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 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(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. diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 8ee539d6f79..540ea92fd70 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::{ComputeStackingRelativePositions, RecalcStyleAndConstructFlows}; +use layout::traversal::{ComputeStackingRelativePositions, PreorderFlowTraversal, RecalcStyleAndConstructFlows}; use layout::webrender_helpers::WebRenderDisplayListConverter; use layout::wrapper::LayoutNodeLayoutData; use layout_traits::LayoutThreadFactory; @@ -975,9 +975,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(&ComputeStackingRelativePositions { - layout_context: layout_context - }); + let traversal = ComputeStackingRelativePositions { layout_context: layout_context }; + traversal.traverse(layout_root); } if flow::base(layout_root).restyle_damage.contains(REPAINT) || From ee697a926d5773c2d8d2ac24e3daabaf0f514bad Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 17:02:07 -0700 Subject: [PATCH 5/7] Fix spelling of `bottom_up_flow` --- components/layout/parallel.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index e1753d11803..16a68796ffb 100644 --- a/components/layout/parallel.rs +++ b/components/layout/parallel.rs @@ -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) } } From 832b811198363814928365ea4636bca5abae52db Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 7 Aug 2017 17:06:23 -0700 Subject: [PATCH 6/7] Change the mis-named 'traverse_flow_tree_preorder' to 'reflow' --- components/layout/block.rs | 2 +- components/layout/parallel.rs | 3 ++- components/layout/sequential.rs | 3 ++- components/layout_thread/lib.rs | 12 ++++++------ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/components/layout/block.rs b/components/layout/block.rs index c677c9b659f..b2aa6f3dd52 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -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); diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs index 16a68796ffb..6b8cb3ef2cc 100644 --- a/components/layout/parallel.rs +++ b/components/layout/parallel.rs @@ -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, diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index 9e6ea4c2fe6..f0f0a0e7c79 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -24,7 +24,8 @@ pub fn resolve_generated_content(root: &mut Flow, layout_context: &LayoutContext 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, diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 540ea92fd70..5cefd1488a2 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -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 From ca300d642428f3e6ab305165f765c5acccc1a5d9 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Tue, 8 Aug 2017 10:56:53 -0700 Subject: [PATCH 7/7] Allow CalculateStackingRelativePositions to short-circuit --- components/layout/block.rs | 4 +--- components/layout/flow.rs | 3 +-- components/layout/inline.rs | 4 +--- components/layout/traversal.rs | 29 ++++++++++++++++++----------- components/layout_thread/lib.rs | 6 ++---- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/components/layout/block.rs b/components/layout/block.rs index b2aa6f3dd52..e5ef740132c 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -56,7 +56,7 @@ 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; @@ -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/flow.rs b/components/layout/flow.rs index e2d4e5cd99c..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; @@ -343,7 +343,6 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { /// 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. diff --git a/components/layout/inline.rs b/components/layout/inline.rs index bcda03232c8..c78f93fc318 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -33,7 +33,7 @@ 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; @@ -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/traversal.rs b/components/layout/traversal.rs index 54e62b6d591..dfe79b9d178 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -14,7 +14,7 @@ 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}; @@ -96,6 +96,12 @@ 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. @@ -105,6 +111,9 @@ pub trait PreorderFlowTraversal { /// 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); } @@ -283,15 +292,20 @@ impl<'a> PostorderFlowTraversal for AssignBSizes<'a> { } } -#[derive(Copy, Clone)] pub struct ComputeStackingRelativePositions<'a> { pub layout_context: &'a LayoutContext<'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_stacking_relative_position(self.layout_context); + flow::mut_base(flow).restyle_damage.remove(REPOSITION) } } @@ -309,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); @@ -321,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 5cefd1488a2..baa5ff0a35b 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -974,10 +974,8 @@ impl LayoutThread { flow::mut_base(layout_root).clip = data.page_clip_rect; - if flow::base(layout_root).restyle_damage.contains(REPOSITION) { - let traversal = ComputeStackingRelativePositions { layout_context: layout_context }; - traversal.traverse(layout_root); - } + 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() {