aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/servo/layout/block.rs119
-rw-r--r--src/servo/layout/box_builder.rs33
-rw-r--r--src/servo/layout/flow.rs58
-rw-r--r--src/servo/layout/root.rs91
-rwxr-xr-xsrc/servo/servo.rc1
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;
}