Skip to content

Commit

Permalink
Merge RootFlow into BlockFlow
Browse files Browse the repository at this point in the history
  • Loading branch information
sethfowler committed May 11, 2013
1 parent b69a1e1 commit c0d8836
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 227 deletions.
119 changes: 54 additions & 65 deletions src/servo/layout/block.rs
Expand Up @@ -7,7 +7,7 @@
use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, RootFlow};
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow};
use layout::inline::InlineLayout;

use au = gfx::geometry;
Expand All @@ -23,61 +23,52 @@ pub struct BlockFlowData {
common: FlowData,

/// The associated render box.
box: Option<RenderBox>
box: Option<RenderBox>,

/// Whether this block flow is the root flow.
is_root: bool
}

impl BlockFlowData {
pub fn new(common: FlowData) -> BlockFlowData {
BlockFlowData {
common: common,
box: None,
is_root: false
}
}

pub fn new_root(common: FlowData) -> BlockFlowData {
BlockFlowData {
common: common,
box: None,
is_root: true
}
}
}

/// NB: These are part of FlowContext, not part of BlockFlowData, because the root flow calls these
/// as well. It is not clear to me whether this needs to be the case, or whether `RootFlow` can be
/// merged into this.
pub trait BlockLayout {
fn starts_root_flow(&self) -> bool;
fn starts_block_flow(&self) -> bool;
fn with_block_box(&self, &fn(box: RenderBox) -> ()) -> ();

fn bubble_widths_block(&self, ctx: &LayoutContext);
fn assign_widths_block(&self, ctx: &LayoutContext);
fn assign_height_block(&self, ctx: &LayoutContext);
fn build_display_list_block(&self,
a: &DisplayListBuilder,
b: &Rect<Au>,
c: &Point2D<Au>,
d: &Cell<DisplayList>);
}

impl BlockLayout for FlowContext {
fn starts_block_flow(&self) -> bool {
fn starts_root_flow(&self) -> bool {
match *self {
RootFlow(*) | BlockFlow(*) | InlineBlockFlow(*) => true,
_ => false
BlockFlow(info) => info.is_root,
_ => false
}
}

/// Get the current flow's corresponding block box, if it exists, and do something with it.
/// This works on both BlockFlow and RootFlow, since they are mostly the same.
fn with_block_box(&self, callback: &fn(box: RenderBox) -> ()) -> () {
fn starts_block_flow(&self) -> bool {
match *self {
BlockFlow(*) => {
for self.block().box.each |&b| {
callback(b);
}
},
RootFlow(*) => {
for self.root().box.each |&b| {
callback(b);
}
},
_ => fail!(fmt!("Tried to do something with_block_box(), but this is a %?", self))
BlockFlow(*) | InlineBlockFlow(*) => true,
_ => false
}
}
}

impl BlockFlowData {
/* Recursively (bottom-up) determine the context's preferred and
minimum widths. When called on this context, all child contexts
have had their min/pref widths set. This function must decide
Expand All @@ -87,14 +78,12 @@ impl BlockLayout for FlowContext {
/* TODO: floats */
/* TODO: absolute contexts */
/* TODO: inline-blocks */
fn bubble_widths_block(&self, ctx: &LayoutContext) {
assert!(self.starts_block_flow());

pub fn bubble_widths_block(@mut self, ctx: &LayoutContext) {
let mut min_width = Au(0);
let mut pref_width = Au(0);

/* find max width from child block contexts */
for self.each_child |child_ctx| {
for BlockFlow(self).each_child |child_ctx| {
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());

do child_ctx.with_imm_node |child_node| {
Expand All @@ -105,39 +94,40 @@ impl BlockLayout for FlowContext {

/* if not an anonymous block context, add in block box's widths.
these widths will not include child elements, just padding etc. */
do self.with_block_box |box| {
self.box.map(|&box| {
min_width = min_width.add(&box.get_min_width(ctx));
pref_width = pref_width.add(&box.get_pref_width(ctx));
}
});

do self.with_mut_node |this_node| {
this_node.min_width = min_width;
this_node.pref_width = pref_width;
}
self.common.min_width = min_width;
self.common.pref_width = pref_width;
}

/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
/// on this context, the context has had its width set by the parent context.
///
/// Dual boxes consume some width first, and the remainder is assigned to all child (block)
/// contexts.
fn assign_widths_block(&self, _: &LayoutContext) {
assert!(self.starts_block_flow());
pub fn assign_widths_block(@mut self, ctx: &LayoutContext) {
if self.is_root {
self.common.position.origin = Au::zero_point();
self.common.position.size.width = ctx.screen_size.size.width;
}

let mut remaining_width = self.with_imm_node(|this| this.position.size.width);
let mut remaining_width = self.common.position.size.width;
let left_used = Au(0);

// Let the box consume some width. It will return the amount remaining for its children.
do self.with_block_box |box| {
self.box.map(|&box| {
do box.with_mut_base |base| {
base.position.size.width = remaining_width;

let (left_used, right_used) = box.get_used_width();
remaining_width -= left_used.add(&right_used);
}
}
});

for self.each_child |kid| {
for BlockFlow(self).each_child |kid| {
assert!(kid.starts_block_flow() || kid.starts_inline_flow());

do kid.with_mut_node |child_node| {
Expand All @@ -147,51 +137,50 @@ impl BlockLayout for FlowContext {
}
}

fn assign_height_block(&self, _ctx: &LayoutContext) {
assert!(self.starts_block_flow());

pub fn assign_height_block(@mut self, ctx: &LayoutContext) {
let mut cur_y = Au(0);

for self.each_child |kid| {
for BlockFlow(self).each_child |kid| {
do kid.with_mut_node |child_node| {
child_node.position.origin.y = cur_y;
cur_y += child_node.position.size.height;
}
}

do self.with_mut_node |this_node| {
this_node.position.size.height = cur_y;
}
let height = if self.is_root { Au::max(ctx.screen_size.size.height, cur_y) }
else { cur_y };

self.common.position.size.height = height;

let _used_top = Au(0);
let _used_bot = Au(0);

do self.with_block_box |box| {
self.box.map(|&box| {
do box.with_mut_base |base| {
base.position.origin.y = Au(0);
base.position.size.height = cur_y;
base.position.size.height = height;
let (_used_top, _used_bot) = box.get_used_height();
}
}
});
}

fn build_display_list_block(&self,
pub fn build_display_list_block(@mut self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
offset: &Point2D<Au>,
list: &Cell<DisplayList>) {
assert!(self.starts_block_flow());

// add box that starts block context
do self.with_block_box |box| {
self.box.map(|&box| {
box.build_display_list(builder, dirty, offset, list)
}
});


// TODO: handle any out-of-flow elements

// go deeper into the flow tree
for self.each_child |child| {
self.build_display_list_for_child(builder, child, dirty, offset, list)
let flow = BlockFlow(self);
for flow.each_child |child| {
flow.build_display_list_for_child(builder, child, dirty, offset, list)
}
}
}
33 changes: 9 additions & 24 deletions src/servo/layout/box_builder.rs
Expand Up @@ -15,9 +15,8 @@ use layout::context::LayoutContext;
use layout::debug::{BoxedMutDebugMethods, DebugMethods};
use layout::flow::{AbsoluteFlow, BlockFlow, FloatFlow, Flow_Absolute, Flow_Block, Flow_Float};
use layout::flow::{Flow_Inline, Flow_InlineBlock, Flow_Root, Flow_Table, FlowContext};
use layout::flow::{FlowContextType, FlowData, InlineBlockFlow, InlineFlow, RootFlow, TableFlow};
use layout::flow::{FlowContextType, FlowData, InlineBlockFlow, InlineFlow, TableFlow};
use layout::inline::{InlineFlowData, InlineLayout};
use layout::root::RootFlowData;

use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock};
use newcss::values::{CSSDisplayNone};
Expand Down Expand Up @@ -153,18 +152,6 @@ impl BoxGenerator {
assert!(block.box.is_none());
block.box = Some(new_box);
},
RootFlow(root) => {
debug!("BoxGenerator[f%d]: point c", root.common.id);
let new_box = builder.make_box(ctx, box_type, node, self.flow);
debug!("BoxGenerator[f%d]: (node is: %s)", root.common.id, node.debug_str());
debug!("BoxGenerator[f%d]: attaching box[b%d] to root flow (node: %s)",
root.common.id,
new_box.id(),
node.debug_str());

assert!(root.box.is_none());
root.box = Some(new_box);
},
_ => warn!("push_node() not implemented for flow f%d", self.flow.id()),
}
}
Expand Down Expand Up @@ -195,7 +182,7 @@ impl BoxGenerator {
debug!("BoxGenerator: adding element range=%?", node_range);
inline.elems.add_mapping(node, &node_range);
},
BlockFlow(*) | RootFlow(*) => assert!(self.range_stack.len() == 0),
BlockFlow(*) => assert!(self.range_stack.len() == 0),
_ => warn!("pop_node() not implemented for flow %?", self.flow.id()),
}
}
Expand Down Expand Up @@ -279,18 +266,16 @@ impl BuilderContext {
};

let containing_context = match (simulated_display, self.default_collector.flow) {
(CSSDisplayBlock, RootFlow(*)) => {
(CSSDisplayBlock, BlockFlow(info)) => match (info.is_root, node.parent_node()) {
// If this is the root node, then use the root flow's
// context. Otherwise, make a child block context.
match node.parent_node() {
Some(_) => { self.create_child_flow_of_type(Flow_Block, builder, node) }
None => { self.clone() },
(true, Some(_)) => { self.create_child_flow_of_type(Flow_Block, builder, node) }
(true, None) => { self.clone() }
(false, _) => {
self.clear_inline_collector();
self.create_child_flow_of_type(Flow_Block, builder, node)
}
},
(CSSDisplayBlock, BlockFlow(*)) => {
self.clear_inline_collector();
self.create_child_flow_of_type(Flow_Block, builder, node)
},
(CSSDisplayInline, InlineFlow(*)) => self.clone(),
(CSSDisplayInlineBlock, InlineFlow(*)) => self.clone(),
(CSSDisplayInline, BlockFlow(*)) => self.get_inline_collector(builder, node),
Expand Down Expand Up @@ -453,7 +438,7 @@ pub impl LayoutTreeBuilder {
Flow_Float => FloatFlow(@mut info),
Flow_InlineBlock => InlineBlockFlow(@mut info),
Flow_Inline => InlineFlow(@mut InlineFlowData::new(info)),
Flow_Root => RootFlow(@mut RootFlowData::new(info)),
Flow_Root => BlockFlow(@mut BlockFlowData::new_root(info)),
Flow_Table => TableFlow(@mut info),
};
debug!("LayoutTreeBuilder: created flow: %s", result.debug_str());
Expand Down

0 comments on commit c0d8836

Please sign in to comment.