зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
5240195254
Коммит
a0ff56468e
|
@ -4,7 +4,7 @@ export content;
|
||||||
import gfx::geom::*;
|
import gfx::geom::*;
|
||||||
import dom::rcu::*;
|
import dom::rcu::*;
|
||||||
import dom::base::*;
|
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 {
|
enum msg {
|
||||||
exit
|
exit
|
||||||
|
|
|
@ -23,3 +23,23 @@ impl methods for scope<node_data, box> {
|
||||||
kind: k}))
|
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;
|
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 {
|
fn wr<U>(h: handle<T,A>, f: fn(T) -> U) -> U unsafe {
|
||||||
if self.layout_active {
|
if self.layout_active {
|
||||||
if h.rd_ptr() == h.wr_ptr() {
|
if h.rd_ptr() == h.wr_ptr() {
|
||||||
|
|
|
@ -11,15 +11,35 @@ enum box = {
|
||||||
mut bounds: geom::rect<au>
|
mut bounds: geom::rect<au>
|
||||||
};
|
};
|
||||||
|
|
||||||
impl of tree::tree for node {
|
enum ntree { ntree }
|
||||||
fn with_tree_fields<R>(f: fn(tree::fields<node>) -> R) -> R {
|
impl of tree::rd_tree_ops<node> for ntree {
|
||||||
f(self.rd { |f| f.tree })
|
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 {
|
enum btree { btree }
|
||||||
fn with_tree_fields<R>(f: fn(tree::fields<@box>) -> R) -> R {
|
impl of tree::rd_tree_ops<@box> for btree {
|
||||||
f(self.tree)
|
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;
|
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;
|
let mut blk_available_width = available_width;
|
||||||
// FIXME subtract borders, margins, etc
|
// FIXME subtract borders, margins, etc
|
||||||
c.bounds.origin = {mut x: au(0), mut y: au(current_height)};
|
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)]
|
#[cfg(test)]
|
||||||
mod 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;
|
import dom::rcu::scope;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -90,7 +111,7 @@ mod test {
|
||||||
|
|
||||||
fn flat_bounds(root: @box) -> [geom::rect<au>] {
|
fn flat_bounds(root: @box) -> [geom::rect<au>] {
|
||||||
let mut r = [];
|
let mut r = [];
|
||||||
for tree::each_child(root) {|c|
|
for tree::each_child(btree, root) {|c|
|
||||||
r += flat_bounds(c);
|
r += flat_bounds(c);
|
||||||
}
|
}
|
||||||
ret r + [root.bounds];
|
ret r + [root.bounds];
|
||||||
|
@ -105,18 +126,18 @@ mod test {
|
||||||
let n2 = s.new_node(nk_img(size(au(10),au(20))));
|
let n2 = s.new_node(nk_img(size(au(10),au(20))));
|
||||||
let n3 = s.new_node(nk_div);
|
let n3 = s.new_node(nk_div);
|
||||||
|
|
||||||
tree::add_child(n3, n0);
|
tree::add_child(s, n3, n0);
|
||||||
tree::add_child(n3, n1);
|
tree::add_child(s, n3, n1);
|
||||||
tree::add_child(n3, n2);
|
tree::add_child(s, n3, n2);
|
||||||
|
|
||||||
let b0 = linked_box(n0);
|
let b0 = linked_box(n0);
|
||||||
let b1 = linked_box(n1);
|
let b1 = linked_box(n1);
|
||||||
let b2 = linked_box(n2);
|
let b2 = linked_box(n2);
|
||||||
let b3 = linked_box(n3);
|
let b3 = linked_box(n3);
|
||||||
|
|
||||||
tree::add_child(b3, b0);
|
tree::add_child(btree, b3, b0);
|
||||||
tree::add_child(b3, b1);
|
tree::add_child(btree, b3, b1);
|
||||||
tree::add_child(b3, b2);
|
tree::add_child(btree, b3, b2);
|
||||||
|
|
||||||
reflow_block(b3, au(100));
|
reflow_block(b3, au(100));
|
||||||
let fb = flat_bounds(b3);
|
let fb = flat_bounds(b3);
|
||||||
|
|
|
@ -13,7 +13,7 @@ import gfx::renderer;
|
||||||
import dom::base::*;
|
import dom::base::*;
|
||||||
import display_list::*;
|
import display_list::*;
|
||||||
import dom::rcu::scope;
|
import dom::rcu::scope;
|
||||||
import base::tree;
|
import base::{btree, rd_tree_ops, wr_tree_ops};
|
||||||
|
|
||||||
enum msg {
|
enum msg {
|
||||||
build,
|
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 % 800),
|
||||||
int_to_au(r.next() as int % 200)
|
int_to_au(r.next() as int % 200)
|
||||||
)));
|
)));
|
||||||
tree::add_child(ndiv, node);
|
s.add_child(ndiv, node);
|
||||||
let b = base::linked_box(node);
|
let b = base::linked_box(node);
|
||||||
tree::add_child(bdiv, b);
|
btree.add_child(bdiv, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
alt recv(po) {
|
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 {
|
fn build_display_list(box: @base::box) -> display_list::display_list {
|
||||||
let mut list = [box_to_display_item(box)];
|
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);
|
list += build_display_list(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,20 +6,24 @@ type fields<T> = {
|
||||||
mut next_sibling: option<T>
|
mut next_sibling: option<T>
|
||||||
};
|
};
|
||||||
|
|
||||||
iface tree {
|
iface rd_tree_ops<T> {
|
||||||
fn with_tree_fields<R>(f: fn(fields<self>) -> R) -> R;
|
fn with_tree_fields<R>(T, f: fn(fields<T>) -> R) -> R;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn each_child<T:copy tree>(
|
iface wr_tree_ops<T> {
|
||||||
node: T, f: fn(T) -> bool) {
|
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 {
|
loop {
|
||||||
alt p {
|
alt p {
|
||||||
none { ret; }
|
none { ret; }
|
||||||
some(c) {
|
some(c) {
|
||||||
if !f(c) { ret; }
|
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}
|
mut next_sibling: none}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_child<T:copy tree>(
|
fn add_child<T:copy,O:wr_tree_ops<T>>(
|
||||||
node: T, child: T) {
|
ops: O, node: T, child: T) {
|
||||||
|
|
||||||
child.with_tree_fields { |child_tf|
|
ops.with_tree_fields(child) { |child_tf|
|
||||||
alt child_tf.parent {
|
alt child_tf.parent {
|
||||||
some(_) { fail "Already has a parent"; }
|
some(_) { fail "Already has a parent"; }
|
||||||
none { child_tf.parent = some(node); }
|
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.prev_sibling == none;
|
||||||
assert child_tf.next_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 {
|
alt node_tf.last_child {
|
||||||
none {
|
none {
|
||||||
node_tf.first_child = some(child);
|
node_tf.first_child = some(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
some(lc) {
|
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;
|
assert lc_tf.next_sibling == none;
|
||||||
lc_tf.next_sibling = some(child);
|
lc_tf.next_sibling = some(child);
|
||||||
}
|
}
|
||||||
|
@ -72,9 +77,17 @@ mod test {
|
||||||
value: uint
|
value: uint
|
||||||
};
|
};
|
||||||
|
|
||||||
impl of tree for dummy {
|
enum dtree { dtree }
|
||||||
fn with_tree_fields<R>(f: fn(fields<dummy>) -> R) -> R {
|
|
||||||
f(self.fields)
|
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);
|
let p = new_dummy(3u);
|
||||||
|
|
||||||
for vec::each(children) {|c|
|
for vec::each(children) {|c|
|
||||||
add_child(p, c);
|
add_child(dtree, p, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret {p: p, children: children};
|
ret {p: p, children: children};
|
||||||
|
@ -99,7 +112,7 @@ mod test {
|
||||||
fn add_child_0() {
|
fn add_child_0() {
|
||||||
let {p, children} = parent_with_3_children();
|
let {p, children} = parent_with_3_children();
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
for each_child(p) {|c|
|
for each_child(dtree, p) {|c|
|
||||||
assert c.value == i;
|
assert c.value == i;
|
||||||
i += 1u;
|
i += 1u;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +123,7 @@ mod test {
|
||||||
fn add_child_break() {
|
fn add_child_break() {
|
||||||
let {p, _} = parent_with_3_children();
|
let {p, _} = parent_with_3_children();
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
for each_child(p) {|_c|
|
for each_child(dtree, p) {|_c|
|
||||||
i += 1u;
|
i += 1u;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче