mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
auto merge of #3668 : cgaebel/servo/sequential-reflow, r=pcwalton
Now that DOM/Flow traversals have been refactored out, the `recalc_style_for_subtree` function in `css/matching.rs` can be removed, in lieu of just running the standard `recalc_style_for_node` and `construct_flows` traversals sequentially. Now we no longer have the maintenance headache of duplicating selector matching logic in two places! \o/ This passes reftests with both default arguments, and with `-y 1`. r? @pcwalton
This commit is contained in:
commit
7eaeaeeb21
8 changed files with 201 additions and 312 deletions
|
@ -431,18 +431,17 @@ struct AbsoluteAssignBSizesTraversal<'a>(&'a LayoutContext<'a>);
|
||||||
|
|
||||||
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
|
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&self, flow: &mut Flow) {
|
||||||
let block_flow = flow.as_block();
|
let block_flow = flow.as_block();
|
||||||
|
|
||||||
// The root of the absolute flow tree is definitely not absolutely
|
// The root of the absolute flow tree is definitely not absolutely
|
||||||
// positioned. Nothing to process here.
|
// positioned. Nothing to process here.
|
||||||
if block_flow.is_root_of_absolute_flow_tree() {
|
if block_flow.is_root_of_absolute_flow_tree() {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let AbsoluteAssignBSizesTraversal(ref ctx) = *self;
|
let AbsoluteAssignBSizesTraversal(ref ctx) = *self;
|
||||||
block_flow.calculate_abs_block_size_and_margins(*ctx);
|
block_flow.calculate_abs_block_size_and_margins(*ctx);
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,14 +457,13 @@ struct AbsoluteStoreOverflowTraversal<'a>{
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
|
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&self, flow: &mut Flow) {
|
||||||
// This will be taken care of by the normal store-overflow traversal.
|
// This will be taken care of by the normal store-overflow traversal.
|
||||||
if flow.is_root_of_absolute_flow_tree() {
|
if flow.is_root_of_absolute_flow_tree() {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
flow.store_overflow(self.layout_context);
|
flow.store_overflow(self.layout_context);
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,16 +709,10 @@ impl BlockFlow {
|
||||||
///
|
///
|
||||||
/// Return true if the traversal is to continue or false to stop.
|
/// Return true if the traversal is to continue or false to stop.
|
||||||
fn traverse_preorder_absolute_flows<T:PreorderFlowTraversal>(&mut self,
|
fn traverse_preorder_absolute_flows<T:PreorderFlowTraversal>(&mut self,
|
||||||
traversal: &mut T)
|
traversal: &mut T) {
|
||||||
-> bool {
|
|
||||||
let flow = self as &mut Flow;
|
let flow = self as &mut Flow;
|
||||||
if traversal.should_prune(flow) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !traversal.process(flow) {
|
traversal.process(flow);
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
let cb_block_start_edge_offset = flow.generated_containing_block_rect().start.b;
|
let cb_block_start_edge_offset = flow.generated_containing_block_rect().start.b;
|
||||||
let mut descendant_offset_iter = mut_base(flow).abs_descendants.iter_with_offset();
|
let mut descendant_offset_iter = mut_base(flow).abs_descendants.iter_with_offset();
|
||||||
|
@ -730,30 +722,20 @@ impl BlockFlow {
|
||||||
// The stored y_offset is wrt to the flow box.
|
// The stored y_offset is wrt to the flow box.
|
||||||
// Translate it to the CB (which is the padding box).
|
// Translate it to the CB (which is the padding box).
|
||||||
block.static_b_offset = **y_offset - cb_block_start_edge_offset;
|
block.static_b_offset = **y_offset - cb_block_start_edge_offset;
|
||||||
if !block.traverse_preorder_absolute_flows(traversal) {
|
block.traverse_preorder_absolute_flows(traversal);
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverse the Absolute flow tree in postorder.
|
/// Traverse the Absolute flow tree in postorder.
|
||||||
///
|
///
|
||||||
/// Return true if the traversal is to continue or false to stop.
|
/// Return true if the traversal is to continue or false to stop.
|
||||||
fn traverse_postorder_absolute_flows<T:PostorderFlowTraversal>(&mut self,
|
fn traverse_postorder_absolute_flows<T:PostorderFlowTraversal>(&mut self,
|
||||||
traversal: &mut T)
|
traversal: &mut T) {
|
||||||
-> bool {
|
|
||||||
let flow = self as &mut Flow;
|
let flow = self as &mut Flow;
|
||||||
if traversal.should_prune(flow) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for descendant_link in mut_base(flow).abs_descendants.iter() {
|
for descendant_link in mut_base(flow).abs_descendants.iter() {
|
||||||
let block = descendant_link.as_block();
|
let block = descendant_link.as_block();
|
||||||
if !block.traverse_postorder_absolute_flows(traversal) {
|
block.traverse_postorder_absolute_flows(traversal);
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
traversal.process(flow)
|
traversal.process(flow)
|
||||||
|
|
|
@ -5,10 +5,8 @@
|
||||||
// High-level interface to CSS selector matching.
|
// High-level interface to CSS selector matching.
|
||||||
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use construct::FlowConstructor;
|
|
||||||
use context::LayoutContext;
|
|
||||||
use util::{LayoutDataAccess, LayoutDataWrapper};
|
use util::{LayoutDataAccess, LayoutDataWrapper};
|
||||||
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode};
|
use wrapper::{LayoutElement, LayoutNode};
|
||||||
use wrapper::{TLayoutNode};
|
use wrapper::{TLayoutNode};
|
||||||
|
|
||||||
use script::dom::node::{TextNodeTypeId};
|
use script::dom::node::{TextNodeTypeId};
|
||||||
|
@ -295,15 +293,6 @@ pub trait MatchMethods {
|
||||||
/// called to reset the bloom filter after an `insert`.
|
/// called to reset the bloom filter after an `insert`.
|
||||||
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter);
|
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter);
|
||||||
|
|
||||||
/// Performs aux initialization, selector matching, cascading, and flow construction
|
|
||||||
/// sequentially.
|
|
||||||
fn recalc_style_for_subtree(&self,
|
|
||||||
stylist: &Stylist,
|
|
||||||
layout_context: &LayoutContext,
|
|
||||||
parent_bf: &mut Option<Box<BloomFilter>>,
|
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
|
||||||
parent: Option<LayoutNode>);
|
|
||||||
|
|
||||||
fn match_node(&self,
|
fn match_node(&self,
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
parent_bf: &Option<Box<BloomFilter>>,
|
parent_bf: &Option<Box<BloomFilter>>,
|
||||||
|
@ -524,67 +513,6 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
element.each_class(|class| bf.remove(class));
|
element.each_class(|class| bf.remove(class));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recalc_style_for_subtree(&self,
|
|
||||||
stylist: &Stylist,
|
|
||||||
layout_context: &LayoutContext,
|
|
||||||
parent_bf: &mut Option<Box<BloomFilter>>,
|
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
|
||||||
parent: Option<LayoutNode>) {
|
|
||||||
self.initialize_layout_data(layout_context.shared.layout_chan.clone());
|
|
||||||
|
|
||||||
// First, check to see whether we can share a style with someone.
|
|
||||||
let sharing_result = unsafe {
|
|
||||||
self.share_style_if_possible(layout_context.style_sharing_candidate_cache(),
|
|
||||||
parent.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Otherwise, match and cascade selectors.
|
|
||||||
match sharing_result {
|
|
||||||
CannotShare(mut shareable) => {
|
|
||||||
if self.is_element() {
|
|
||||||
self.match_node(stylist, &*parent_bf, applicable_declarations, &mut shareable);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
self.cascade_node(parent,
|
|
||||||
applicable_declarations,
|
|
||||||
layout_context.applicable_declarations_cache())
|
|
||||||
}
|
|
||||||
|
|
||||||
applicable_declarations.clear();
|
|
||||||
|
|
||||||
// Add ourselves to the LRU cache.
|
|
||||||
if shareable {
|
|
||||||
layout_context.style_sharing_candidate_cache().insert_if_possible(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StyleWasShared(index) => layout_context.style_sharing_candidate_cache().touch(index),
|
|
||||||
}
|
|
||||||
|
|
||||||
match *parent_bf {
|
|
||||||
None => {},
|
|
||||||
Some(ref mut pbf) => self.insert_into_bloom_filter(&mut **pbf),
|
|
||||||
}
|
|
||||||
|
|
||||||
for kid in self.children() {
|
|
||||||
kid.recalc_style_for_subtree(stylist,
|
|
||||||
layout_context,
|
|
||||||
parent_bf,
|
|
||||||
applicable_declarations,
|
|
||||||
Some(self.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
match *parent_bf {
|
|
||||||
None => {},
|
|
||||||
Some(ref mut pbf) => self.remove_from_bloom_filter(&mut **pbf),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct flows.
|
|
||||||
let layout_node = ThreadSafeLayoutNode::new(self);
|
|
||||||
let mut flow_constructor = FlowConstructor::new(layout_context);
|
|
||||||
flow_constructor.process(&layout_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
applicable_declarations: &ApplicableDeclarations,
|
applicable_declarations: &ApplicableDeclarations,
|
||||||
|
|
|
@ -411,10 +411,10 @@ pub trait MutableFlowUtils {
|
||||||
// Traversals
|
// Traversals
|
||||||
|
|
||||||
/// Traverses the tree in preorder.
|
/// Traverses the tree in preorder.
|
||||||
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &mut T) -> bool;
|
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &T);
|
||||||
|
|
||||||
/// Traverses the tree in postorder.
|
/// Traverses the tree in postorder.
|
||||||
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &mut T) -> bool;
|
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &T);
|
||||||
|
|
||||||
// Mutators
|
// Mutators
|
||||||
|
|
||||||
|
@ -464,41 +464,27 @@ pub enum FlowClass {
|
||||||
/// A top-down traversal.
|
/// A top-down traversal.
|
||||||
pub trait PreorderFlowTraversal {
|
pub trait PreorderFlowTraversal {
|
||||||
/// The operation to perform. Return true to continue or false to stop.
|
/// The operation to perform. Return true to continue or false to stop.
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool;
|
fn process(&self, flow: &mut Flow);
|
||||||
|
|
||||||
/// Returns true if this node must be processed in-order. If this returns false,
|
/// 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.
|
/// we skip the operation for this node, but continue processing the descendants.
|
||||||
/// This is called *after* parent nodes are visited.
|
/// This is called *after* parent nodes are visited.
|
||||||
fn should_process(&mut self, _flow: &mut Flow) -> bool {
|
fn should_process(&self, _flow: &mut Flow) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this node should be pruned. If this returns true, we skip the operation
|
|
||||||
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
|
|
||||||
/// visited. The default implementation never prunes any nodes.
|
|
||||||
fn should_prune(&mut self, _flow: &mut Flow) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A bottom-up traversal, with a optional in-order pass.
|
/// A bottom-up traversal, with a optional in-order pass.
|
||||||
pub trait PostorderFlowTraversal {
|
pub trait PostorderFlowTraversal {
|
||||||
/// The operation to perform. Return true to continue or false to stop.
|
/// The operation to perform. Return true to continue or false to stop.
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool;
|
fn process(&self, flow: &mut Flow);
|
||||||
|
|
||||||
/// Returns false if this node must be processed in-order. If this returns false, we skip the
|
/// 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*
|
/// operation for this node, but continue processing the ancestors. This is called *after*
|
||||||
/// child nodes are visited.
|
/// child nodes are visited.
|
||||||
fn should_process(&mut self, _flow: &mut Flow) -> bool {
|
fn should_process(&self, _flow: &mut Flow) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this node should be pruned. If this returns true, we skip the operation
|
|
||||||
/// entirely and do not process any descendant nodes. This is called *before* child nodes are
|
|
||||||
/// visited. The default implementation never prunes any nodes.
|
|
||||||
fn should_prune(&mut self, _flow: &mut Flow) -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flags used in flows, tightly packed to save space.
|
/// Flags used in flows, tightly packed to save space.
|
||||||
|
@ -1043,45 +1029,25 @@ impl<'a> ImmutableFlowUtils for &'a Flow + 'a {
|
||||||
|
|
||||||
impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
||||||
/// Traverses the tree in preorder.
|
/// Traverses the tree in preorder.
|
||||||
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &mut T) -> bool {
|
fn traverse_preorder<T:PreorderFlowTraversal>(self, traversal: &T) {
|
||||||
if traversal.should_prune(self) {
|
if traversal.should_process(self) {
|
||||||
return true
|
traversal.process(self);
|
||||||
}
|
|
||||||
|
|
||||||
if !traversal.should_process(self) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !traversal.process(self) {
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for kid in child_iter(self) {
|
for kid in child_iter(self) {
|
||||||
if !kid.traverse_preorder(traversal) {
|
kid.traverse_preorder(traversal);
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the tree in postorder.
|
/// Traverses the tree in postorder.
|
||||||
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &mut T) -> bool {
|
fn traverse_postorder<T:PostorderFlowTraversal>(self, traversal: &T) {
|
||||||
if traversal.should_prune(self) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for kid in child_iter(self) {
|
for kid in child_iter(self) {
|
||||||
if !kid.traverse_postorder(traversal) {
|
kid.traverse_postorder(traversal);
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !traversal.should_process(self) {
|
if traversal.should_process(self) {
|
||||||
return true
|
traversal.process(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
traversal.process(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate and set overflow for current flow.
|
/// Calculate and set overflow for current flow.
|
||||||
|
|
|
@ -5,18 +5,16 @@
|
||||||
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
|
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
|
||||||
//! rendered.
|
//! rendered.
|
||||||
|
|
||||||
use css::matching::{ApplicableDeclarations, MatchMethods};
|
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use construct::FlowConstructionResult;
|
use construct::FlowConstructionResult;
|
||||||
use context::{LayoutContext, SharedLayoutContext};
|
use context::{LayoutContext, SharedLayoutContext};
|
||||||
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
|
||||||
use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
|
|
||||||
use flow;
|
use flow;
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
use parallel::UnsafeFlow;
|
use parallel::UnsafeFlow;
|
||||||
use parallel;
|
use parallel;
|
||||||
use traversal;
|
use sequential;
|
||||||
use util::{LayoutDataAccess, LayoutDataWrapper, OpaqueNodeMethods, ToGfxColor};
|
use util::{LayoutDataAccess, LayoutDataWrapper, OpaqueNodeMethods, ToGfxColor};
|
||||||
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
|
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
|
||||||
|
|
||||||
|
@ -48,7 +46,6 @@ use servo_msg::constellation_msg::{ConstellationChan, PipelineId, Failure, Failu
|
||||||
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||||
use gfx::font_cache_task::{FontCacheTask};
|
use gfx::font_cache_task::{FontCacheTask};
|
||||||
use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
|
use servo_net::local_image_cache::{ImageResponder, LocalImageCache};
|
||||||
use servo_util::bloom::BloomFilter;
|
|
||||||
use servo_net::resource_task::{ResourceTask, load_bytes_iter};
|
use servo_net::resource_task::{ResourceTask, load_bytes_iter};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::Au;
|
||||||
use servo_util::geometry;
|
use servo_util::geometry;
|
||||||
|
@ -515,31 +512,10 @@ impl LayoutTask {
|
||||||
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
|
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn solve_constraints<'a>(&self,
|
fn solve_constraints<'a>(&self,
|
||||||
layout_root: &mut Flow,
|
layout_root: &mut FlowRef,
|
||||||
layout_context: &'a LayoutContext<'a>) {
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
let _scope = layout_debug_scope!("solve_constraints");
|
let _scope = layout_debug_scope!("solve_constraints");
|
||||||
|
sequential::traverse_flow_tree_preorder(layout_root, shared_layout_context);
|
||||||
if layout_context.shared.opts.bubble_inline_sizes_separately {
|
|
||||||
let mut traversal = traversal::BubbleISizes {
|
|
||||||
layout_context: layout_context,
|
|
||||||
};
|
|
||||||
layout_root.traverse_postorder(&mut traversal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(pcwalton): Prune these two passes.
|
|
||||||
{
|
|
||||||
let mut traversal = traversal::AssignISizes {
|
|
||||||
layout_context: layout_context,
|
|
||||||
};
|
|
||||||
layout_root.traverse_preorder(&mut traversal);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut traversal = traversal::AssignBSizesAndStoreOverflow {
|
|
||||||
layout_context: layout_context,
|
|
||||||
};
|
|
||||||
layout_root.traverse_postorder(&mut traversal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs layout constraint solving in parallel.
|
/// Performs layout constraint solving in parallel.
|
||||||
|
@ -552,12 +528,7 @@ impl LayoutTask {
|
||||||
rw_data: &mut LayoutTaskData,
|
rw_data: &mut LayoutTaskData,
|
||||||
layout_root: &mut FlowRef,
|
layout_root: &mut FlowRef,
|
||||||
shared_layout_context: &SharedLayoutContext) {
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
if shared_layout_context.opts.bubble_inline_sizes_separately {
|
let _scope = layout_debug_scope!("solve_constraints_parallel");
|
||||||
let mut traversal = traversal::BubbleISizes {
|
|
||||||
layout_context: &LayoutContext::new(shared_layout_context),
|
|
||||||
};
|
|
||||||
layout_root.get_mut().traverse_postorder(&mut traversal);
|
|
||||||
}
|
|
||||||
|
|
||||||
match rw_data.parallel_traversal {
|
match rw_data.parallel_traversal {
|
||||||
None => fail!("solve_contraints_parallel() called with no parallel traversal ready"),
|
None => fail!("solve_contraints_parallel() called with no parallel traversal ready"),
|
||||||
|
@ -649,17 +620,10 @@ impl LayoutTask {
|
||||||
let rw_data = rw_data.deref_mut();
|
let rw_data = rw_data.deref_mut();
|
||||||
match rw_data.parallel_traversal {
|
match rw_data.parallel_traversal {
|
||||||
None => {
|
None => {
|
||||||
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
|
sequential::traverse_dom_preorder(*node, &shared_layout_ctx);
|
||||||
let mut applicable_declarations = ApplicableDeclarations::new();
|
|
||||||
let mut parent_bf = Some(box BloomFilter::new());
|
|
||||||
node.recalc_style_for_subtree(&*rw_data.stylist,
|
|
||||||
&layout_ctx,
|
|
||||||
&mut parent_bf,
|
|
||||||
&mut applicable_declarations,
|
|
||||||
None)
|
|
||||||
}
|
}
|
||||||
Some(ref mut traversal) => {
|
Some(ref mut traversal) => {
|
||||||
parallel::traverse_dom_preorder(*node, &mut shared_layout_ctx, traversal)
|
parallel::traverse_dom_preorder(*node, &shared_layout_ctx, traversal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,8 +666,7 @@ impl LayoutTask {
|
||||||
match rw_data.parallel_traversal {
|
match rw_data.parallel_traversal {
|
||||||
None => {
|
None => {
|
||||||
// Sequential mode.
|
// Sequential mode.
|
||||||
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
|
self.solve_constraints(&mut layout_root, &shared_layout_ctx)
|
||||||
self.solve_constraints(layout_root.get_mut(), &layout_ctx)
|
|
||||||
}
|
}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
// Parallel mode.
|
// Parallel mode.
|
||||||
|
@ -724,20 +687,19 @@ impl LayoutTask {
|
||||||
let rw_data = rw_data.deref_mut();
|
let rw_data = rw_data.deref_mut();
|
||||||
match rw_data.parallel_traversal {
|
match rw_data.parallel_traversal {
|
||||||
None => {
|
None => {
|
||||||
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
|
sequential::build_display_list_for_subtree(
|
||||||
let mut traversal = traversal::BuildDisplayList {
|
&mut layout_root,
|
||||||
layout_context: &layout_ctx,
|
&shared_layout_ctx);
|
||||||
};
|
|
||||||
traversal.process(layout_root.get_mut());
|
|
||||||
}
|
}
|
||||||
Some(ref mut traversal) => {
|
Some(ref mut traversal) => {
|
||||||
parallel::build_display_list_for_subtree(&mut layout_root,
|
parallel::build_display_list_for_subtree(
|
||||||
&data.url,
|
&mut layout_root,
|
||||||
data.iframe,
|
&data.url,
|
||||||
self.first_reflow.get(),
|
data.iframe,
|
||||||
self.time_profiler_chan.clone(),
|
self.first_reflow.get(),
|
||||||
&mut shared_layout_ctx,
|
self.time_profiler_chan.clone(),
|
||||||
traversal);
|
&shared_layout_ctx,
|
||||||
|
traversal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub mod layout_task;
|
||||||
pub mod inline;
|
pub mod inline;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod parallel;
|
pub mod parallel;
|
||||||
|
pub mod sequential;
|
||||||
pub mod table_wrapper;
|
pub mod table_wrapper;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
pub mod table_caption;
|
pub mod table_caption;
|
||||||
|
|
|
@ -11,7 +11,8 @@ use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal
|
||||||
use flow;
|
use flow;
|
||||||
use flow_ref::FlowRef;
|
use flow_ref::FlowRef;
|
||||||
use traversal::{RecalcStyleForNode, ConstructFlows};
|
use traversal::{RecalcStyleForNode, ConstructFlows};
|
||||||
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes, BubbleISizes};
|
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
|
||||||
|
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::{LayoutDataAccess, LayoutDataWrapper};
|
use util::{LayoutDataAccess, LayoutDataWrapper};
|
||||||
use wrapper::{layout_node_to_unsafe_layout_node, layout_node_from_unsafe_layout_node, LayoutNode};
|
use wrapper::{layout_node_to_unsafe_layout_node, layout_node_from_unsafe_layout_node, LayoutNode};
|
||||||
|
@ -79,12 +80,12 @@ impl DomParallelInfo {
|
||||||
|
|
||||||
/// A parallel top-down DOM traversal.
|
/// A parallel top-down DOM traversal.
|
||||||
pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
|
pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
node: UnsafeLayoutNode,
|
node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>);
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn run_parallel_helper(&mut self,
|
fn run_parallel_helper(&self,
|
||||||
unsafe_node: UnsafeLayoutNode,
|
unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>,
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>,
|
||||||
top_down_func: extern "Rust" fn(UnsafeFlow,
|
top_down_func: extern "Rust" fn(UnsafeFlow,
|
||||||
|
@ -139,7 +140,7 @@ trait ParallelPostorderDomTraversal : PostorderDomTraversal {
|
||||||
///
|
///
|
||||||
/// The only communication between siblings is that they both
|
/// The only communication between siblings is that they both
|
||||||
/// fetch-and-subtract the parent's children count.
|
/// fetch-and-subtract the parent's children count.
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
mut unsafe_node: UnsafeLayoutNode,
|
mut unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
|
||||||
loop {
|
loop {
|
||||||
|
@ -214,7 +215,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
///
|
///
|
||||||
/// The only communication between siblings is that they both
|
/// The only communication between siblings is that they both
|
||||||
/// fetch-and-subtract the parent's children count.
|
/// fetch-and-subtract the parent's children count.
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
mut unsafe_flow: UnsafeFlow,
|
mut unsafe_flow: UnsafeFlow,
|
||||||
_: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
_: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
||||||
loop {
|
loop {
|
||||||
|
@ -259,12 +260,12 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
|
|
||||||
/// A parallel top-down flow traversal.
|
/// A parallel top-down flow traversal.
|
||||||
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
|
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
unsafe_flow: UnsafeFlow,
|
unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn run_parallel_helper(&mut self,
|
fn run_parallel_helper(&self,
|
||||||
unsafe_flow: UnsafeFlow,
|
unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
|
||||||
top_down_func: extern "Rust" fn(UnsafeFlow,
|
top_down_func: extern "Rust" fn(UnsafeFlow,
|
||||||
|
@ -304,7 +305,7 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
|
||||||
impl<'a> ParallelPostorderFlowTraversal for BubbleISizes<'a> {}
|
impl<'a> ParallelPostorderFlowTraversal for BubbleISizes<'a> {}
|
||||||
|
|
||||||
impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
|
impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
unsafe_flow: UnsafeFlow,
|
unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
||||||
self.run_parallel_helper(unsafe_flow,
|
self.run_parallel_helper(unsafe_flow,
|
||||||
|
@ -316,10 +317,23 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
|
||||||
|
|
||||||
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {}
|
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {}
|
||||||
|
|
||||||
|
impl<'a> ParallelPreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
|
fn run_parallel(&self,
|
||||||
|
unsafe_flow: UnsafeFlow,
|
||||||
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
|
||||||
|
self.run_parallel_helper(unsafe_flow,
|
||||||
|
proxy,
|
||||||
|
compute_absolute_positions,
|
||||||
|
build_display_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ParallelPostorderFlowTraversal for BuildDisplayList<'a> {}
|
||||||
|
|
||||||
impl<'a> ParallelPostorderDomTraversal for ConstructFlows<'a> {}
|
impl<'a> ParallelPostorderDomTraversal for ConstructFlows<'a> {}
|
||||||
|
|
||||||
impl <'a> ParallelPreorderDomTraversal for RecalcStyleForNode<'a> {
|
impl <'a> ParallelPreorderDomTraversal for RecalcStyleForNode<'a> {
|
||||||
fn run_parallel(&mut self,
|
fn run_parallel(&self,
|
||||||
unsafe_node: UnsafeLayoutNode,
|
unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
||||||
self.run_parallel_helper(unsafe_node,
|
self.run_parallel_helper(unsafe_node,
|
||||||
|
@ -333,7 +347,7 @@ fn recalc_style(unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
||||||
let shared_layout_context = unsafe { &**proxy.user_data() };
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
let mut recalc_style_for_node_traversal = RecalcStyleForNode {
|
let recalc_style_for_node_traversal = RecalcStyleForNode {
|
||||||
layout_context: &layout_context,
|
layout_context: &layout_context,
|
||||||
};
|
};
|
||||||
recalc_style_for_node_traversal.run_parallel(unsafe_node, proxy)
|
recalc_style_for_node_traversal.run_parallel(unsafe_node, proxy)
|
||||||
|
@ -343,7 +357,7 @@ fn construct_flows(unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
|
||||||
let shared_layout_context = unsafe { &**proxy.user_data() };
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
let mut construct_flows_traversal = ConstructFlows {
|
let construct_flows_traversal = ConstructFlows {
|
||||||
layout_context: &layout_context,
|
layout_context: &layout_context,
|
||||||
};
|
};
|
||||||
construct_flows_traversal.run_parallel(unsafe_node, proxy)
|
construct_flows_traversal.run_parallel(unsafe_node, proxy)
|
||||||
|
@ -353,91 +367,40 @@ fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
||||||
let shared_layout_context = unsafe { &**proxy.user_data() };
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
let mut assign_inline_sizes_traversal = AssignISizes {
|
let assign_inline_sizes_traversal = AssignISizes {
|
||||||
layout_context: &layout_context,
|
layout_context: &layout_context,
|
||||||
};
|
};
|
||||||
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
|
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
|
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
||||||
let shared_layout_context = unsafe { &**proxy.user_data() };
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflow {
|
let assign_block_sizes_traversal = AssignBSizesAndStoreOverflow {
|
||||||
layout_context: &layout_context,
|
layout_context: &layout_context,
|
||||||
};
|
};
|
||||||
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
|
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_absolute_position(unsafe_flow: UnsafeFlow,
|
fn compute_absolute_positions(unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
|
||||||
let mut had_descendants = false;
|
|
||||||
unsafe {
|
|
||||||
// Get a real flow.
|
|
||||||
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
|
|
||||||
|
|
||||||
// Compute the absolute position for the flow.
|
|
||||||
flow.get_mut().compute_absolute_position();
|
|
||||||
|
|
||||||
// Enqueue all children.
|
|
||||||
for kid in flow::child_iter(flow.get_mut()) {
|
|
||||||
had_descendants = true;
|
|
||||||
proxy.push(WorkUnit {
|
|
||||||
fun: compute_absolute_position,
|
|
||||||
data: borrowed_flow_to_unsafe_flow(kid),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there were no more descendants, start building the display list.
|
|
||||||
if !had_descendants {
|
|
||||||
build_display_list(mut_owned_flow_to_unsafe_flow(flow), proxy)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_display_list(mut unsafe_flow: UnsafeFlow,
|
|
||||||
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
|
|
||||||
let shared_layout_context = unsafe { &**proxy.user_data() };
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
let compute_absolute_positions_traversal = ComputeAbsolutePositions {
|
||||||
|
layout_context: &layout_context,
|
||||||
|
};
|
||||||
|
compute_absolute_positions_traversal.run_parallel(unsafe_flow, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
fn build_display_list(unsafe_flow: UnsafeFlow,
|
||||||
unsafe {
|
proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
|
||||||
// Get a real flow.
|
let shared_layout_context = unsafe { &**proxy.user_data() };
|
||||||
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
let build_display_list_traversal = BuildDisplayList {
|
||||||
// Build display lists.
|
layout_context: &layout_context,
|
||||||
flow.get_mut().build_display_list(&layout_context);
|
};
|
||||||
|
build_display_list_traversal.run_parallel(unsafe_flow, proxy);
|
||||||
{
|
|
||||||
let base = flow::mut_base(flow.get_mut());
|
|
||||||
|
|
||||||
// Reset the count of children for the next layout traversal.
|
|
||||||
base.parallel.children_count.store(base.children.len() as int, Relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Possibly enqueue the parent.
|
|
||||||
let unsafe_parent = flow::mut_base(flow.get_mut()).parallel.parent;
|
|
||||||
if unsafe_parent == null_unsafe_flow() {
|
|
||||||
// We're done!
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// No, we're not at the root yet. Then are we the last child
|
|
||||||
// of our parent to finish processing? If so, we can continue
|
|
||||||
// on with our parent; otherwise, we've gotta wait.
|
|
||||||
let parent: &mut FlowRef = mem::transmute(&unsafe_parent);
|
|
||||||
let parent_base = flow::mut_base(parent.get_mut());
|
|
||||||
if parent_base.parallel
|
|
||||||
.children_count
|
|
||||||
.fetch_sub(1, SeqCst) == 1 {
|
|
||||||
// We were the last child of our parent. Build display lists for our parent.
|
|
||||||
unsafe_flow = unsafe_parent
|
|
||||||
} else {
|
|
||||||
// Stop.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn traverse_dom_preorder(root: LayoutNode,
|
pub fn traverse_dom_preorder(root: LayoutNode,
|
||||||
|
@ -462,6 +425,12 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
|
||||||
time_profiler_chan: TimeProfilerChan,
|
time_profiler_chan: TimeProfilerChan,
|
||||||
shared_layout_context: &SharedLayoutContext,
|
shared_layout_context: &SharedLayoutContext,
|
||||||
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
|
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
|
||||||
|
if shared_layout_context.opts.bubble_inline_sizes_separately {
|
||||||
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
|
||||||
|
root.get_mut().traverse_postorder(&bubble_inline_sizes);
|
||||||
|
}
|
||||||
|
|
||||||
queue.data = shared_layout_context as *const _;
|
queue.data = shared_layout_context as *const _;
|
||||||
|
|
||||||
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
|
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
|
||||||
|
@ -487,7 +456,7 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
|
|
||||||
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
|
profile(time::LayoutParallelWarmupCategory, Some((url, iframe, first_reflow)), time_profiler_chan, || {
|
||||||
queue.push(WorkUnit {
|
queue.push(WorkUnit {
|
||||||
fun: compute_absolute_position,
|
fun: compute_absolute_positions,
|
||||||
data: mut_owned_flow_to_unsafe_flow(root),
|
data: mut_owned_flow_to_unsafe_flow(root),
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
89
components/layout/sequential.rs
Normal file
89
components/layout/sequential.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Implements sequential traversals over the DOM and flow trees.
|
||||||
|
|
||||||
|
use context::{LayoutContext, SharedLayoutContext};
|
||||||
|
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
||||||
|
use flow;
|
||||||
|
use flow_ref::FlowRef;
|
||||||
|
use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows};
|
||||||
|
use traversal::{AssignBSizesAndStoreOverflow, AssignISizes};
|
||||||
|
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
|
||||||
|
use wrapper::LayoutNode;
|
||||||
|
use wrapper::{PostorderNodeMutTraversal};
|
||||||
|
use wrapper::{PreorderDomTraversal, PostorderDomTraversal};
|
||||||
|
|
||||||
|
pub fn traverse_dom_preorder(root: LayoutNode,
|
||||||
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
|
fn doit(node: LayoutNode, recalc_style: RecalcStyleForNode, construct_flows: ConstructFlows) {
|
||||||
|
recalc_style.process(node);
|
||||||
|
|
||||||
|
for kid in node.children() {
|
||||||
|
doit(kid, recalc_style, construct_flows);
|
||||||
|
}
|
||||||
|
|
||||||
|
construct_flows.process(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
let recalc_style = RecalcStyleForNode { layout_context: &layout_context };
|
||||||
|
let construct_flows = ConstructFlows { layout_context: &layout_context };
|
||||||
|
|
||||||
|
doit(root, recalc_style, construct_flows);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
|
||||||
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
|
fn doit(flow: &mut Flow, assign_inline_sizes: AssignISizes, assign_block_sizes: AssignBSizesAndStoreOverflow) {
|
||||||
|
if assign_inline_sizes.should_process(flow) {
|
||||||
|
assign_inline_sizes.process(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
for kid in flow::child_iter(flow) {
|
||||||
|
doit(kid, assign_inline_sizes, assign_block_sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if assign_block_sizes.should_process(flow) {
|
||||||
|
assign_block_sizes.process(flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
|
||||||
|
let root = root.get_mut();
|
||||||
|
|
||||||
|
if layout_context.shared.opts.bubble_inline_sizes_separately {
|
||||||
|
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
|
||||||
|
root.traverse_postorder(&bubble_inline_sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
let assign_inline_sizes = AssignISizes { layout_context: &layout_context };
|
||||||
|
let assign_block_sizes = AssignBSizesAndStoreOverflow { layout_context: &layout_context };
|
||||||
|
|
||||||
|
doit(root, assign_inline_sizes, assign_block_sizes);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
|
shared_layout_context: &SharedLayoutContext) {
|
||||||
|
fn doit(flow: &mut Flow, compute_absolute_positions: ComputeAbsolutePositions, build_display_list: BuildDisplayList) {
|
||||||
|
if compute_absolute_positions.should_process(flow) {
|
||||||
|
compute_absolute_positions.process(flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
for kid in flow::mut_base(flow).child_iter() {
|
||||||
|
doit(kid, compute_absolute_positions, build_display_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
if build_display_list.should_process(flow) {
|
||||||
|
build_display_list.process(flow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let layout_context = LayoutContext::new(shared_layout_context);
|
||||||
|
let compute_absolute_positions = ComputeAbsolutePositions { layout_context: &layout_context };
|
||||||
|
let build_display_list = BuildDisplayList { layout_context: &layout_context };
|
||||||
|
|
||||||
|
doit(root.get_mut(), compute_absolute_positions, build_display_list);
|
||||||
|
}
|
|
@ -261,14 +261,13 @@ struct FlowTreeVerification;
|
||||||
#[cfg(debug)]
|
#[cfg(debug)]
|
||||||
impl PreorderFlow for FlowTreeVerification {
|
impl PreorderFlow for FlowTreeVerification {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&mut self, flow: &mut Flow) {
|
||||||
let base = flow::base(flow);
|
let base = flow::base(flow);
|
||||||
if !base.flags.is_leaf() && !base.flags.is_nonleaf() {
|
if !base.flags.is_leaf() && !base.flags.is_nonleaf() {
|
||||||
println("flow tree verification failed: flow wasn't a leaf or a nonleaf!");
|
println("flow tree verification failed: flow wasn't a leaf or a nonleaf!");
|
||||||
flow.dump();
|
flow.dump();
|
||||||
fail!("flow tree verification failed")
|
fail!("flow tree verification failed")
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,18 +279,9 @@ pub struct BubbleISizes<'a> {
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
|
impl<'a> PostorderFlowTraversal for BubbleISizes<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.bubble_inline_sizes();
|
flow.bubble_inline_sizes();
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We can't prune until we start reusing flows
|
|
||||||
/*
|
|
||||||
#[inline]
|
|
||||||
fn should_prune(&mut self, flow: &mut Flow) -> bool {
|
|
||||||
flow::mut_base(flow).restyle_damage.lacks(BubbleISizes)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
|
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
|
||||||
|
@ -301,9 +291,8 @@ pub struct AssignISizes<'a> {
|
||||||
|
|
||||||
impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
|
impl<'a> PreorderFlowTraversal for AssignISizes<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.assign_inline_sizes(self.layout_context);
|
flow.assign_inline_sizes(self.layout_context);
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,36 +306,39 @@ pub struct AssignBSizesAndStoreOverflow<'a> {
|
||||||
|
|
||||||
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
|
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process(&mut self, flow: &mut Flow) -> bool {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.assign_block_size(self.layout_context);
|
flow.assign_block_size(self.layout_context);
|
||||||
// Skip store-overflow for absolutely positioned flows. That will be
|
// Skip store-overflow for absolutely positioned flows. That will be
|
||||||
// done in a separate traversal.
|
// done in a separate traversal.
|
||||||
if !flow.is_store_overflow_delayed() {
|
if !flow.is_store_overflow_delayed() {
|
||||||
flow.store_overflow(self.layout_context);
|
flow.store_overflow(self.layout_context);
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn should_process(&mut self, flow: &mut Flow) -> bool {
|
fn should_process(&self, flow: &mut Flow) -> bool {
|
||||||
!flow::base(flow).flags.impacted_by_floats()
|
!flow::base(flow).flags.impacted_by_floats()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The display list construction traversal.
|
pub struct ComputeAbsolutePositions<'a> {
|
||||||
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PreorderFlowTraversal for ComputeAbsolutePositions<'a> {
|
||||||
|
#[inline]
|
||||||
|
fn process(&self, flow: &mut Flow) {
|
||||||
|
flow.compute_absolute_position()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct BuildDisplayList<'a> {
|
pub struct BuildDisplayList<'a> {
|
||||||
pub layout_context: &'a LayoutContext<'a>,
|
pub layout_context: &'a LayoutContext<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> BuildDisplayList<'a> {
|
impl<'a> PostorderFlowTraversal for BuildDisplayList<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn process(&mut self, flow: &mut Flow) {
|
fn process(&self, flow: &mut Flow) {
|
||||||
flow.compute_absolute_position();
|
|
||||||
|
|
||||||
for kid in flow::mut_base(flow).child_iter() {
|
|
||||||
self.process(kid)
|
|
||||||
}
|
|
||||||
|
|
||||||
flow.build_display_list(self.layout_context)
|
flow.build_display_list(self.layout_context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue