diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2012-05-17 12:27:11 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2012-05-17 14:14:37 -0700 |
commit | dccee997e872d79ce08642a36566a9c2505f8e58 (patch) | |
tree | f80f95d4768ea59eed54b90be2baafd33b1e9f3e /src | |
parent | 1cab10d8ba0cc92b8b18ea2680dc364a02b61664 (diff) | |
download | servo-dccee997e872d79ce08642a36566a9c2505f8e58.tar.gz servo-dccee997e872d79ce08642a36566a9c2505f8e58.zip |
Implement toy inline layout
Diffstat (limited to 'src')
-rw-r--r-- | src/servo/dom/base.rs | 1 | ||||
-rw-r--r-- | src/servo/dom/rcu.rs | 3 | ||||
-rw-r--r-- | src/servo/layout/base.rs | 46 | ||||
-rw-r--r-- | src/servo/layout/box_builder.rs | 120 | ||||
-rw-r--r-- | src/servo/layout/layout.rs | 11 | ||||
-rw-r--r-- | src/servo/layout/style/style.rs | 7 |
6 files changed, 169 insertions, 19 deletions
diff --git a/src/servo/dom/base.rs b/src/servo/dom/base.rs index 16eddd5ffdf..73379023706 100644 --- a/src/servo/dom/base.rs +++ b/src/servo/dom/base.rs @@ -52,3 +52,4 @@ impl of tree::wr_tree_ops<node> for node_scope { self.wr(node) { |n| f(n.tree) } } } + diff --git a/src/servo/dom/rcu.rs b/src/servo/dom/rcu.rs index df78116506b..9c043899167 100644 --- a/src/servo/dom/rcu.rs +++ b/src/servo/dom/rcu.rs @@ -52,6 +52,9 @@ impl reader_methods<T:send,A> for handle<T,A> { } fn set_aux(p: @A) unsafe { + let p2 = p; + unsafe::forget(p2); // Bump the reference count. + (**self).rd_aux = ptr::addr_of(*p); } diff --git a/src/servo/layout/base.rs b/src/servo/layout/base.rs index 0a25568ae7c..5ce07de2dda 100644 --- a/src/servo/layout/base.rs +++ b/src/servo/layout/base.rs @@ -61,6 +61,22 @@ impl of tree::wr_tree_ops<@box> for btree { } } +impl layout_methods_priv for @box { + #[doc="Dumps the box tree, for debugging, with indentation."] + fn dump_indent(indent: uint) { + let mut s = ""; + uint::range(0u, indent) { + |_i| + s += " "; + } + + s += #fmt("%?", self.kind); + #debug["%s", s]; + + for btree.each_child(self) { |kid| kid.dump_indent(indent + 1u) } + } +} + impl layout_methods for @box { #[doc="The main reflow routine."] fn reflow(available_width: au) { @@ -77,6 +93,36 @@ impl layout_methods for @box { #debug["reflow_intrinsic size=%?", self.bounds]; } + + #[doc="Dumps the box tree, for debugging."] + fn dump() { + self.dump_indent(0u); + } +} + +// Debugging + +impl node_methods_priv for node { + #[doc="Dumps the node tree, for debugging, with indentation."] + fn dump_indent(indent: uint) { + let mut s = ""; + uint::range(0u, indent) { + |_i| + s += " "; + } + + s += #fmt("%?", self.rd({ |n| n.kind })); + #debug["%s", s]; + + for ntree.each_child(self) { |kid| kid.dump_indent(indent + 1u) } + } +} + +impl node_methods for node { + #[doc="Dumps the subtree rooted at this node, for debugging."] + fn dump() { + self.dump_indent(0u); + } } #[cfg(test)] diff --git a/src/servo/layout/box_builder.rs b/src/servo/layout/box_builder.rs index 5efb1bc3c01..412eea8003f 100644 --- a/src/servo/layout/box_builder.rs +++ b/src/servo/layout/box_builder.rs @@ -3,13 +3,27 @@ import dom::base::{nk_div, nk_img, node}; import dom::rcu::reader_methods; import gfx::geom; -import /*layout::*/base::{bk_block, bk_intrinsic, box, box_kind, btree, ntree}; -import /*layout::*/base::{rd_tree_ops, wr_tree_ops}; -import /*layout::*/style::style::{di_block, di_inline}; +import /*layout::*/base::{bk_block, bk_inline, bk_intrinsic, box, box_kind}; +import /*layout::*/base::{btree, node_methods, ntree, rd_tree_ops}; +import /*layout::*/base::wr_tree_ops; +import /*layout::*/style::style::{di_block, di_inline, style_methods}; import util::tree; export box_builder_methods; +enum ctxt = { + // The parent node that we're scanning. + parent_node: node, + // The parent box that these boxes will be added to. + parent_box: @box, + + // The current anonymous box that we're currently appending inline nodes + // to. + // + // See CSS2 9.2.1.1. + mut anon_box: option<@box> +}; + fn new_box(n: node, kind: box_kind) -> @box { @box({tree: tree::empty(), node: n, @@ -17,14 +31,88 @@ fn new_box(n: node, kind: box_kind) -> @box { kind: kind }) } -impl box_builder_priv_methods for node { - fn construct_boxes() -> @box { - let b = new_box(self, self.determine_box_kind()); - self.aux::<()>({ |a| a.box = some(b); }); - ret b; +fn create_context(parent_node: node, parent_box: @box) -> ctxt { + ret ctxt({ + parent_node: parent_node, + parent_box: parent_box, + mut anon_box: none + }); +} + +impl methods for ctxt { + #[doc=" + Constructs boxes for the parent's children, when the parent's 'display' + attribute is 'block'. + "] + fn construct_boxes_for_block_children() { + for ntree.each_child(self.parent_node) { + |kid| + + // Create boxes for the child. Get its primary box. + let kid_box = kid.construct_boxes(); + + // Determine the child's display. + let disp = kid.get_computed_style().display; + if disp != di_inline { + self.finish_anonymous_box_if_necessary(); + } + + // Add the child's box to the current enclosing box or the current + // anonymous box. + alt kid.get_computed_style().display { + di_block { btree.add_child(self.parent_box, kid_box); } + di_inline { + let anon_box = alt self.anon_box { + none { + let b = new_box(kid, bk_inline); + self.anon_box = some(b); + b + } + some(b) { b } + }; + btree.add_child(anon_box, kid_box); + } + } + } } #[doc=" + Constructs boxes for the parent's children, when the parent's 'display' + attribute is 'inline'. + "] + fn construct_boxes_for_inline_children() { + // TODO + } + + #[doc="Constructs boxes for the parent's children."] + fn construct_boxes_for_children() { + #debug("parent node:"); + self.parent_node.dump(); + + alt self.parent_node.get_computed_style().display { + di_block { self.construct_boxes_for_block_children(); } + di_inline { self.construct_boxes_for_inline_children(); } + } + + self.finish_anonymous_box_if_necessary(); + assert self.anon_box.is_none(); + } + + #[doc=" + Flushes the anonymous box we're creating if it exists. This appends the + anonymous box to the block. + "] + fn finish_anonymous_box_if_necessary() { + alt self.anon_box { + none { /* Nothing to do. */ } + some(b) { btree.add_child(self.parent_box, b); } + } + self.anon_box = none; + } +} + +impl box_builder_priv for node { + #[doc=" Determines the kind of box that this node needs. Also, for images, computes the intrinsic size. "] @@ -37,15 +125,15 @@ impl box_builder_priv_methods for node { } impl box_builder_methods for node { - #[doc="Creates boxes for a subtree. This is the entry point."] - fn construct_boxes_for_subtree() -> @box { - let p_box = self.construct_boxes(); - for ntree.each_child(self) { - |c| - let c_box = c.construct_boxes_for_subtree(); - btree.add_child(p_box, c_box); + #[doc="Creates boxes for this node. This is the entry point."] + fn construct_boxes() -> @box { + let box_kind = self.determine_box_kind(); + let my_box = new_box(self, box_kind); + if box_kind == bk_block { + let cx = create_context(self, my_box); + cx.construct_boxes_for_children(); } - ret p_box; + ret my_box; } } diff --git a/src/servo/layout/layout.rs b/src/servo/layout/layout.rs index 93c562a6a6e..36d2dbb3d09 100644 --- a/src/servo/layout/layout.rs +++ b/src/servo/layout/layout.rs @@ -11,8 +11,8 @@ import gfx::geom; import gfx::renderer; import dom::base::node; import dom::rcu::scope; +import /*layout::*/base::*; import /*layout::*/style::style::style_methods; -import base::*; import box_builder::box_builder_methods; import dl = display_list; @@ -29,9 +29,14 @@ fn layout(to_renderer: chan<renderer::msg>) -> chan<msg> { ping(ch) { ch.send(content::pong); } exit { break; } build(node) { - #debug("layout: received layout request"); + #debug("layout: received layout request for:"); + node.dump(); + node.recompute_style_for_subtree(); - let this_box = node.construct_boxes_for_subtree(); + + let this_box = node.construct_boxes(); + this_box.dump(); + this_box.reflow(geom::px_to_au(800)); let dlist = build_display_list(this_box); to_renderer.send(renderer::render(dlist)); diff --git a/src/servo/layout/style/style.rs b/src/servo/layout/style/style.rs index 448f8370725..fd6dd261c67 100644 --- a/src/servo/layout/style/style.rs +++ b/src/servo/layout/style/style.rs @@ -32,10 +32,17 @@ impl style_priv for node { fn recompute_style() { let default_style: computed_style = default_style_for_node_kind(self.rd { |n| n.kind }); + + #debug("recomputing style; parent node:"); + self.dump(); + let the_layout_data = @layout_data({ mut computed_style: default_style, mut box: none }); + + #debug("layout data: %?", the_layout_data); + self.set_aux(the_layout_data); } } |