Split layout/base.rs into box.rs and flow.rs

This commit is contained in:
Brian J. Burg 2012-09-21 16:23:30 -07:00
parent b5e0cee1ab
commit c4338500b2
14 changed files with 267 additions and 243 deletions

View file

@ -5,7 +5,7 @@
use au = gfx::geometry;
use dom::node::{Node, NodeTree};
use dom::element::*;
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
use layout::box::{RenderBox, SpecifiedStyle, RenderBoxTree};
use layout::context::LayoutContext;
use layout::traverse_parallel::top_down_traversal;
use image::ImageHolder;

View file

@ -1,10 +1,10 @@
/* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */
use css::styles::SpecifiedStyle;
use css::values::Stylesheet;
use dom::bindings;
use dom::document::Document;
use dom::element::{Attr, ElementData};
use dom::window::Window;
use dom::bindings;
use geom::size::Size2D;
use gfx::geometry::au;
use js::crust::*;
@ -12,8 +12,8 @@ use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, jsval, JSBool};
use js::rust::{bare_compartment, compartment, methods};
use js::{JSPROP_ENUMERATE, JSPROP_SHARED};
use layout::base::FlowContext;
use layout::debug::DebugMethods;
use layout::flow::FlowContext;
use ptr::null;
use std::arc::ARC;
use util::tree;

View file

@ -5,8 +5,9 @@ use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use layout::base::{RenderBox, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use util::tree;
struct BlockFlowData {

View file

@ -17,11 +17,9 @@ use geom::rect::Rect;
use geom::size::Size2D;
use geom::point::Point2D;
use image::{Image, ImageHolder};
use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
use layout::inline::InlineFlowData;
use layout::root::RootFlowData;
use layout::flow::FlowContext;
use layout::text::TextBoxData;
use servo_text::text_run::TextRun;
use std::net::url::Url;
@ -30,12 +28,7 @@ use util::color::Color;
use util::tree;
use vec::{push, push_all};
/** Servo's experimental layout system builds a tree of FlowContexts
and RenderBoxes, and figures out positions and display attributes of
tree nodes. Positions are computed in several tree traversals driven
by fundamental data dependencies of inline and block layout.
/**
Render boxes (`struct RenderBox`) are the leafs of the layout
tree. They cannot position themselves. In general, render boxes do not
have a simple correspondence with CSS boxes as in the specification:
@ -65,149 +58,8 @@ padding, backgrounds. It is analogous to a CSS nonreplaced content box.
node. Split text boxes are implemented by referring to subsets of a
master TextRun object.
Flows (`struct FlowContext`) are interior nodes in the layout tree,
and correspond closely to flow contexts in the CSS
specification. Flows are responsible for positioning their child flow
contexts and render boxes. Flows have purpose-specific fields, such as
auxilliary line box structs, out-of-flow child lists, and so on.
Currently, the important types of flows are:
* BlockFlow: a flow that establishes a block context. It has several
child flows, each of which are positioned according to block
formatting context rules (as if child flows CSS block boxes). Block
flows also contain a single GenericBox to represent their rendered
borders, padding, etc. (In the future, this render box may be
folded into BlockFlow to save space.)
* InlineFlow: a flow that establishes an inline context. It has a
flat list of child boxes/flows that are subject to inline layout
and line breaking, and structs to represent line breaks and mapping
to CSS boxes, for the purpose of handling `getClientRects()`.
*/
struct FlowLayoutData {
// TODO: min/pref and position are used during disjoint phases of
// layout; maybe combine into a single enum to save space.
mut min_width: au,
mut pref_width: au,
mut position: Rect<au>,
}
fn FlowLayoutData() -> FlowLayoutData {
FlowLayoutData {
min_width: au(0),
pref_width: au(0),
position : au::zero_rect(),
}
}
/* The type of the formatting context, and data specific to each
context, such as linebox structures or float lists */
enum FlowContextData {
AbsoluteFlow,
BlockFlow(BlockFlowData),
FloatFlow,
InlineBlockFlow,
InlineFlow(InlineFlowData),
RootFlow(RootFlowData),
TableFlow
}
/* A particular kind of layout context. It manages the positioning of
render boxes within the context. */
struct FlowContext {
kind: FlowContextData,
data: FlowLayoutData,
mut node: Option<Node>,
/* reference to parent, children flow contexts */
tree: tree::Tree<@FlowContext>,
/* TODO: debug only */
mut id: int
}
fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
FlowContext {
kind: kind,
data: FlowLayoutData(),
node: None,
tree: tree,
id: id
}
}
impl @FlowContext : cmp::Eq {
pure fn eq(other: &@FlowContext) -> bool { box::ptr_eq(self, *other) }
pure fn ne(other: &@FlowContext) -> bool { !box::ptr_eq(self, *other) }
}
/* Flow context disambiguation methods: the verbose alternative to virtual methods */
impl @FlowContext {
fn bubble_widths(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.bubble_widths_block(ctx),
InlineFlow(*) => self.bubble_widths_inline(ctx),
RootFlow(*) => self.bubble_widths_root(ctx),
_ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
}
}
fn assign_widths(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.assign_widths_block(ctx),
InlineFlow(*) => self.assign_widths_inline(ctx),
RootFlow(*) => self.assign_widths_root(ctx),
_ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
}
}
fn assign_height(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.assign_height_block(ctx),
InlineFlow(*) => self.assign_height_inline(ctx),
RootFlow(*) => self.assign_height_root(ctx),
_ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
}
}
fn build_display_list_recurse(builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
offset: &Point2D<au>, list: &dl::DisplayList) {
match self.kind {
RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list),
InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list),
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self.kind)
}
}
}
/* The tree holding FlowContexts */
enum FlowTree { FlowTree }
impl FlowTree : tree::ReadMethods<@FlowContext> {
fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
tree::each_child(self, ctx, f)
}
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
f(b.tree)
}
}
impl FlowTree : tree::WriteMethods<@FlowContext> {
fn add_child(parent: @FlowContext, child: @FlowContext) {
assert !box::ptr_eq(parent, child);
tree::add_child(self, parent, child)
}
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
f(b.tree)
}
}
/* A box's kind influences how its styles are interpreted during
layout. For example, replaced content such as images are resized
@ -418,10 +270,11 @@ impl @RenderBox {
}
}
// FIXME: Why do these have to be redefined for each node type?
/* The tree holding render box relations. (This should only be used
for painting nested inlines, AFAIK-- everything else depends on Flow tree) */
/**
* The tree holding render box relations. These are only defined for
* nested CSS boxes that are nested in an otherwise inline flow
* context.
*/
enum RenderBoxTree { RenderBoxTree }
impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
@ -436,7 +289,7 @@ impl RenderBoxTree : tree::ReadMethods<@RenderBox> {
impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
fn add_child(parent: @RenderBox, child: @RenderBox) {
assert !box::ptr_eq(parent, child);
assert !core::box::ptr_eq(parent, child);
tree::add_child(self, parent, child)
}
@ -445,50 +298,6 @@ impl RenderBoxTree : tree::WriteMethods<@RenderBox> {
}
}
// Debugging
impl @FlowContext : DebugMethods {
fn dump() {
self.dump_indent(0u);
}
/** Dumps the flow tree, for debugging, with indentation. */
fn dump_indent(indent: uint) {
let mut s = ~"|";
for uint::range(0u, indent) |_i| {
s += ~"---- ";
}
s += self.debug_str();
debug!("%s", s);
for FlowTree.each_child(self) |child| {
child.dump_indent(indent + 1u)
}
}
/* TODO: we need a string builder. This is horribly inefficient */
fn debug_str() -> ~str {
let repr = match self.kind {
InlineFlow(d) => {
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
fmt!("%s %?", s, box.id)
});
s += ~")"; s
},
BlockFlow(d) => {
match d.box {
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
None => ~"BlockFlow",
}
},
_ => fmt!("%?", self.kind)
};
fmt!("c%? %?", self.id, repr)
}
}
impl @RenderBox : DebugMethods {
fn dump() {
self.dump_indent(0u);

View file

@ -7,17 +7,17 @@ use css::values::{Inherit, Initial, Specified};
use dom::element::*;
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
use image::holder::ImageHolder;
use layout::base::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
use layout::flow::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
use layout::box::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::inline::InlineFlowData;
use layout::root::RootFlowData;
use layout::text::TextBoxData;
use option::is_none;
use util::tree;
use servo_text::text_run::TextRun;
use servo_text::font_cache::FontCache;
use servo_text::text_run::TextRun;
use util::tree;
export LayoutTreeBuilder;

View file

@ -1,7 +1,7 @@
export DisplayListBuilder;
use au = gfx::geometry;
use base::{RenderBox, RenderBoxTree};
use au::au;
use css::values::{BgColor, BgColorTransparent, Specified};
use dl = gfx::display_list;
use dom::node::{Text, NodeScope};
@ -11,9 +11,10 @@ use either::{Left, Right};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use layout::box::{RenderBox, RenderBoxTree, TextBox};
use layout::context::LayoutContext;
use layout::flow::FlowContext;
use layout::text::TextBoxData;
use layout::base::{LayoutContext, FlowContext, TextBox};
use servo_text::text_run::TextRun;
use util::tree;
use vec::push;

206
src/servo/layout/flow.rs Normal file
View file

@ -0,0 +1,206 @@
use au = gfx::geometry;
use au::au;
use dl = gfx::display_list;
use dom::node::Node;
use geom::rect::Rect;
use geom::point::Point2D;
// TODO: pub-use these
use layout::block::BlockFlowData;
use layout::context::LayoutContext;
use layout::debug::DebugMethods;
use layout::inline::InlineFlowData;
use layout::root::RootFlowData;
use util::tree;
/** Servo's experimental layout system builds a tree of FlowContexts
and RenderBoxes, and figures out positions and display attributes of
tree nodes. Positions are computed in several tree traversals driven
by fundamental data dependencies of inline and block layout.
Flows are interior nodes in the layout tree, and correspond closely to
flow contexts in the CSS specification. Flows are responsible for
positioning their child flow contexts and render boxes. Flows have
purpose-specific fields, such as auxilliary line box structs,
out-of-flow child lists, and so on.
Currently, the important types of flows are:
* BlockFlow: a flow that establishes a block context. It has several
child flows, each of which are positioned according to block
formatting context rules (as if child flows CSS block boxes). Block
flows also contain a single GenericBox to represent their rendered
borders, padding, etc. (In the future, this render box may be
folded into BlockFlow to save space.)
* InlineFlow: a flow that establishes an inline context. It has a
flat list of child boxes/flows that are subject to inline layout
and line breaking, and structs to represent line breaks and mapping
to CSS boxes, for the purpose of handling `getClientRects()`.
*/
struct FlowLayoutData {
// TODO: min/pref and position are used during disjoint phases of
// layout; maybe combine into a single enum to save space.
mut min_width: au,
mut pref_width: au,
mut position: Rect<au>,
}
fn FlowLayoutData() -> FlowLayoutData {
FlowLayoutData {
min_width: au(0),
pref_width: au(0),
position : au::zero_rect(),
}
}
/* The type of the formatting context, and data specific to each
context, such as linebox structures or float lists */
enum FlowContextData {
AbsoluteFlow,
BlockFlow(BlockFlowData),
FloatFlow,
InlineBlockFlow,
InlineFlow(InlineFlowData),
RootFlow(RootFlowData),
TableFlow
}
/* A particular kind of layout context. It manages the positioning of
render boxes within the context. */
struct FlowContext {
kind: FlowContextData,
data: FlowLayoutData,
mut node: Option<Node>,
/* reference to parent, children flow contexts */
tree: tree::Tree<@FlowContext>,
/* TODO: debug only */
mut id: int
}
fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -> FlowContext {
FlowContext {
kind: kind,
data: FlowLayoutData(),
node: None,
tree: tree,
id: id
}
}
impl @FlowContext : cmp::Eq {
pure fn eq(other: &@FlowContext) -> bool { core::box::ptr_eq(self, *other) }
pure fn ne(other: &@FlowContext) -> bool { !core::box::ptr_eq(self, *other) }
}
/* Flow context disambiguation methods: the verbose alternative to virtual methods */
impl @FlowContext {
fn bubble_widths(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.bubble_widths_block(ctx),
InlineFlow(*) => self.bubble_widths_inline(ctx),
RootFlow(*) => self.bubble_widths_root(ctx),
_ => fail fmt!("Tried to bubble_widths of flow: %?", self.kind)
}
}
fn assign_widths(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.assign_widths_block(ctx),
InlineFlow(*) => self.assign_widths_inline(ctx),
RootFlow(*) => self.assign_widths_root(ctx),
_ => fail fmt!("Tried to assign_widths of flow: %?", self.kind)
}
}
fn assign_height(ctx: &LayoutContext) {
match self.kind {
BlockFlow(*) => self.assign_height_block(ctx),
InlineFlow(*) => self.assign_height_inline(ctx),
RootFlow(*) => self.assign_height_root(ctx),
_ => fail fmt!("Tried to assign_height of flow: %?", self.kind)
}
}
fn build_display_list_recurse(builder: &dl::DisplayListBuilder, dirty: &Rect<au>,
offset: &Point2D<au>, list: &dl::DisplayList) {
match self.kind {
RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list),
InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list),
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self.kind)
}
}
}
/* The tree holding FlowContexts */
enum FlowTree { FlowTree }
impl FlowTree : tree::ReadMethods<@FlowContext> {
fn each_child(ctx: @FlowContext, f: fn(&&@FlowContext) -> bool) {
tree::each_child(self, ctx, f)
}
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
f(b.tree)
}
}
impl FlowTree : tree::WriteMethods<@FlowContext> {
fn add_child(parent: @FlowContext, child: @FlowContext) {
assert !core::box::ptr_eq(parent, child);
tree::add_child(self, parent, child)
}
fn with_tree_fields<R>(&&b: @FlowContext, f: fn(tree::Tree<@FlowContext>) -> R) -> R {
f(b.tree)
}
}
impl @FlowContext : DebugMethods {
fn dump() {
self.dump_indent(0u);
}
/** Dumps the flow tree, for debugging, with indentation. */
fn dump_indent(indent: uint) {
let mut s = ~"|";
for uint::range(0u, indent) |_i| {
s += ~"---- ";
}
s += self.debug_str();
debug!("%s", s);
for FlowTree.each_child(self) |child| {
child.dump_indent(indent + 1u)
}
}
/* TODO: we need a string builder. This is horribly inefficient */
fn debug_str() -> ~str {
let repr = match self.kind {
InlineFlow(d) => {
let mut s = d.boxes.foldl(~"InlineFlow(children=", |s, box| {
fmt!("%s %?", s, box.id)
});
s += ~")"; s
},
BlockFlow(d) => {
match d.box {
Some(_b) => fmt!("BlockFlow(box=b%?)", d.box.get().id),
None => ~"BlockFlow",
}
},
_ => fmt!("%?", self.kind)
};
fmt!("c%? %?", self.id, repr)
}
}

View file

@ -1,5 +1,4 @@
use au = gfx::geometry;
use base::RenderBox;
use core::dvec::DVec;
use css::values::{BoxAuto, BoxLength, Px};
use dl = gfx::display_list;
@ -8,8 +7,9 @@ use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::geometry::au;
use layout::box::{RenderBox, RenderBoxTree, ImageBox, TextBox, GenericBox};
use layout::flow::{FlowContext, InlineFlow};
use layout::context::LayoutContext;
use layout::base::{FlowContext, InlineFlow, RenderBoxTree, ImageBox, TextBox, GenericBox};
use num::Num;
use util::tree;

View file

@ -1,7 +1,7 @@
#[doc = "
/**
The layout task. Performs layout on the DOM, builds display lists and sends them to be
rendered.
"];
*/
use au = gfx::geometry;
use au::au;
@ -10,20 +10,20 @@ use core::dvec::DVec;
use css::resolve::apply::apply_style;
use css::values::Stylesheet;
use dl = gfx::display_list;
use dom::node::{Node, LayoutData};
use dom::event::{Event, ReflowEvent};
use dom::node::{Node, LayoutData};
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::render_task;
use layout::base::RenderBox;
use layout::box::RenderBox;
use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext;
use render_task::RenderTask;
use resource::image_cache_task::ImageCacheTask;
use servo_text::font_cache::FontCache;
use std::arc::ARC;
use std::net::url::Url;
use servo_text::font_cache::FontCache;
use layout::traverse::*;
use comm::*;

View file

@ -4,8 +4,9 @@ use dl = gfx::display_list;
use geom::point::Point2D;
use geom::rect::Rect;
use gfx::geometry::au;
use layout::base::{RenderBox, FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::box::RenderBox;
use layout::context::LayoutContext;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use util::tree;
struct RootFlowData {

View file

@ -5,7 +5,7 @@ use geom::size::Size2D;
use gfx::geometry::au;
use servo_text::text_run::TextRun;
use servo_text::font_cache::FontCache;
use layout::base::{TextBox, RenderBox};
use layout::box::{TextBox, RenderBox};
use layout::context::LayoutContext;
struct TextBoxData {

View file

@ -1,7 +1,7 @@
/** Interface for running tree-based traversals over layout boxes and contextsg */
use layout::base::{RenderBox, RenderBoxTree};
use layout::base::{FlowContext, FlowTree};
use layout::box::{RenderBox, RenderBoxTree};
use layout::flow::{FlowContext, FlowTree};
/* TODO: we shouldn't need render box traversals */
trait RenderBoxTraversals {

View file

@ -1,6 +1,5 @@
#[doc = "Interface for running tree-based traversals over layout boxes"]
use base::{RenderBox, RenderBoxTree};
/* Interface for running tree-based traversals over layout boxes */
use layout::box::{RenderBox, RenderBoxTree};
use intrinsic::TyDesc;
export full_traversal;
@ -21,19 +20,23 @@ type shared_box<T> = {
payload : T
};
#[doc="Transform and @ into its underlying representation. The reference count stays constant."]
/**
Transform and @ into its underlying representation. The reference count stays constant.
*/
fn unwrap_box(-b : @RenderBox) -> *shared_box<RenderBox> unsafe {
let new_box : *shared_box<RenderBox> = cast::transmute(b);
return new_box;
}
#[doc="Transform an underlying representation back to an @. The reference count stays constant."]
/**
Transform an underlying representation back to an @. The reference count stays constant.
*/
fn rewrap_box(-b : *shared_box<RenderBox>) -> @RenderBox unsafe {
let new_box : @RenderBox = cast::transmute(b);
return new_box;
}
#[doc="
/**
Iterate down and then up a tree of layout boxes in parallel and apply
the given functions to each box. Each box applies the first function,
@ -52,7 +55,7 @@ finish, and then applies the second function to the current box.
* `bottom_up` - A function that is applied to each node after it is
applied to that node's children
"]
*/
fn traverse_helper<T : Copy Send>(-root : @RenderBox, returned : T, -top_down : fn~(+T, @RenderBox) -> T,
-bottom_up : fn~(@RenderBox)) {
let returned = top_down(returned, root);
@ -96,61 +99,63 @@ fn traverse_helper<T : Copy Send>(-root : @RenderBox, returned : T, -top_down :
bottom_up(root);
}
#[doc="A noneffectful function to be used if only one pass is required."]
/**
A noneffectful function to be used if only one pass is required.
*/
fn nop(_box : @RenderBox) {
return;
}
#[doc= "
/**
A wrapper to change a function that only acts on a box to one that
threasds a unit through to match travserse_helper
"]
*/
fn unit_wrapper(-fun : fn~(@RenderBox)) -> fn~(+(), @RenderBox) {
fn~(+_u : (), box : @RenderBox) { fun(box); }
}
#[doc="
/**
Iterate in parallel over the boxes in a tree, applying one function
to a parent before recursing on its children and one after.
"]
*/
fn full_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox), -bottom_up : fn~(@RenderBox)) {
traverse_helper(root, (), unit_wrapper(top_down), bottom_up);
}
#[doc="
/**
Iterate in parallel over the boxes in a tree, applying the given
function to a parent before its children.
"]
*/
fn top_down_traversal(+root : @RenderBox, -top_down : fn~(@RenderBox)) {
traverse_helper(root, (), unit_wrapper(top_down), nop);
}
#[doc="
/**
Iterate in parallel over the boxes in a tree, applying the given
function to a parent after its children.
"]
*/
fn bottom_up_traversal(+root : @RenderBox, -bottom_up : fn~(@RenderBox)) {
traverse_helper(root, (), unit_wrapper(nop), bottom_up);
}
#[doc="
/**
Iterate in parallel over the boxes in a tree, applying the given
function to a parent before its children, the value returned by the
function is passed to each child when they are recursed upon. As
the recursion unwinds, the second function is applied to first the
children in parallel, and then the parent.
"]
*/
fn extended_full_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
-top_down : fn~(+T, @RenderBox) -> T,
-bottom_up : fn~(@RenderBox)) {
traverse_helper(root, first_val, top_down, bottom_up);
}
#[doc="
/**
Iterate in parallel over the boxes in a tree, applying the given
function to a parent before its children, the value returned by the
function is passed to each child when they are recursed upon.
"]
*/
fn extended_top_down_traversal<T : Copy Send>(+root : @RenderBox, first_val : T,
-top_down : fn~(+T, @RenderBox) -> T) {
traverse_helper(root, first_val, top_down, nop);

View file

@ -58,14 +58,15 @@ mod css {
}
mod layout {
mod base;
mod block;
mod box;
mod box_builder;
mod context;
mod debug;
mod display_list_builder;
mod inline;
mod flow;
mod layout_task;
mod inline;
mod root;
mod text;
mod traverse;