servo: reorganize code, add tests for tree, add 'make test'

Source-Repo: https://github.com/servo/servo
Source-Revision: da19925c20f58657fcf33f61e0c99dd8988bf2ef
This commit is contained in:
Niko Matsakis 2012-03-27 16:22:29 -07:00
parent 10d93d10c3
commit b98c0e9eff
7 changed files with 216 additions and 47 deletions

1
servo/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*~

View File

@ -5,13 +5,21 @@ RUSTFLAGS?=
RUST_SRC=$(shell find $(VPATH)/src -type f -name '*.rs')
.PHONY: all
all: servo
servo: src/servo.rc $(RUST_SRC)
servo: \
src/servo.rc $(RUST_SRC)
$(RUSTC) $(RUSTFLAGS) -o $@ $<
servo-test: \
src/servo.rc $(RUST_SRC)
$(RUSTC) $(RUSTFLAGS) --test -o $@ $<
.PHONY: clean
clean:
rm -f servo
rm -f servo servo-test
.PHONY: test
test: servo-test
./servo-test

View File

@ -1,6 +1,15 @@
enum handle<T> = @T;
enum handle<T> {
_handle(@T)
}
impl methods<T> for handle<T> {
fn get() -> @T { *self }
fn with(f: fn(T)) {
f(**self)
}
}
fn handle<T:copy>(t: T) -> handle<T> {
_handle(@t)
}

View File

@ -1,29 +1,16 @@
import dom::rcu;
import dom::rcu::methods;
// FIXME--mut should be inherited
type point<A> = { mut x: A, mut y: A };
type size<A> = { mut width: A, mut height: A };
type rect<A> = { mut origin: point<A>, mut size: size<A> };
enum au = int;
type tree_fields<T> = {
parent: option<T>,
first_child: option<T>,
last_child: option<T>,
prev_sibling: option<T>,
next_sibling: option<T>
};
import util::{tree, geom};
import geom::{size, rect, point, au};
enum box = @{
tree: tree_fields<box>,
tree: tree::fields<box>,
node: node,
mut bounds: rect<au>
mut bounds: geom::rect<au>
};
type node_data = {
tree: tree_fields<node>,
enum node_data = {
tree: tree::fields<node>,
kind: node_kind,
// Points to the primary box. Note that there may be multiple
@ -36,44 +23,37 @@ enum node_kind {
nk_img(size<au>)
}
enum node = rcu::handle<node_data>;
type node = rcu::handle<node_data>;
iface tree {
fn tree_fields() -> tree_fields<self>;
}
impl of tree for box {
fn tree_fields() -> tree_fields<box> {
impl of tree::tree for box {
fn tree_fields() -> tree::fields<box> {
ret self.tree;
}
}
impl of tree for node {
fn tree_fields() -> tree_fields<node> {
ret (*self).get().tree;
impl of tree::tree for node {
fn tree_fields() -> tree::fields<node> {
ret self.get().tree;
}
}
fn each_child<T:copy tree>(
node: T, f: fn(T) -> bool) {
fn new_node(+k: node_kind) -> node {
rcu::handle(node_data({tree: tree::empty(),
kind: k,
mut linfo: none}))
}
let mut p = node.tree_fields().first_child;
loop {
alt p {
none { ret; }
some(c) {
if !f(c) { ret; }
p = c.tree_fields().next_sibling;
}
}
}
fn new_box(n: node) -> box {
box(@{tree: tree::empty(),
node: n,
mut bounds: geom::zero_rect_au()})
}
fn reflow_block(root: box, available_width: au) {
// Root here is the root of the reflow, not necessarily the doc as
// a whole.
alt (*root.node).get().kind {
alt root.node.get().kind {
nk_img(size) {
root.bounds.size = size;
ret;
@ -83,7 +63,7 @@ fn reflow_block(root: box, available_width: au) {
}
let mut current_height = 0;
for each_child(root) {|c|
for tree::each_child(root) {|c|
let mut blk_available_width = available_width;
// FIXME subtract borders, margins, etc
c.bounds.origin = {x: au(0), y: au(current_height)};
@ -94,3 +74,45 @@ fn reflow_block(root: box, available_width: au) {
root.bounds.size = {width: available_width, // FIXME
height: au(current_height)};
}
/*
#[cfg(test)]
mod test {
use sdl;
import sdl::video;
fn with_screen(f: fn(*sdl::surface)) {
let screen = video::set_video_mode(
320, 200, 32,
[video::hwsurface], [video::doublebuf]);
assert screen != ptr::null();
f(screen);
video::free_surface(screen);
}
}
#[test]
fn do_layout() {
test::with_screen {|s|
let n0 = node(nk_img(size(au(22),au(44))));
let n1 = node(nk_img(size(au(22),au(44))));
let n2 = node(nk_img(size(au(22),au(44))));
let n3 = node(nk_div);
tree::add_child(n3, n0);
tree::add_child(n3, n1);
tree::add_child(n3, n2);
let b0 = box(n0);
let b1 = box(n1);
let b2 = box(n2);
let b3 = box(n3);
tree::add_child(b3, b0);
tree::add_child(b3, b1);
tree::add_child(b3, b2);
}
}
*/

View File

@ -6,6 +6,8 @@
#[comment = "The Servo Parallel Browser Project"];
#[license = "MPL"];
use std;
mod dom {
mod base;
mod rcu;
@ -19,3 +21,7 @@ mod widget {
mod base;
}
mod util {
mod tree;
mod geom;
}

25
servo/src/util/geom.rs Normal file
View File

@ -0,0 +1,25 @@
// FIXME--mut should be inherited
type point<A> = { mut x: A, mut y: A };
type size<A> = { mut width: A, mut height: A };
type rect<A> = { mut origin: point<A>, mut size: size<A> };
enum au = int;
fn point<A:copy>(x: A, y: A) -> point<A> {
{mut x: x, mut y: y}
}
fn size<A:copy>(w: A, h: A) -> size<A> {
{mut width: w, mut height: h}
}
fn box<A:copy>(x: A, y: A, w: A, h: A) -> rect<A> {
{mut origin: point(x, y),
mut size: size(w, h)}
}
fn zero_rect_au() -> rect<au> {
let z = au(0);
{mut origin: point(z, z), mut size: size(z, z)}
}

98
servo/src/util/tree.rs Normal file
View File

@ -0,0 +1,98 @@
type fields<T> = @{
mut parent: option<T>,
mut first_child: option<T>,
mut last_child: option<T>,
mut prev_sibling: option<T>,
mut next_sibling: option<T>
};
iface tree {
fn tree_fields() -> fields<self>;
}
fn each_child<T:copy tree>(
node: T, f: fn(T) -> bool) {
let mut p = node.tree_fields().first_child;
loop {
alt p {
none { ret; }
some(c) {
if !f(c) { ret; }
p = c.tree_fields().next_sibling;
}
}
}
}
fn empty<T>() -> fields<T> {
@{mut parent: none,
mut first_child: none,
mut last_child: none,
mut prev_sibling: none,
mut next_sibling: none}
}
fn add_child<T:copy tree>(
node: T, child: T) {
let child_tf = child.tree_fields();
alt child_tf.parent {
some(_) { fail "Already has a parent"; }
none { child_tf.parent = some(node); }
}
assert child_tf.prev_sibling == none;
assert child_tf.next_sibling == none;
let node_tf = node.tree_fields();
alt node_tf.last_child {
none {
node_tf.first_child = some(child);
}
some(lc) {
let lc_tf = lc.tree_fields();
assert lc_tf.next_sibling == none;
lc_tf.next_sibling = some(child);
child_tf.prev_sibling = some(lc);
}
}
node_tf.last_child = some(child);
}
#[cfg(test)]
mod test {
enum dummy = @{
fields: fields<dummy>,
value: uint
};
impl of tree for dummy {
fn tree_fields() -> fields<dummy> { self.fields }
}
fn new_dummy(v: uint) -> dummy {
dummy(@{fields: empty(), value: v})
}
#[test]
fn add_child_0() {
let children = [new_dummy(0u),
new_dummy(1u),
new_dummy(2u)];
let p = new_dummy(3u);
for vec::each(children) {|c|
add_child(p, c);
}
let mut i = 0u;
for each_child(p) {|c|
assert c.value == i;
i += 1u;
}
assert i == children.len();
}
}