mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Implement toy inline layout
This commit is contained in:
parent
1cab10d8ba
commit
dccee997e8
7 changed files with 175 additions and 19 deletions
|
@ -52,3 +52,4 @@ impl of tree::wr_tree_ops<node> for node_scope {
|
||||||
self.wr(node) { |n| f(n.tree) }
|
self.wr(node) { |n| f(n.tree) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,9 @@ impl reader_methods<T:send,A> for handle<T,A> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_aux(p: @A) unsafe {
|
fn set_aux(p: @A) unsafe {
|
||||||
|
let p2 = p;
|
||||||
|
unsafe::forget(p2); // Bump the reference count.
|
||||||
|
|
||||||
(**self).rd_aux = ptr::addr_of(*p);
|
(**self).rd_aux = ptr::addr_of(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
impl layout_methods for @box {
|
||||||
#[doc="The main reflow routine."]
|
#[doc="The main reflow routine."]
|
||||||
fn reflow(available_width: au) {
|
fn reflow(available_width: au) {
|
||||||
|
@ -77,6 +93,36 @@ impl layout_methods for @box {
|
||||||
|
|
||||||
#debug["reflow_intrinsic size=%?", self.bounds];
|
#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)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -3,13 +3,27 @@
|
||||||
import dom::base::{nk_div, nk_img, node};
|
import dom::base::{nk_div, nk_img, node};
|
||||||
import dom::rcu::reader_methods;
|
import dom::rcu::reader_methods;
|
||||||
import gfx::geom;
|
import gfx::geom;
|
||||||
import /*layout::*/base::{bk_block, bk_intrinsic, box, box_kind, btree, ntree};
|
import /*layout::*/base::{bk_block, bk_inline, bk_intrinsic, box, box_kind};
|
||||||
import /*layout::*/base::{rd_tree_ops, wr_tree_ops};
|
import /*layout::*/base::{btree, node_methods, ntree, rd_tree_ops};
|
||||||
import /*layout::*/style::style::{di_block, di_inline};
|
import /*layout::*/base::wr_tree_ops;
|
||||||
|
import /*layout::*/style::style::{di_block, di_inline, style_methods};
|
||||||
import util::tree;
|
import util::tree;
|
||||||
|
|
||||||
export box_builder_methods;
|
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 {
|
fn new_box(n: node, kind: box_kind) -> @box {
|
||||||
@box({tree: tree::empty(),
|
@box({tree: tree::empty(),
|
||||||
node: n,
|
node: n,
|
||||||
|
@ -17,13 +31,87 @@ fn new_box(n: node, kind: box_kind) -> @box {
|
||||||
kind: kind })
|
kind: kind })
|
||||||
}
|
}
|
||||||
|
|
||||||
impl box_builder_priv_methods for node {
|
fn create_context(parent_node: node, parent_box: @box) -> ctxt {
|
||||||
fn construct_boxes() -> @box {
|
ret ctxt({
|
||||||
let b = new_box(self, self.determine_box_kind());
|
parent_node: parent_node,
|
||||||
self.aux::<()>({ |a| a.box = some(b); });
|
parent_box: parent_box,
|
||||||
ret b;
|
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="
|
#[doc="
|
||||||
Determines the kind of box that this node needs. Also, for images,
|
Determines the kind of box that this node needs. Also, for images,
|
||||||
computes the intrinsic size.
|
computes the intrinsic size.
|
||||||
|
@ -37,15 +125,15 @@ impl box_builder_priv_methods for node {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl box_builder_methods for node {
|
impl box_builder_methods for node {
|
||||||
#[doc="Creates boxes for a subtree. This is the entry point."]
|
#[doc="Creates boxes for this node. This is the entry point."]
|
||||||
fn construct_boxes_for_subtree() -> @box {
|
fn construct_boxes() -> @box {
|
||||||
let p_box = self.construct_boxes();
|
let box_kind = self.determine_box_kind();
|
||||||
for ntree.each_child(self) {
|
let my_box = new_box(self, box_kind);
|
||||||
|c|
|
if box_kind == bk_block {
|
||||||
let c_box = c.construct_boxes_for_subtree();
|
let cx = create_context(self, my_box);
|
||||||
btree.add_child(p_box, c_box);
|
cx.construct_boxes_for_children();
|
||||||
}
|
}
|
||||||
ret p_box;
|
ret my_box;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ import gfx::geom;
|
||||||
import gfx::renderer;
|
import gfx::renderer;
|
||||||
import dom::base::node;
|
import dom::base::node;
|
||||||
import dom::rcu::scope;
|
import dom::rcu::scope;
|
||||||
|
import /*layout::*/base::*;
|
||||||
import /*layout::*/style::style::style_methods;
|
import /*layout::*/style::style::style_methods;
|
||||||
import base::*;
|
|
||||||
import box_builder::box_builder_methods;
|
import box_builder::box_builder_methods;
|
||||||
import dl = display_list;
|
import dl = display_list;
|
||||||
|
|
||||||
|
@ -29,9 +29,14 @@ fn layout(to_renderer: chan<renderer::msg>) -> chan<msg> {
|
||||||
ping(ch) { ch.send(content::pong); }
|
ping(ch) { ch.send(content::pong); }
|
||||||
exit { break; }
|
exit { break; }
|
||||||
build(node) {
|
build(node) {
|
||||||
#debug("layout: received layout request");
|
#debug("layout: received layout request for:");
|
||||||
|
node.dump();
|
||||||
|
|
||||||
node.recompute_style_for_subtree();
|
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));
|
this_box.reflow(geom::px_to_au(800));
|
||||||
let dlist = build_display_list(this_box);
|
let dlist = build_display_list(this_box);
|
||||||
to_renderer.send(renderer::render(dlist));
|
to_renderer.send(renderer::render(dlist));
|
||||||
|
|
|
@ -32,10 +32,17 @@ impl style_priv for node {
|
||||||
fn recompute_style() {
|
fn recompute_style() {
|
||||||
let default_style: computed_style =
|
let default_style: computed_style =
|
||||||
default_style_for_node_kind(self.rd { |n| n.kind });
|
default_style_for_node_kind(self.rd { |n| n.kind });
|
||||||
|
|
||||||
|
#debug("recomputing style; parent node:");
|
||||||
|
self.dump();
|
||||||
|
|
||||||
let the_layout_data = @layout_data({
|
let the_layout_data = @layout_data({
|
||||||
mut computed_style: default_style,
|
mut computed_style: default_style,
|
||||||
mut box: none
|
mut box: none
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#debug("layout data: %?", the_layout_data);
|
||||||
|
|
||||||
self.set_aux(the_layout_data);
|
self.set_aux(the_layout_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
6
test-inline.html
Normal file
6
test-inline.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div>
|
||||||
|
<img></img>
|
||||||
|
<div>
|
||||||
|
<img></img><img></img><img></img>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue