Auto merge of #18004 - mbrubeck:layout-cleanup, r=pcwalton

Clean up and simplify layout traversal code

Various refactorings of the code for traversing flow trees, including:

* Add a generic inorder traversal method
* Remove unused `traverse_postorder_absolute_flows` method
* Combine `compute_absolute_position` and `build_display_list` into a single traversal
* Move all generic traversal code into the `layout::traversal` module

And some changes to add documentation and more-accurate names:

* Fix spelling of `bottom_up_flow`
* Rename `compute_absolute_position` to `compute_stacking_relative_position`
* Change the mis-named `traverse_flow_tree_preorder` to `reflow`

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes do not require tests because they are refactoring only

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18004)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-08-08 14:04:23 -05:00 committed by GitHub
commit ed3c2b9557
17 changed files with 170 additions and 214 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};
@ -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) {

View file

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

View file

@ -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<T: PreorderFlowTraversal>(self, traversal: &T);
/// Traverses the tree in postorder.
fn traverse_postorder<T: PostorderFlowTraversal>(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<T>(&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<T>(&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<ComputedValues>);
@ -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<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)
}
}
/// 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>) {
@ -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<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)
}
}
/// Traverse the Absolute flow tree in postorder.
///
/// Return true if the traversal is to continue or false to stop.
fn traverse_postorder_absolute_flows<T>(&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 {

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

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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<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 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<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> {
/// 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
}
}

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