diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..b25c15b81fa --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ diff --git a/Makefile.in b/Makefile.in index ecc39c8c565..c89415d78bf 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 \ No newline at end of file diff --git a/src/dom/rcu.rs b/src/dom/rcu.rs index bde372f0c71..2473156ca2f 100644 --- a/src/dom/rcu.rs +++ b/src/dom/rcu.rs @@ -1,6 +1,15 @@ -enum handle = @T; +enum handle { + _handle(@T) +} impl methods for handle { fn get() -> @T { *self } + + fn with(f: fn(T)) { + f(**self) + } } +fn handle(t: T) -> handle { + _handle(@t) +} diff --git a/src/layout/base.rs b/src/layout/base.rs index 8268523261f..488d3da2282 100644 --- a/src/layout/base.rs +++ b/src/layout/base.rs @@ -1,29 +1,16 @@ import dom::rcu; import dom::rcu::methods; - -// FIXME--mut should be inherited -type point = { mut x: A, mut y: A }; -type size = { mut width: A, mut height: A }; -type rect = { mut origin: point, mut size: size }; - -enum au = int; - -type tree_fields = { - parent: option, - first_child: option, - last_child: option, - prev_sibling: option, - next_sibling: option -}; +import util::{tree, geom}; +import geom::{size, rect, point, au}; enum box = @{ - tree: tree_fields, + tree: tree::fields, node: node, - mut bounds: rect + mut bounds: geom::rect }; -type node_data = { - tree: tree_fields, +enum node_data = { + tree: tree::fields, kind: node_kind, // Points to the primary box. Note that there may be multiple @@ -36,44 +23,37 @@ enum node_kind { nk_img(size) } -enum node = rcu::handle; +type node = rcu::handle; -iface tree { - fn tree_fields() -> tree_fields; -} - -impl of tree for box { - fn tree_fields() -> tree_fields { +impl of tree::tree for box { + fn tree_fields() -> tree::fields { ret self.tree; } } -impl of tree for node { - fn tree_fields() -> tree_fields { - ret (*self).get().tree; +impl of tree::tree for node { + fn tree_fields() -> tree::fields { + ret self.get().tree; } } -fn each_child( - 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); + } +} +*/ \ No newline at end of file diff --git a/src/servo.rc b/src/servo.rc index 324fd2d0247..6a870e63b9b 100755 --- a/src/servo.rc +++ b/src/servo.rc @@ -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; +} \ No newline at end of file diff --git a/src/util/geom.rs b/src/util/geom.rs new file mode 100644 index 00000000000..4e857ffc802 --- /dev/null +++ b/src/util/geom.rs @@ -0,0 +1,25 @@ +// FIXME--mut should be inherited +type point = { mut x: A, mut y: A }; +type size = { mut width: A, mut height: A }; +type rect = { mut origin: point, mut size: size }; + +enum au = int; + +fn point(x: A, y: A) -> point { + {mut x: x, mut y: y} +} + +fn size(w: A, h: A) -> size { + {mut width: w, mut height: h} +} + +fn box(x: A, y: A, w: A, h: A) -> rect { + {mut origin: point(x, y), + mut size: size(w, h)} +} + +fn zero_rect_au() -> rect { + let z = au(0); + {mut origin: point(z, z), mut size: size(z, z)} +} + diff --git a/src/util/tree.rs b/src/util/tree.rs new file mode 100644 index 00000000000..fb3acd21fd0 --- /dev/null +++ b/src/util/tree.rs @@ -0,0 +1,98 @@ +type fields = @{ + mut parent: option, + mut first_child: option, + mut last_child: option, + mut prev_sibling: option, + mut next_sibling: option +}; + +iface tree { + fn tree_fields() -> fields; +} + +fn each_child( + 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() -> fields { + @{mut parent: none, + mut first_child: none, + mut last_child: none, + mut prev_sibling: none, + mut next_sibling: none} +} + +fn add_child( + 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, + value: uint + }; + + impl of tree for dummy { + fn tree_fields() -> fields { 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(); + } +} \ No newline at end of file