diff options
-rw-r--r-- | src/servo/layout/block.rs | 119 | ||||
-rw-r--r-- | src/servo/layout/box_builder.rs | 33 | ||||
-rw-r--r-- | src/servo/layout/flow.rs | 58 | ||||
-rw-r--r-- | src/servo/layout/root.rs | 91 | ||||
-rwxr-xr-x | src/servo/servo.rc | 1 |
5 files changed, 75 insertions, 227 deletions
diff --git a/src/servo/layout/block.rs b/src/servo/layout/block.rs index 20df5912808..90d8e1b2870 100644 --- a/src/servo/layout/block.rs +++ b/src/servo/layout/block.rs @@ -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; @@ -23,7 +23,10 @@ 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 { @@ -31,53 +34,41 @@ impl 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 @@ -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| { @@ -105,15 +94,13 @@ 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 @@ -121,23 +108,26 @@ impl BlockLayout for FlowContext { /// /// 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| { @@ -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) } } } diff --git a/src/servo/layout/box_builder.rs b/src/servo/layout/box_builder.rs index 079231bc7ba..c7d49d92d32 100644 --- a/src/servo/layout/box_builder.rs +++ b/src/servo/layout/box_builder.rs @@ -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}; @@ -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()), } } @@ -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()), } } @@ -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), @@ -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()); diff --git a/src/servo/layout/flow.rs b/src/servo/layout/flow.rs index 117d48b7ed5..b832219d080 100644 --- a/src/servo/layout/flow.rs +++ b/src/servo/layout/flow.rs @@ -17,24 +17,21 @@ /// * `BlockFlow`: A flow that establishes a block context. It has several child flows, each of /// which are positioned according to block formatting context rules (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.) -/// +/// (In the future, this render box may be folded into `BlockFlow` to save space.) The BlockFlow +/// at the root of the tree has special behavior: it stretches to the boundaries of the viewport. +/// /// * `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()` and /// similar methods. -/// -/// * `RootFlow`: The flow at the root of the tree. This flow behaves like a `BlockFlow`, except -/// that stretches to the boundaries of the viewport. use dom::node::AbstractNode; -use layout::block::{BlockFlowData, BlockLayout}; +use layout::block::{BlockFlowData}; use layout::box::RenderBox; use layout::context::LayoutContext; use layout::debug::DebugMethods; use layout::display_list_builder::DisplayListBuilder; use layout::inline::{InlineFlowData}; -use layout::root::{RootFlowData}; use core::cell::Cell; use geom::point::Point2D; @@ -51,7 +48,6 @@ pub enum FlowContext { FloatFlow(@mut FlowData), InlineBlockFlow(@mut FlowData), InlineFlow(@mut InlineFlowData), - RootFlow(@mut RootFlowData), TableFlow(@mut FlowData), } @@ -83,10 +79,7 @@ impl TreeNodeRef<FlowData> for FlowContext { InlineFlow(info) => { callback(&info.common) } - RootFlow(info) => { - callback(&info.common) - } - TableFlow(info) => callback(info), + TableFlow(info) => callback(info) } } fn with_mut_node<R>(&self, callback: &fn(&mut FlowData) -> R) -> R { @@ -100,9 +93,6 @@ impl TreeNodeRef<FlowData> for FlowContext { InlineFlow(info) => { callback(&mut info.common) } - RootFlow(info) => { - callback(&mut info.common) - } TableFlow(info) => callback(info), } } @@ -227,36 +217,33 @@ impl<'self> FlowContext { } } - pub fn root(&self) -> @mut RootFlowData { + pub fn root(&self) -> @mut BlockFlowData { match *self { - RootFlow(info) => info, - _ => fail!(fmt!("Tried to access root data of non-root: f%d", self.id())) + BlockFlow(info) if info.is_root => info, + _ => fail!(fmt!("Tried to access root block data of non-root: f%d", self.id())) } } pub fn bubble_widths(&self, ctx: &mut LayoutContext) { match *self { - BlockFlow(*) => self.bubble_widths_block(ctx), + BlockFlow(info) => info.bubble_widths_block(ctx), InlineFlow(info) => info.bubble_widths_inline(ctx), - RootFlow(info) => info.bubble_widths_root(ctx), _ => fail!(fmt!("Tried to bubble_widths of flow: f%d", self.id())) } } pub fn assign_widths(&self, ctx: &mut LayoutContext) { match *self { - BlockFlow(*) => self.assign_widths_block(ctx), + BlockFlow(info) => info.assign_widths_block(ctx), InlineFlow(info) => info.assign_widths_inline(ctx), - RootFlow(info) => info.assign_widths_root(ctx), _ => fail!(fmt!("Tried to assign_widths of flow: f%d", self.id())) } } pub fn assign_height(&self, ctx: &mut LayoutContext) { match *self { - BlockFlow(*) => self.assign_height_block(ctx), + BlockFlow(info) => info.assign_height_block(ctx), InlineFlow(info) => info.assign_height_inline(ctx), - RootFlow(info) => info.assign_height_root(ctx), _ => fail!(fmt!("Tried to assign_height of flow: f%d", self.id())) } } @@ -271,8 +258,7 @@ impl<'self> FlowContext { } match *self { - RootFlow(info) => info.build_display_list_root(builder, dirty, offset, list), - BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list), + BlockFlow(info) => info.build_display_list_block(builder, dirty, offset, list), InlineFlow(info) => info.build_display_list_inline(builder, dirty, offset, list), _ => fail!(fmt!("Tried to build_display_list_recurse of flow: %?", self)) } @@ -281,12 +267,6 @@ impl<'self> FlowContext { // Actual methods that do not require much flow-specific logic pub fn foldl_all_boxes<B:Copy>(&self, seed: B, cb: &fn(a: B, b: RenderBox) -> B) -> B { match *self { - RootFlow(root) => { - let root = &mut *root; - do root.box.map_default(seed) |box| { - cb(seed, *box) - } - } BlockFlow(block) => { let block = &mut *block; do block.box.map_default(seed) |box| { @@ -319,14 +299,6 @@ impl<'self> FlowContext { pub fn iter_all_boxes(&self, cb: &fn(RenderBox) -> bool) { match *self { - RootFlow(root) => { - let root = &mut *root; - for root.box.each |box| { - if !cb(*box) { - break; - } - } - } BlockFlow(block) => { let block = &mut *block; for block.box.each |box| { @@ -394,12 +366,6 @@ impl DebugMethods for FlowContext { None => ~"BlockFlow", } }, - RootFlow(root) => { - match root.box { - Some(box) => fmt!("RootFlow(box=b%d)", box.id()), - None => ~"RootFlow", - } - }, _ => ~"(Unknown flow)" }; diff --git a/src/servo/layout/root.rs b/src/servo/layout/root.rs deleted file mode 100644 index 1e33894621d..00000000000 --- a/src/servo/layout/root.rs +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/. */ - -use core::cell::Cell; -use geom::point::Point2D; -use geom::rect::Rect; -use gfx::display_list::DisplayList; -use gfx::geometry::Au; -use layout::block::BlockLayout; -use layout::box::RenderBox; -use layout::context::LayoutContext; -use layout::flow::{FlowContext, FlowData, RootFlow}; -use layout::display_list_builder::DisplayListBuilder; - -use servo_util::tree::{TreeNodeRef, TreeUtils}; - -pub struct RootFlowData { - /// Data common to all flows. - common: FlowData, - - /// The render box at the root of the tree. - box: Option<RenderBox> -} - -impl RootFlowData { - pub fn new(common: FlowData) -> RootFlowData { - RootFlowData { - common: common, - box: None, - } - } -} - -pub trait RootLayout { - fn starts_root_flow(&self) -> bool; -} - -impl RootLayout for FlowContext { - fn starts_root_flow(&self) -> bool { - match *self { - RootFlow(*) => true, - _ => false - } - } -} - -impl RootFlowData { - /// Defer to the block algorithm. - pub fn bubble_widths_root(@mut self, ctx: &LayoutContext) { - RootFlow(self).bubble_widths_block(ctx) - } - - pub fn assign_widths_root(@mut self, ctx: &LayoutContext) { - self.common.position.origin = Au::zero_point(); - self.common.position.size.width = ctx.screen_size.size.width; - - RootFlow(self).assign_widths_block(ctx) - } - - pub fn assign_height_root(@mut self, ctx: &LayoutContext) { - // this is essentially the same as assign_height_block(), except - // the root adjusts self height to at least cover the viewport. - let mut cur_y = Au(0); - - for RootFlow(self).each_child |child_flow| { - do child_flow.with_mut_node |child_node| { - child_node.position.origin.y = cur_y; - cur_y += child_node.position.size.height; - } - } - - self.common.position.size.height = Au::max(ctx.screen_size.size.height, cur_y); - - do RootFlow(self).with_block_box |box| { - do box.with_mut_base |base| { - base.position.origin.y = Au(0); - base.position.size.height = Au::max(ctx.screen_size.size.height, cur_y); - let (_used_top, _used_bot) = box.get_used_height(); - } - } - } - - pub fn build_display_list_root(@mut self, - builder: &DisplayListBuilder, - dirty: &Rect<Au>, - offset: &Point2D<Au>, - list: &Cell<DisplayList>) { - RootFlow(self).build_display_list_block(builder, dirty, offset, list); - } -} diff --git a/src/servo/servo.rc b/src/servo/servo.rc index b9435467379..51b83b6a76a 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -111,7 +111,6 @@ pub mod layout { pub mod flow; pub mod layout_task; pub mod inline; - pub mod root; pub mod text; mod aux; } |