Skip to content
Permalink
Browse files

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
  • Loading branch information...
nikomatsakis committed May 4, 2012
1 parent 39462a5 commit bbc936dec423ba5acadcfb7ad67934d7e89a887f
Showing with 97 additions and 37 deletions.
  1. +1 −1 src/servo/content.rs
  2. +20 −0 src/servo/dom/base.rs
  3. +6 −0 src/servo/dom/rcu.rs
  4. +36 −15 src/servo/layout/base.rs
  5. +4 −4 src/servo/layout/layout.rs
  6. +30 −17 src/servo/util/tree.rs
@@ -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;
}

fn each_child<T:copy,O:rd_tree_ops<T>>(
ops: O, node: T, f: fn(T) -> bool) {

let mut p = node.with_tree_fields { |f| f.first_child };
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;
}

0 comments on commit bbc936d

Please sign in to comment.
You can’t perform that action at this time.