Code organization: Move all generic traversal code to layout::traversal

This commit is contained in:
Matt Brubeck 2017-08-07 16:59:05 -07:00
parent a08bc13df9
commit d1a37f1ea3
8 changed files with 107 additions and 139 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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' ];

View file

@ -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() {

View file

@ -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 };

View file

@ -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 {

View file

@ -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.

View file

@ -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) ||