servo: separate tree rd/wr ifaces, make them based on an ops object

the ops object is needed to make it so that dom node mutations
go through the RCU store

Source-Repo: https://github.com/servo/servo
Source-Revision: bbc936dec423ba5acadcfb7ad67934d7e89a887f
This commit is contained in:
Niko Matsakis 2012-05-04 13:21:25 -07:00
Родитель 5240195254
Коммит a0ff56468e
6 изменённых файлов: 97 добавлений и 37 удалений

Просмотреть файл

@ -4,7 +4,7 @@ export content;
import gfx::geom::*;
import dom::rcu::*;
import dom::base::*;
import layout::base::tree; // method implementations of tree for box and node
import layout::base::{rd_tree_ops, wr_tree_ops};
enum msg {
exit

Просмотреть файл

@ -23,3 +23,23 @@ impl methods for scope<node_data, box> {
kind: k}))
}
}
impl of tree::rd_tree_ops<node> for scope<node_data, box> {
fn each_child(node: node, f: fn(node) -> bool) {
tree::each_child(self, node, f)
}
fn with_tree_fields<R>(node: node, f: fn(tree::fields<node>) -> R) -> R {
f(self.rd(node) { |f| f.tree })
}
}
impl of tree::wr_tree_ops<node> for scope<node_data, box> {
fn add_child(node: node, child: node) {
tree::add_child(self, node, child)
}
fn with_tree_fields<R>(node: node, f: fn(tree::fields<node>) -> R) -> R {
f(self.wr(node) { |f| f.tree })
}
}

Просмотреть файл

@ -123,6 +123,12 @@ impl writer_methods<T:send,A> for scope<T,A> {
self.layout_active = false;
}
fn rd<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
// Use the wr_ptr, which may be more up to date than the
// rd_ptr or may not
f(*h.wr_ptr())
}
fn wr<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
if self.layout_active {
if h.rd_ptr() == h.wr_ptr() {

Просмотреть файл

@ -11,15 +11,35 @@ enum box = {
mut bounds: geom::rect<au>
};
impl of tree::tree for node {
fn with_tree_fields<R>(f: fn(tree::fields<node>) -> R) -> R {
f(self.rd { |f| f.tree })
enum ntree { ntree }
impl of tree::rd_tree_ops<node> for ntree {
fn each_child(node: node, f: fn(node) -> bool) {
tree::each_child(self, node, f)
}
fn with_tree_fields<R>(n: node, f: fn(tree::fields<node>) -> R) -> R {
n.rd { |n| f(n.tree) }
}
}
impl of tree::tree for @box {
fn with_tree_fields<R>(f: fn(tree::fields<@box>) -> R) -> R {
f(self.tree)
enum btree { btree }
impl of tree::rd_tree_ops<@box> for btree {
fn each_child(node: @box, f: fn(&&@box) -> bool) {
tree::each_child(self, node, f)
}
fn with_tree_fields<R>(b: @box, f: fn(tree::fields<@box>) -> R) -> R {
f(b.tree)
}
}
impl of tree::wr_tree_ops<@box> for btree {
fn add_child(node: @box, child: @box) {
tree::add_child(self, node, child)
}
fn with_tree_fields<R>(b: @box, f: fn(tree::fields<@box>) -> R) -> R {
f(b.tree)
}
}
@ -55,7 +75,7 @@ fn reflow_block(root: @box, available_width: au) {
}
let mut current_height = 0;
for tree::each_child(root) {|c|
for tree::each_child(btree, root) {|c|
let mut blk_available_width = available_width;
// FIXME subtract borders, margins, etc
c.bounds.origin = {mut x: au(0), mut y: au(current_height)};
@ -69,7 +89,8 @@ fn reflow_block(root: @box, available_width: au) {
#[cfg(test)]
mod test {
import dom::base::{nk_img, node_data, node_kind, node, methods};
import dom::base::{nk_img, node_data, node_kind, node, methods,
wr_tree_ops};
import dom::rcu::scope;
/*
@ -90,7 +111,7 @@ mod test {
fn flat_bounds(root: @box) -> [geom::rect<au>] {
let mut r = [];
for tree::each_child(root) {|c|
for tree::each_child(btree, root) {|c|
r += flat_bounds(c);
}
ret r + [root.bounds];
@ -105,18 +126,18 @@ mod test {
let n2 = s.new_node(nk_img(size(au(10),au(20))));
let n3 = s.new_node(nk_div);
tree::add_child(n3, n0);
tree::add_child(n3, n1);
tree::add_child(n3, n2);
tree::add_child(s, n3, n0);
tree::add_child(s, n3, n1);
tree::add_child(s, n3, n2);
let b0 = linked_box(n0);
let b1 = linked_box(n1);
let b2 = linked_box(n2);
let b3 = linked_box(n3);
tree::add_child(b3, b0);
tree::add_child(b3, b1);
tree::add_child(b3, b2);
tree::add_child(btree, b3, b0);
tree::add_child(btree, b3, b1);
tree::add_child(btree, b3, b2);
reflow_block(b3, au(100));
let fb = flat_bounds(b3);

Просмотреть файл

@ -13,7 +13,7 @@ import gfx::renderer;
import dom::base::*;
import display_list::*;
import dom::rcu::scope;
import base::tree;
import base::{btree, rd_tree_ops, wr_tree_ops};
enum msg {
build,
@ -38,9 +38,9 @@ fn layout(renderer: chan<renderer::msg>) -> chan<msg> {
int_to_au(r.next() as int % 800),
int_to_au(r.next() as int % 200)
)));
tree::add_child(ndiv, node);
s.add_child(ndiv, node);
let b = base::linked_box(node);
tree::add_child(bdiv, b);
btree.add_child(bdiv, b);
}
alt recv(po) {
@ -63,7 +63,7 @@ fn layout(renderer: chan<renderer::msg>) -> chan<msg> {
fn build_display_list(box: @base::box) -> display_list::display_list {
let mut list = [box_to_display_item(box)];
for tree::each_child(box) {|c|
for btree.each_child(box) {|c|
list += build_display_list(c);
}

Просмотреть файл

@ -6,20 +6,24 @@ type fields<T> = {
mut next_sibling: option<T>
};
iface tree {
fn with_tree_fields<R>(f: fn(fields<self>) -> R) -> R;
iface rd_tree_ops<T> {
fn with_tree_fields<R>(T, f: fn(fields<T>) -> R) -> R;
}
fn each_child<T:copy tree>(
node: T, f: fn(T) -> bool) {
iface wr_tree_ops<T> {
fn with_tree_fields<R>(T, f: fn(fields<T>) -> R) -> R;
}
let mut p = node.with_tree_fields { |f| f.first_child };
fn each_child<T:copy,O:rd_tree_ops<T>>(
ops: O, node: T, f: fn(T) -> bool) {
let mut p = ops.with_tree_fields(node) { |f| f.first_child };
loop {
alt p {
none { ret; }
some(c) {
if !f(c) { ret; }
p = c.with_tree_fields { |f| f.next_sibling };
p = ops.with_tree_fields(c) { |f| f.next_sibling };
}
}
}
@ -33,10 +37,10 @@ fn empty<T>() -> fields<T> {
mut next_sibling: none}
}
fn add_child<T:copy tree>(
node: T, child: T) {
fn add_child<T:copy,O:wr_tree_ops<T>>(
ops: O, node: T, child: T) {
child.with_tree_fields { |child_tf|
ops.with_tree_fields(child) { |child_tf|
alt child_tf.parent {
some(_) { fail "Already has a parent"; }
none { child_tf.parent = some(node); }
@ -45,14 +49,15 @@ fn add_child<T:copy tree>(
assert child_tf.prev_sibling == none;
assert child_tf.next_sibling == none;
node.with_tree_fields { |node_tf|
ops.with_tree_fields(node) { |node_tf|
alt node_tf.last_child {
none {
node_tf.first_child = some(child);
}
some(lc) {
lc.with_tree_fields { |lc_tf|
let lc = lc; // satisfy alias checker
ops.with_tree_fields(lc) { |lc_tf|
assert lc_tf.next_sibling == none;
lc_tf.next_sibling = some(child);
}
@ -72,9 +77,17 @@ mod test {
value: uint
};
impl of tree for dummy {
fn with_tree_fields<R>(f: fn(fields<dummy>) -> R) -> R {
f(self.fields)
enum dtree { dtree }
impl of rd_tree_ops<dummy> for dtree {
fn with_tree_fields<R>(d: dummy, f: fn(fields<dummy>) -> R) -> R {
f(d.fields)
}
}
impl of wr_tree_ops<dummy> for dtree {
fn with_tree_fields<R>(d: dummy, f: fn(fields<dummy>) -> R) -> R {
f(d.fields)
}
}
@ -89,7 +102,7 @@ mod test {
let p = new_dummy(3u);
for vec::each(children) {|c|
add_child(p, c);
add_child(dtree, p, c);
}
ret {p: p, children: children};
@ -99,7 +112,7 @@ mod test {
fn add_child_0() {
let {p, children} = parent_with_3_children();
let mut i = 0u;
for each_child(p) {|c|
for each_child(dtree, p) {|c|
assert c.value == i;
i += 1u;
}
@ -110,7 +123,7 @@ mod test {
fn add_child_break() {
let {p, _} = parent_with_3_children();
let mut i = 0u;
for each_child(p) {|_c|
for each_child(dtree, p) {|_c|
i += 1u;
break;
}