diff options
-rw-r--r-- | components/layout/block.rs | 10 | ||||
-rw-r--r-- | components/layout/flow.rs | 109 | ||||
-rw-r--r-- | components/layout/generated_content.rs | 2 | ||||
-rw-r--r-- | components/layout/inline.rs | 8 | ||||
-rw-r--r-- | components/layout/parallel.rs | 8 | ||||
-rw-r--r-- | components/layout/sequential.rs | 13 | ||||
-rw-r--r-- | components/layout/traversal.rs | 87 | ||||
-rw-r--r-- | 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<T: PreorderFlowTraversal>(self, traversal: &T); - - /// Traverses the tree in postorder. - fn traverse_postorder<T: PostorderFlowTraversal>(self, traversal: &T); - - /// Traverses the tree in-order. - fn traverse_inorder<T: InorderFlowTraversal>(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<T>(&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<ComputedValues>); @@ -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<T: PreorderFlowTraversal>(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<T: PostorderFlowTraversal>(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<T: InorderFlowTraversal>(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<ComputedValues>) { @@ -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<T>(&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<E> 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<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> { /// 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) || |