aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-05-17 12:27:11 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-05-17 14:14:37 -0700
commitdccee997e872d79ce08642a36566a9c2505f8e58 (patch)
treef80f95d4768ea59eed54b90be2baafd33b1e9f3e /src
parent1cab10d8ba0cc92b8b18ea2680dc364a02b61664 (diff)
downloadservo-dccee997e872d79ce08642a36566a9c2505f8e58.tar.gz
servo-dccee997e872d79ce08642a36566a9c2505f8e58.zip
Implement toy inline layout
Diffstat (limited to 'src')
-rw-r--r--src/servo/dom/base.rs1
-rw-r--r--src/servo/dom/rcu.rs3
-rw-r--r--src/servo/layout/base.rs46
-rw-r--r--src/servo/layout/box_builder.rs120
-rw-r--r--src/servo/layout/layout.rs11
-rw-r--r--src/servo/layout/style/style.rs7
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);
}
}