Upgrade Rust compiler

Some work to do yet on Mac
This commit is contained in:
Brian Anderson 2013-01-20 14:38:41 -08:00
parent 2325db188f
commit 094cfece48
45 changed files with 189 additions and 111 deletions

View file

@ -78,6 +78,11 @@ $(S)config.stamp : $(S)configure $(S)Makefile.in
$(CFG_RUSTC): $(CFG_RUSTC):
$(MAKE) -C "$(CFG_BUILD_DIR)src/rust" CFG_RUSTC_FLAGS="" RUSTFLAGS="" $(MAKE) -C "$(CFG_BUILD_DIR)src/rust" CFG_RUSTC_FLAGS="" RUSTFLAGS=""
rust: $(CFG_RUSTC)
clean-rust:
$(MAKE) -C "$(CFG_BUILD_DIR)src/rust" CFG_RUSTC_FLAGS="" RUSTFLAGS="" clean
define DEF_SUBMODULE_VARS define DEF_SUBMODULE_VARS
DEPS_$(1) = DEPS_$(1) =
CFLAGS_$(1) = -O2 CFLAGS_$(1) = -O2

@ -1 +1 @@
Subproject commit 3ee1d3ebb81de199fc630a86933ac18c0a869482 Subproject commit f405e41d7a43ebd7fdd0fcd90f6e0542a5a6ccf6

@ -1 +1 @@
Subproject commit 535e779370b7d94cdd46403f1d883fbc1b04af05 Subproject commit 91ebe55a5af22452e906dab6dad791f7761bde3d

@ -1 +1 @@
Subproject commit 7d37d899a0fb038069a796ed4c866e6ec76cc268 Subproject commit f0da2d3a9c67d0a4748779c67576cb763558e047

@ -1 +1 @@
Subproject commit 461dcedfb36240f3c82f1d193f8cb42c9528fe34 Subproject commit 6a58ecc96287aa1c051c0aacba3d3b6857b4dd0d

@ -1 +1 @@
Subproject commit cbb84866b91aaff3fcd1dc774f61f76c4a7c3b0b Subproject commit 09e2852951c635cf9cabc76a862740188869c915

@ -1 +1 @@
Subproject commit f0aebb8ba525cd39227e1fe0ca8c2119ddac3f29 Subproject commit 5b39316c0b9f37417a7a5863dcfb03b007bd3634

@ -1 +1 @@
Subproject commit caecddcc50418adbed686f6bd33e4c1d9ea5efeb Subproject commit b69b3b49ad993c79156298eb6c96bec58db77128

@ -1 +1 @@
Subproject commit 6194981fc653b02facd12adc964ec42511cc762f Subproject commit b5a5d728f0c092ca1881a26446860bb717d27448

@ -1 +1 @@
Subproject commit 261693b63e8922a95204db3681209138627362c4 Subproject commit a03bfeb74adfa0aae7e459a249f62e6e553c823b

View file

@ -28,7 +28,7 @@ pub enum DisplayItem {
// (i.e, to support rendering of CSS 'word-spacing' and 'letter-spacing') // (i.e, to support rendering of CSS 'word-spacing' and 'letter-spacing')
// TODO: don't copy text runs, ever. // TODO: don't copy text runs, ever.
Text(DisplayItemData, ~SendableTextRun, Range, Color), Text(DisplayItemData, ~SendableTextRun, Range, Color),
Image(DisplayItemData, ARC<~image::base::Image>), Image(DisplayItemData, ARC<~Image>),
Border(DisplayItemData, Au, Color) Border(DisplayItemData, Au, Color)
} }
@ -80,7 +80,7 @@ impl DisplayItem {
} }
// ARC should be cloned into ImageData, but Images are not sendable // ARC should be cloned into ImageData, but Images are not sendable
static pure fn new_Image(bounds: &Rect<Au>, image: ARC<~image::base::Image>) -> DisplayItem { static pure fn new_Image(bounds: &Rect<Au>, image: ARC<~Image>) -> DisplayItem {
Image(DisplayItemData::new(bounds), move image) Image(DisplayItemData::new(bounds), move image)
} }
} }

View file

@ -12,6 +12,12 @@ use azure::azure_hl::{BackendType, ColorPattern};
use core::dvec::DVec; use core::dvec::DVec;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
#[cfg(target_os = "macos")]
use quartz;
#[cfg(target_os = "linux")]
use freetype_impl;
use native;
// FontHandle encapsulates access to the platform's font API, // FontHandle encapsulates access to the platform's font API,
// e.g. quartz, FreeType. It provides access to metrics and tables // e.g. quartz, FreeType. It provides access to metrics and tables
// needed by the text shaper as well as access to the underlying font // needed by the text shaper as well as access to the underlying font
@ -416,7 +422,7 @@ pub impl Font : FontMethods {
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| { for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
let glyph_advance = glyph.advance(); let glyph_advance = glyph.advance();
let glyph_offset = glyph.offset().get_default(Au::zero_point()); let glyph_offset = glyph.offset().get_or_default(Au::zero_point());
let azglyph: AzGlyph = { let azglyph: AzGlyph = {
mIndex: glyph.index() as uint32_t, mIndex: glyph.index() as uint32_t,

View file

@ -10,6 +10,12 @@ use core::dvec::DVec;
use core::send_map::linear::LinearMap; use core::send_map::linear::LinearMap;
use core::send_map::linear; use core::send_map::linear;
#[cfg(target_os = "macos")]
use quartz;
#[cfg(target_os = "linux")]
use freetype_impl;
use font_context;
// TODO(Issue #164): delete, and get default font from font list // TODO(Issue #164): delete, and get default font from font list
const TEST_FONT: [u8 * 33004] = include_bin!("JosefinSans-SemiBold.ttf"); const TEST_FONT: [u8 * 33004] = include_bin!("JosefinSans-SemiBold.ttf");

View file

@ -2,7 +2,12 @@ use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle};
use native::FontHandle; use native::FontHandle;
use dvec::DVec; use dvec::DVec;
use send_map::{linear, SendMap}; use core::send_map::{linear, SendMap};
#[cfg(target_os = "linux")]
use fontconfig;
use native;
use util::time::time;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
type FontListHandle/& = quartz::font_list::QuartzFontListHandle; type FontListHandle/& = quartz::font_list::QuartzFontListHandle;
@ -50,7 +55,7 @@ pub impl FontList {
// changed. Does OSX have a notification for this event? // changed. Does OSX have a notification for this event?
// //
// Should font families with entries be invalidated/refreshed too? // Should font families with entries be invalidated/refreshed too?
do util::time::time("gfx::font_list: regenerating available font families and faces") { do time("gfx::font_list: regenerating available font families and faces") {
self.family_map = self.handle.get_available_families(); self.family_map = self.handle.get_available_families();
} }
} }

View file

@ -25,6 +25,7 @@ use core::dvec::DVec;
use core::send_map::{linear, SendMap}; use core::send_map::{linear, SendMap};
use libc::c_int; use libc::c_int;
use ptr::Ptr; use ptr::Ptr;
use native;
pub struct FontconfigFontListHandle { pub struct FontconfigFontListHandle {
fctx: FreeTypeFontContextHandle, fctx: FreeTypeFontContextHandle,

View file

@ -1,5 +1,6 @@
extern mod freetype; extern mod freetype;
use native;
use freetype_impl::font_context::FreeTypeFontContextHandle; use freetype_impl::font_context::FreeTypeFontContextHandle;
use gfx_font::{ use gfx_font::{
CSSFontWeight, CSSFontWeight,
@ -22,6 +23,7 @@ use gfx_font::{
FontWeight800, FontWeight800,
FontWeight900, FontWeight900,
}; };
use geometry;
use geometry::Au; use geometry::Au;
use text::glyph::GlyphIndex; use text::glyph::GlyphIndex;
use text::util::{float_to_fixed, fixed_to_float}; use text::util::{float_to_fixed, fixed_to_float};

View file

@ -1,4 +1,5 @@
use io::WriterUtil; use io::WriterUtil;
use surface;
fn encode(writer: io::Writer, surface: &surface::image_surface) { fn encode(writer: io::Writer, surface: &surface::image_surface) {
assert surface.format == surface::fo_rgba_8888; assert surface.format == surface::fo_rgba_8888;

View file

@ -14,6 +14,7 @@ use core::ptr::to_unsafe_ptr;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use std::arc;
use std::arc::ARC; use std::arc::ARC;
pub struct RenderContext { pub struct RenderContext {
@ -48,7 +49,7 @@ impl RenderContext {
} }
pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) { pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) {
let image = std::arc::get(&image); let image = arc::get(&image);
let size = Size2D(image.width as i32, image.height as i32); let size = Size2D(image.width as i32, image.height as i32);
let stride = image.width * 4; let stride = image.width * 4;

View file

@ -4,7 +4,7 @@ use opts::Opts;
use render_context::RenderContext; use render_context::RenderContext;
use render_layers::{RenderLayer, render_layers}; use render_layers::{RenderLayer, render_layers};
use resource::util::spawn_listener; use resource::util::spawn_listener;
use util::time::time;
use azure::AzFloat; use azure::AzFloat;
use core::oldcomm::*; use core::oldcomm::*;
use core::libc::size_t; use core::libc::size_t;
@ -109,7 +109,7 @@ impl<C: Compositor Owned> Renderer<C> {
debug!("renderer: rendering"); debug!("renderer: rendering");
do util::time::time(~"rendering") { do time(~"rendering") {
let layer_buffer_set = layer_buffer_set_cell.take(); let layer_buffer_set = layer_buffer_set_cell.take();
let layer_buffer_set_channel = layer_buffer_set_channel_cell.take(); let layer_buffer_set_channel = layer_buffer_set_channel_cell.take();

View file

@ -4,6 +4,7 @@ use oldcomm::Chan;
use task::spawn; use task::spawn;
use resource::resource_task::{ProgressMsg, Payload, Done}; use resource::resource_task::{ProgressMsg, Payload, Done};
use std::net::url::Url; use std::net::url::Url;
use http_client;
use http_client::{uv_http_request}; use http_client::{uv_http_request};
pub fn factory(url: Url, progress_chan: Chan<ProgressMsg>) { pub fn factory(url: Url, progress_chan: Chan<ProgressMsg>) {

View file

@ -8,6 +8,7 @@ use oldcomm::{Chan, Port};
use resource::util::spawn_listener; use resource::util::spawn_listener;
use std::net::url; use std::net::url;
use std::net::url::{Url, to_str}; use std::net::url::{Url, to_str};
use super::{file_loader, http_loader};
pub enum ControlMsg { pub enum ControlMsg {
/// Request the data associated with a particular URL /// Request the data associated with a particular URL
@ -52,9 +53,11 @@ type LoaderTaskFactory = fn~(url: Url, Chan<ProgressMsg>);
/// Create a ResourceTask with the default loaders /// Create a ResourceTask with the default loaders
pub fn ResourceTask() -> ResourceTask { pub fn ResourceTask() -> ResourceTask {
let file_loader_factory: LoaderTaskFactory = file_loader::factory;
let http_loader_factory: LoaderTaskFactory = http_loader::factory;
let loaders = ~[ let loaders = ~[
(~"file", file_loader::factory), (~"file", file_loader_factory),
(~"http", http_loader::factory) (~"http", http_loader_factory)
]; ];
create_resource_task_with_loaders(move loaders) create_resource_task_with_loaders(move loaders)
} }
@ -100,7 +103,7 @@ impl ResourceManager {
match self.get_loader_factory(&url) { match self.get_loader_factory(&url) {
Some(loader_factory) => { Some(loader_factory) => {
debug!("resource_task: loading url: %s", to_str(copy url)); debug!("resource_task: loading url: %s", to_str(&url));
loader_factory(move url, progress_chan); loader_factory(move url, progress_chan);
} }
None => { None => {

View file

@ -2,6 +2,8 @@ use geometry::Au;
use servo_gfx_util::range::Range; use servo_gfx_util::range::Range;
use servo_gfx_util::vec::*; use servo_gfx_util::vec::*;
use geometry;
use core;
use core::cmp::{Ord, Eq}; use core::cmp::{Ord, Eq};
use core::dvec::DVec; use core::dvec::DVec;
use core::u16; use core::u16;

View file

@ -61,6 +61,8 @@ use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
hb_font_funcs_set_glyph_func, hb_font_funcs_set_glyph_func,
hb_font_funcs_set_glyph_h_kerning_func}; hb_font_funcs_set_glyph_h_kerning_func};
use text::util::{float_to_fixed, fixed_to_float, fixed_to_rounded_int};
pub struct ShapedGlyphData { pub struct ShapedGlyphData {
count: uint, count: uint,
glyph_infos: *hb_glyph_info_t, glyph_infos: *hb_glyph_info_t,
@ -169,7 +171,7 @@ pub impl HarfbuzzShaper {
hb_font_funcs_set_glyph_func(hb_funcs, glyph_func, ptr::null(), ptr::null()); hb_font_funcs_set_glyph_func(hb_funcs, glyph_func, ptr::null(), ptr::null());
hb_font_funcs_set_glyph_h_advance_func(hb_funcs, glyph_h_advance_func, ptr::null(), ptr::null()); hb_font_funcs_set_glyph_h_advance_func(hb_funcs, glyph_h_advance_func, ptr::null(), ptr::null());
unsafe { unsafe {
let font_data: *c_void = core::ptr::addr_of(font) as *c_void; let font_data: *c_void = ptr::addr_of(font) as *c_void;
hb_font_set_funcs(hb_font, hb_funcs, font_data, ptr::null()); hb_font_set_funcs(hb_font, hb_funcs, font_data, ptr::null());
}; };
@ -182,15 +184,15 @@ pub impl HarfbuzzShaper {
} }
static priv fn float_to_fixed(f: float) -> i32 { static priv fn float_to_fixed(f: float) -> i32 {
util::float_to_fixed(16, f) float_to_fixed(16, f)
} }
static priv fn fixed_to_float(i: hb_position_t) -> float { static priv fn fixed_to_float(i: hb_position_t) -> float {
util::fixed_to_float(16, i) fixed_to_float(16, i)
} }
static priv fn fixed_to_rounded_int(f: hb_position_t) -> int { static priv fn fixed_to_rounded_int(f: hb_position_t) -> int {
util::fixed_to_rounded_int(16, f) fixed_to_rounded_int(16, f)
} }
} }

View file

@ -6,6 +6,7 @@ Currently, only harfbuzz bindings are implemented.
*/ */
use gfx_font::Font; use gfx_font::Font;
use text::glyph::GlyphStore; use text::glyph::GlyphStore;
use harfbuzz;
pub type Shaper/& = harfbuzz::shaper::HarfbuzzShaper; pub type Shaper/& = harfbuzz::shaper::HarfbuzzShaper;

View file

@ -35,6 +35,8 @@ use std::arc::{ARC, clone};
use std::cell::Cell; use std::cell::Cell;
use std::net::url::Url; use std::net::url::Url;
use url_to_str = std::net::url::to_str; use url_to_str = std::net::url::to_str;
use dom;
use html;
pub enum ControlMsg { pub enum ControlMsg {
ParseMsg(Url), ParseMsg(Url),
@ -174,7 +176,7 @@ impl Content {
fn handle_control_msg(control_msg: ControlMsg) -> bool { fn handle_control_msg(control_msg: ControlMsg) -> bool {
match move control_msg { match move control_msg {
ParseMsg(move url) => { ParseMsg(move url) => {
debug!("content: Received url `%s` to parse", url_to_str(copy url)); debug!("content: Received url `%s` to parse", url_to_str(&url));
// Note: we can parse the next document in parallel // Note: we can parse the next document in parallel
// with any previous documents. // with any previous documents.
@ -241,11 +243,11 @@ impl Content {
ExecuteMsg(url) => { ExecuteMsg(url) => {
debug!("content: Received url `%s` to execute", url_to_str(copy url)); debug!("content: Received url `%s` to execute", url_to_str(&url));
match read_whole_file(&Path(url.path)) { match read_whole_file(&Path(url.path)) {
Err(msg) => { Err(msg) => {
println(fmt!("Error opening %s: %s", url_to_str(copy url), msg)); println(fmt!("Error opening %s: %s", url_to_str(&url), msg));
} }
Ok(move bytes) => { Ok(move bytes) => {
let compartment = option::expect(self.compartment, ~"TODO error checking"); let compartment = option::expect(self.compartment, ~"TODO error checking");

View file

@ -29,11 +29,12 @@ fn default_url(name: &str) -> Url {
fn style_stream(style: &str) -> DataStream { fn style_stream(style: &str) -> DataStream {
let style = Cell(str::to_bytes(style)); let style = Cell(str::to_bytes(style));
|move style| if !style.is_empty() { let d: DataStream = |move style| if !style.is_empty() {
Some(style.take()) Some(style.take())
} else { } else {
None None
} };
return d;
} }
fn html4_default_style_str() -> ~str { fn html4_default_style_str() -> ~str {

View file

@ -14,6 +14,8 @@ use dom::bindings::utils::{DOMString, domstring_to_jsval, rust_box, squirrel_awa
use dom::bindings::node::create; use dom::bindings::node::create;
use dom::document::Document; use dom::document::Document;
use dom::bindings::node;
use dom::bindings::utils;
enum DOMException { enum DOMException {
INVALID_CHARACTER_ERR INVALID_CHARACTER_ERR

View file

@ -19,7 +19,7 @@ use dom::bindings::utils::{str};
use libc::c_uint; use libc::c_uint;
use ptr::null; use ptr::null;
use dom::bindings::node::unwrap; use dom::bindings::node::unwrap;
use super::utils;
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
debug!("element finalize!"); debug!("element finalize!");
@ -75,10 +75,10 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
let node = (*bundle).payload.node; let node = (*bundle).payload.node;
let scope = (*bundle).payload.scope; let scope = (*bundle).payload.scope;
let width = scope.write(&node, |nd| { let width = scope.write(&node, |nd| {
match nd.kind { match &nd.kind {
~Element(ed) => { &~Element(ref ed) => {
match ed.kind { match &ed.kind {
~HTMLImageElement(*) => { &~HTMLImageElement(*) => {
let content = task_from_context(cx); let content = task_from_context(cx);
match (*content).query_layout(layout_task::ContentBox(node)) { match (*content).query_layout(layout_task::ContentBox(node)) {
Ok(rect) => rect.width, Ok(rect) => rect.width,
@ -152,13 +152,13 @@ extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe { pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe {
let proto = scope.write(&node, |nd| { let proto = scope.write(&node, |nd| {
match nd.kind { match &nd.kind {
~Element(ed) => { &~Element(ref ed) => {
match ed.kind { match &ed.kind {
~HTMLDivElement(*) => ~"HTMLDivElement", &~HTMLDivElement(*) => ~"HTMLDivElement",
~HTMLHeadElement(*) => ~"HTMLHeadElement", &~HTMLHeadElement(*) => ~"HTMLHeadElement",
~HTMLImageElement(*) => ~"HTMLImageElement", &~HTMLImageElement(*) => ~"HTMLImageElement",
~HTMLScriptElement(*) => ~"HTMLScriptElement", &~HTMLScriptElement(*) => ~"HTMLScriptElement",
_ => ~"HTMLElement" _ => ~"HTMLElement"
} }
} }

View file

@ -14,6 +14,9 @@ use dom::bindings::utils::{rust_box, squirrel_away_unique, get_compartment, doms
use dom::bindings::utils::{str}; use dom::bindings::utils::{str};
use libc::c_uint; use libc::c_uint;
use ptr::null; use ptr::null;
use super::utils;
use super::element;
use js;
pub fn init(compartment: &bare_compartment) { pub fn init(compartment: &bare_compartment) {
let obj = utils::define_empty_prototype(~"Node", None, compartment); let obj = utils::define_empty_prototype(~"Node", None, compartment);

View file

@ -1,3 +1,4 @@
use js;
use js::rust::{compartment, bare_compartment, methods}; use js::rust::{compartment, bare_compartment, methods};
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
JS_THIS_OBJECT, JS_SET_RVAL}; JS_THIS_OBJECT, JS_SET_RVAL};
@ -96,7 +97,7 @@ extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSB
} }
pub fn prototype_jsclass(name: ~str) -> @fn(compartment: &bare_compartment) -> JSClass { pub fn prototype_jsclass(name: ~str) -> @fn(compartment: &bare_compartment) -> JSClass {
|compartment: &bare_compartment, move name| { let f: @fn(&bare_compartment) -> JSClass = |compartment: &bare_compartment, move name| {
{name: compartment.add_name(copy name), {name: compartment.add_name(copy name),
flags: 0, flags: 0,
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8, addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
@ -120,11 +121,13 @@ pub fn prototype_jsclass(name: ~str) -> @fn(compartment: &bare_compartment) -> J
null(), null(), null(), null(), null(), // 30 null(), null(), null(), null(), null(), // 30
null(), null(), null(), null(), null(), // 35 null(), null(), null(), null(), null(), // 35
null(), null(), null(), null(), null())} // 40 null(), null(), null(), null(), null())} // 40
} };
return f;
} }
pub fn instance_jsclass(name: ~str, finalize: *u8) pub fn instance_jsclass(name: ~str, finalize: *u8)
-> @fn(compartment: &bare_compartment) -> JSClass { -> @fn(compartment: &bare_compartment) -> JSClass {
let f: @fn(&bare_compartment) -> JSClass =
|compartment: &bare_compartment, move name| { |compartment: &bare_compartment, move name| {
{name: compartment.add_name(copy name), {name: compartment.add_name(copy name),
flags: JSCLASS_HAS_RESERVED_SLOTS(1), flags: JSCLASS_HAS_RESERVED_SLOTS(1),
@ -149,13 +152,14 @@ pub fn instance_jsclass(name: ~str, finalize: *u8)
null(), null(), null(), null(), null(), // 30 null(), null(), null(), null(), null(), // 30
null(), null(), null(), null(), null(), // 35 null(), null(), null(), null(), null(), // 35
null(), null(), null(), null(), null())} // 40 null(), null(), null(), null(), null())} // 40
} };
return f;
} }
// FIXME: A lot of string copies here // FIXME: A lot of string copies here
pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: &bare_compartment) pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: &bare_compartment)
-> js::rust::jsobj { -> js::rust::jsobj {
compartment.register_class(utils::prototype_jsclass(copy name)); compartment.register_class(prototype_jsclass(copy name));
//TODO error checking //TODO error checking
let obj = result::unwrap( let obj = result::unwrap(

View file

@ -16,6 +16,7 @@ use dom::bindings::node::create;
use dom::window::{Window, TimerMessage_Fire}; use dom::window::{Window, TimerMessage_Fire};
use dom::node::Node; use dom::node::Node;
use core::dvec::DVec; use core::dvec::DVec;
use super::utils;
extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {

View file

@ -15,6 +15,7 @@ use layout::flow::FlowContext;
use ptr::null; use ptr::null;
use std::arc::ARC; use std::arc::ARC;
use util::tree; use util::tree;
use super::cow;
pub enum NodeData = { pub enum NodeData = {
tree: tree::Tree<Node>, tree: tree::Tree<Node>,
@ -175,7 +176,7 @@ impl NodeScope {
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
impl NodeScope : tree::WriteMethods<Node> { impl NodeScope : tree::WriteMethods<Node> {
pure fn eq(a: &Node, b: &Node) -> bool { a == b } pure fn tree_eq(a: &Node, b: &Node) -> bool { a == b }
fn with_tree_fields<R>(node: &Node, f: fn(&tree::Tree<Node>) -> R) -> R { fn with_tree_fields<R>(node: &Node, f: fn(&tree::Tree<Node>) -> R) -> R {
self.write(node, |n| f(&n.tree)) self.write(node, |n| f(&n.tree))

View file

@ -3,6 +3,8 @@ use content::content_task::{ControlMsg, Timer, ExitMsg};
use js::jsapi::JSVal; use js::jsapi::JSVal;
use dvec::DVec; use dvec::DVec;
use util::task::spawn_listener; use util::task::spawn_listener;
use std::timer;
use std::uv_global_loop;
pub enum TimerControlMsg { pub enum TimerControlMsg {
TimerMessage_Fire(~TimerData), TimerMessage_Fire(~TimerData),
@ -58,9 +60,9 @@ impl Window {
// Post a delayed message to the per-window timer task; it will dispatch it // Post a delayed message to the per-window timer task; it will dispatch it
// to the relevant content handler that will deal with it. // to the relevant content handler that will deal with it.
std::timer::delayed_send(std::uv_global_loop::get(), timer::delayed_send(uv_global_loop::get(),
timeout, self.timer_chan, timeout, self.timer_chan,
TimerMessage_Fire(~TimerData(argc, argv))); TimerMessage_Fire(~TimerData(argc, argv)));
} }
} }

View file

@ -10,6 +10,7 @@ use newcss::util::DataStream;
use std::cell::Cell; use std::cell::Cell;
use std::net::url::Url; use std::net::url::Url;
use std::net::url; use std::net::url;
use core::oldcomm::{Port, Chan};
/// Where a style sheet comes from. /// Where a style sheet comes from.
pub enum StylesheetProvenance { pub enum StylesheetProvenance {

View file

@ -1,3 +1,4 @@
use gfx::util::url::make_url;
use au = gfx::geometry; use au = gfx::geometry;
use content::content_task::ContentTask; use content::content_task::ContentTask;
use dom::cow; use dom::cow;

View file

@ -10,6 +10,7 @@ use layout::context::LayoutContext;
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use util::tree; use util::tree;
use core::mutable::Mut;
pub struct BlockFlowData { pub struct BlockFlowData {
mut box: Option<@RenderBox> mut box: Option<@RenderBox>
@ -29,7 +30,7 @@ trait BlockLayout {
fn assign_widths_block(@self, ctx: &LayoutContext); fn assign_widths_block(@self, ctx: &LayoutContext);
fn assign_height_block(@self, ctx: &LayoutContext); fn assign_height_block(@self, ctx: &LayoutContext);
fn build_display_list_block(@self, a: &DisplayListBuilder, b: &Rect<Au>, fn build_display_list_block(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &mut DisplayList); c: &Point2D<Au>, d: &Mut<DisplayList>);
} }
impl FlowContext : BlockLayout { impl FlowContext : BlockLayout {
@ -143,7 +144,7 @@ impl FlowContext : BlockLayout {
} }
fn build_display_list_block(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_block(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) { offset: &Point2D<Au>, list: &Mut<DisplayList>) {
assert self.starts_block_flow(); assert self.starts_block_flow();

View file

@ -7,14 +7,17 @@ use layout::debug::BoxedDebugMethods;
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use layout;
use util::tree::ReadMethods; use util::tree::ReadMethods;
use core::mutable::Mut;
use arc = std::arc; use arc = std::arc;
use core::managed;
use core::dvec::DVec; use core::dvec::DVec;
use core::to_str::ToStr; use core::to_str::ToStr;
use core::rand; use core::rand;
use core::task::spawn; use core::task::spawn;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx;
use gfx::display_list::{DisplayItem, DisplayList}; use gfx::display_list::{DisplayItem, DisplayList};
use gfx::font::{FontStyle, FontWeight300}; use gfx::font::{FontStyle, FontWeight300};
use gfx::geometry::Au; use gfx::geometry::Au;
@ -147,13 +150,13 @@ impl RenderBox {
} }
fn can_merge_with_box(@self, other: @RenderBox) -> bool { fn can_merge_with_box(@self, other: @RenderBox) -> bool {
assert !core::managed::ptr_eq(self, other); assert !managed::ptr_eq(self, other);
match (self, other) { match (self, other) {
(@UnscannedTextBox(*), @UnscannedTextBox(*)) => { (@UnscannedTextBox(*), @UnscannedTextBox(*)) => {
self.font_style() == other.font_style() self.font_style() == other.font_style()
}, },
(@TextBox(_, ref d1), @TextBox(_, ref d2)) => core::managed::ptr_eq(d1.run, d2.run), (@TextBox(_, ref d1), @TextBox(_, ref d2)) => managed::ptr_eq(d1.run, d2.run),
(_, _) => false (_, _) => false
} }
} }
@ -244,7 +247,7 @@ impl RenderBox {
&GenericBox(*) => Au(0), &GenericBox(*) => Au(0),
// TODO: consult CSS 'width', margin, border. // TODO: consult CSS 'width', margin, border.
// TODO: If image isn't available, consult 'width'. // TODO: If image isn't available, consult 'width'.
&ImageBox(_, ref i) => Au::from_px(i.get_size().get_default(Size2D(0,0)).width), &ImageBox(_, ref i) => Au::from_px(i.get_size().get_or_default(Size2D(0,0)).width),
&TextBox(_,d) => d.run.min_width_for_range(&const d.range), &TextBox(_,d) => d.run.min_width_for_range(&const d.range),
&UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here." &UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here."
} }
@ -258,7 +261,7 @@ impl RenderBox {
// FlowContext will combine the width of this element and // FlowContext will combine the width of this element and
// that of its children to arrive at the context width. // that of its children to arrive at the context width.
&GenericBox(*) => Au(0), &GenericBox(*) => Au(0),
&ImageBox(_, ref i) => Au::from_px(i.get_size().get_default(Size2D(0,0)).width), &ImageBox(_, ref i) => Au::from_px(i.get_size().get_or_default(Size2D(0,0)).width),
// a text box cannot span lines, so assume that this is an unsplit text box. // a text box cannot span lines, so assume that this is an unsplit text box.
@ -380,7 +383,7 @@ impl RenderBox {
* `list` - List to which items should be appended * `list` - List to which items should be appended
*/ */
fn build_display_list(@self, _builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list(@self, _builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) { offset: &Point2D<Au>, list: &Mut<DisplayList>) {
let box_bounds = self.d().position; let box_bounds = self.d().position;
@ -400,28 +403,30 @@ impl RenderBox {
match self { match self {
@UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.", @UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.",
@TextBox(_,data) => { @TextBox(_,data) => {
let nearest_ancestor_element = self.nearest_ancestor_element(); do list.borrow_mut |list| {
let color = nearest_ancestor_element.style().color().to_gfx_color(); let nearest_ancestor_element = self.nearest_ancestor_element();
list.append_item(~DisplayItem::new_Text(&abs_box_bounds, let color = nearest_ancestor_element.style().color().to_gfx_color();
~data.run.serialize(), list.append_item(~DisplayItem::new_Text(&abs_box_bounds,
data.range, ~data.run.serialize(),
color)); data.range,
// debug frames for text box bounds color));
debug!("%?", { // debug frames for text box bounds
// text box bounds debug!("%?", {
list.append_item(~DisplayItem::new_Border(&abs_box_bounds, // text box bounds
Au::from_px(1), list.append_item(~DisplayItem::new_Border(&abs_box_bounds,
rgb(0, 0, 200).to_gfx_color())); Au::from_px(1),
// baseline "rect" rgb(0, 0, 200).to_gfx_color()));
// TODO(Issue #221): create and use a Line display item for baseline. // baseline "rect"
let ascent = data.run.metrics_for_range(&data.range).ascent; // TODO(Issue #221): create and use a Line display item for baseline.
let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent), let ascent = data.run.metrics_for_range(&data.range).ascent;
Size2D(abs_box_bounds.size.width, Au(0))); let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent),
Size2D(abs_box_bounds.size.width, Au(0)));
list.append_item(~DisplayItem::new_Border(&baseline,
Au::from_px(1), list.append_item(~DisplayItem::new_Border(&baseline,
rgb(0, 200, 0).to_gfx_color())); Au::from_px(1),
; ()}); rgb(0, 200, 0).to_gfx_color()));
; ()});
}
}, },
// TODO: items for background, border, outline // TODO: items for background, border, outline
@GenericBox(_) => { @GenericBox(_) => {
@ -429,9 +434,11 @@ impl RenderBox {
@ImageBox(_, ref i) => { @ImageBox(_, ref i) => {
match i.get_image() { match i.get_image() {
Some(image) => { Some(image) => {
debug!("(building display list) building image box"); do list.borrow_mut |list| {
list.append_item(~DisplayItem::new_Image(&abs_box_bounds, debug!("(building display list) building image box");
arc::clone(&image))); list.append_item(~DisplayItem::new_Image(&abs_box_bounds,
arc::clone(&image)));
}
} }
None => { None => {
/* No image data at all? Okay, add some fallback content instead. */ /* No image data at all? Okay, add some fallback content instead. */
@ -444,7 +451,7 @@ impl RenderBox {
self.add_border_to_list(list, &abs_box_bounds); self.add_border_to_list(list, &abs_box_bounds);
} }
fn add_bgcolor_to_list(@self, list: &mut DisplayList, abs_bounds: &Rect<Au>) { fn add_bgcolor_to_list(@self, list: &Mut<DisplayList>, abs_bounds: &Rect<Au>) {
use std::cmp::FuzzyEq; use std::cmp::FuzzyEq;
// FIXME: This causes a lot of background colors to be displayed when they are clearly not // FIXME: This causes a lot of background colors to be displayed when they are clearly not
@ -455,11 +462,13 @@ impl RenderBox {
let bgcolor = nearest_ancestor_element.style().background_color(); let bgcolor = nearest_ancestor_element.style().background_color();
if !bgcolor.alpha.fuzzy_eq(&0.0) { if !bgcolor.alpha.fuzzy_eq(&0.0) {
list.append_item(~DisplayItem::new_SolidColor(abs_bounds, bgcolor.to_gfx_color())); do list.borrow_mut |list| {
list.append_item(~DisplayItem::new_SolidColor(abs_bounds, bgcolor.to_gfx_color()));
}
} }
} }
fn add_border_to_list(list: &mut DisplayList, abs_bounds: &Rect<Au>) { fn add_border_to_list(list: &Mut<DisplayList>, abs_bounds: &Rect<Au>) {
if !self.d().node.is_element() { return } if !self.d().node.is_element() { return }
let top_width = self.style().border_top_width(); let top_width = self.style().border_top_width();
@ -494,7 +503,9 @@ impl RenderBox {
let top_color = self.style().border_top_color(); let top_color = self.style().border_top_color();
let color = top_color.to_gfx_color(); // FIXME let color = top_color.to_gfx_color(); // FIXME
list.append_item(~DisplayItem::new_Border(&bounds, border_width, color)); do list.borrow_mut |list| {
list.append_item(~DisplayItem::new_Border(&bounds, border_width, color));
}
} else { } else {
warn!("ignoring unimplemented border widths"); warn!("ignoring unimplemented border widths");

View file

@ -1,5 +1,6 @@
/** Creates CSS boxes from a DOM. */ /** Creates CSS boxes from a DOM. */
use dom;
use dom::element::*; use dom::element::*;
use dom::node::{Comment, Doctype, Element, Text, Node, LayoutData}; use dom::node::{Comment, Doctype, Element, Text, Node, LayoutData};
use layout::box::*; use layout::box::*;

View file

@ -15,9 +15,10 @@ use layout::flow::FlowContext;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use util::tree; use util::tree;
use vec::push; use vec::push;
use gfx;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::geometry::Au; use gfx::geometry::Au;
use core::mutable::Mut;
/** A builder object that manages display list builder should mainly /** A builder object that manages display list builder should mainly
hold information about the initial request and desired result---for hold information about the initial request and desired result---for
@ -32,15 +33,15 @@ pub struct DisplayListBuilder {
trait FlowDisplayListBuilderMethods { trait FlowDisplayListBuilderMethods {
fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &mut DisplayList); fn build_display_list(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Mut<DisplayList>);
fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext, fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext,
c: &Rect<Au>, d: &Point2D<Au>, e: &mut DisplayList); c: &Rect<Au>, d: &Point2D<Au>, e: &Mut<DisplayList>);
} }
impl FlowContext: FlowDisplayListBuilderMethods { impl FlowContext: FlowDisplayListBuilderMethods {
fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
list: &mut DisplayList) { list: &Mut<DisplayList>) {
let zero = gfx::geometry::zero_point(); let zero = gfx::geometry::zero_point();
self.build_display_list_recurse(builder, dirty, &zero, list); self.build_display_list_recurse(builder, dirty, &zero, list);
} }
@ -49,7 +50,7 @@ impl FlowContext: FlowDisplayListBuilderMethods {
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
child_flow: @FlowContext, child_flow: @FlowContext,
dirty: &Rect<Au>, offset: &Point2D<Au>, dirty: &Rect<Au>, offset: &Point2D<Au>,
list: &mut DisplayList) { list: &Mut<DisplayList>) {
// adjust the dirty rect to child flow context coordinates // adjust the dirty rect to child flow context coordinates
let abs_flow_bounds = child_flow.d().position.translate(offset); let abs_flow_bounds = child_flow.d().position.translate(offset);

View file

@ -1,3 +1,4 @@
use core;
use dom::node::Node; use dom::node::Node;
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::box::RenderBox; use layout::box::RenderBox;
@ -7,7 +8,7 @@ use layout::display_list_builder::DisplayListBuilder;
use layout::inline::{InlineFlowData, NodeRange}; use layout::inline::{InlineFlowData, NodeRange};
use layout::root::RootFlowData; use layout::root::RootFlowData;
use util::tree; use util::tree;
use core::mutable::Mut;
use core::dvec::DVec; use core::dvec::DVec;
use geom::rect::Rect; use geom::rect::Rect;
use geom::point::Point2D; use geom::point::Point2D;
@ -154,7 +155,7 @@ impl FlowContext {
} }
fn build_display_list_recurse(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_recurse(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) { offset: &Point2D<Au>, list: &Mut<DisplayList>) {
debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str()); debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str());
match self { match self {
@ -224,7 +225,7 @@ impl FlowTree {
impl FlowTree : tree::WriteMethods<@FlowContext> { impl FlowTree : tree::WriteMethods<@FlowContext> {
pure fn eq(a: &@FlowContext, b: &@FlowContext) -> bool { core::managed::ptr_eq(*a, *b) } pure fn tree_eq(a: &@FlowContext, b: &@FlowContext) -> bool { core::managed::ptr_eq(*a, *b) }
fn with_tree_fields<R>(box: &@FlowContext, f: fn(&tree::Tree<@FlowContext>) -> R) -> R { fn with_tree_fields<R>(box: &@FlowContext, f: fn(&tree::Tree<@FlowContext>) -> R) -> R {
f(&box.d().tree) f(&box.d().tree)

View file

@ -1,3 +1,4 @@
use core;
use dom::node::Node; use dom::node::Node;
use layout::box::*; use layout::box::*;
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -585,7 +586,7 @@ trait InlineLayout {
fn assign_widths_inline(@self, ctx: &LayoutContext); fn assign_widths_inline(@self, ctx: &LayoutContext);
fn assign_height_inline(@self, ctx: &LayoutContext); fn assign_height_inline(@self, ctx: &LayoutContext);
fn build_display_list_inline(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>, fn build_display_list_inline(@self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>,
d: &mut DisplayList); d: &Mut<DisplayList>);
} }
impl FlowContext : InlineLayout { impl FlowContext : InlineLayout {
@ -622,7 +623,7 @@ impl FlowContext : InlineLayout {
for self.inline().boxes.each |box| { for self.inline().boxes.each |box| {
box.d().position.size.width = match *box { box.d().position.size.width = match *box {
@ImageBox(_, ref img) => { @ImageBox(_, ref img) => {
Au::from_px(img.get_size().get_default(Size2D(0,0)).width) Au::from_px(img.get_size().get_or_default(Size2D(0,0)).width)
} }
@TextBox(*) => { /* text boxes are initialized with dimensions */ @TextBox(*) => { /* text boxes are initialized with dimensions */
box.d().position.size.width box.d().position.size.width
@ -718,7 +719,7 @@ impl FlowContext : InlineLayout {
} }
fn build_display_list_inline(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_inline(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) { offset: &Point2D<Au>, list: &Mut<DisplayList>) {
assert self.starts_inline_flow(); assert self.starts_inline_flow();

View file

@ -233,16 +233,20 @@ impl Layout {
let builder = DisplayListBuilder { let builder = DisplayListBuilder {
ctx: &layout_ctx, ctx: &layout_ctx,
}; };
let mut render_layer = RenderLayer {
display_list: DisplayList::new(), let display_list = Mut(DisplayList::new());
// TODO: set options on the builder before building
// TODO: be smarter about what needs painting
layout_root.build_display_list(&builder, &copy layout_root.d().position,
&display_list);
let render_layer = RenderLayer {
display_list: display_list.unwrap(),
size: Size2D(screen_size.width.to_px() as uint, size: Size2D(screen_size.width.to_px() as uint,
screen_size.height.to_px() as uint) screen_size.height.to_px() as uint)
}; };
// TODO: set options on the builder before building
// TODO: be smarter about what needs painting
layout_root.build_display_list(&builder, &copy layout_root.d().position,
&mut render_layer.display_list);
self.render_task.send(RenderMsg(move render_layer)); self.render_task.send(RenderMsg(move render_layer));
} // time(layout: display list building) } // time(layout: display list building)

View file

@ -9,6 +9,7 @@ use layout::context::LayoutContext;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use util::tree; use util::tree;
use core::mutable::Mut;
pub struct RootFlowData { pub struct RootFlowData {
mut box: Option<@RenderBox> mut box: Option<@RenderBox>
@ -27,7 +28,7 @@ trait RootLayout {
fn assign_widths_root(@self, ctx: &LayoutContext); fn assign_widths_root(@self, ctx: &LayoutContext);
fn assign_height_root(@self, ctx: &LayoutContext); fn assign_height_root(@self, ctx: &LayoutContext);
fn build_display_list_root(@self, a: &DisplayListBuilder, b: &Rect<Au>, fn build_display_list_root(@self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &mut DisplayList); c: &Point2D<Au>, d: &Mut<DisplayList>);
} }
impl FlowContext : RootLayout { impl FlowContext : RootLayout {
@ -76,7 +77,7 @@ impl FlowContext : RootLayout {
} }
fn build_display_list_root(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_root(@self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &mut DisplayList) { offset: &Point2D<Au>, list: &Mut<DisplayList>) {
assert self.starts_root_flow(); assert self.starts_root_flow();
self.build_display_list_block(builder, dirty, offset, list); self.build_display_list_block(builder, dirty, offset, list);

View file

@ -18,6 +18,9 @@ use layers::layers::ImageLayer;
use std::cell::Cell; use std::cell::Cell;
use std::cmp::FuzzyEq; use std::cmp::FuzzyEq;
use glut::glut; use glut::glut;
use layers;
use sharegl;
use sharegl::ShareGlContext;
pub struct OSMain { pub struct OSMain {
chan: oldcomm::Chan<Msg> chan: oldcomm::Chan<Msg>

View file

@ -18,7 +18,7 @@ pub trait ReadMethods<T> {
pub trait WriteMethods<T> { pub trait WriteMethods<T> {
fn with_tree_fields<R>(&T, f: fn(&Tree<T>) -> R) -> R; fn with_tree_fields<R>(&T, f: fn(&Tree<T>) -> R) -> R;
pure fn eq(&T, &T) -> bool; pure fn tree_eq(&T, &T) -> bool;
} }
pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: fn(&T) -> bool) { pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: fn(&T) -> bool) {
@ -35,7 +35,7 @@ pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: fn(&T) -> bool)
} }
pub fn is_leaf<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> bool { pub fn is_leaf<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> bool {
tree::first_child(ops, node).is_none() first_child(ops, node).is_none()
} }
pub fn first_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> Option<T> { pub fn first_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> Option<T> {
@ -67,7 +67,7 @@ pub fn empty<T>() -> Tree<T> {
} }
pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) { pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
assert !ops.eq(&parent, &child); assert !ops.tree_eq(&parent, &child);
ops.with_tree_fields(&child, |child_tf| { ops.with_tree_fields(&child, |child_tf| {
match child_tf.parent { match child_tf.parent {
@ -102,13 +102,13 @@ pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
match copy child_tf.parent { match copy child_tf.parent {
None => { fail ~"Not a child"; } None => { fail ~"Not a child"; }
Some(parent_n) => { Some(parent_n) => {
assert ops.eq(&parent, &parent_n); assert ops.tree_eq(&parent, &parent_n);
// adjust parent fields // adjust parent fields
do ops.with_tree_fields(&parent) |parent_tf| { do ops.with_tree_fields(&parent) |parent_tf| {
match copy parent_tf.first_child { match copy parent_tf.first_child {
None => { fail ~"parent had no first child??" }, None => { fail ~"parent had no first child??" },
Some(first_child) if ops.eq(&child, &first_child) => { Some(first_child) if ops.tree_eq(&child, &first_child) => {
parent_tf.first_child = child_tf.next_sibling; parent_tf.first_child = child_tf.next_sibling;
}, },
Some(_) => {} Some(_) => {}
@ -116,7 +116,7 @@ pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
match copy parent_tf.last_child { match copy parent_tf.last_child {
None => { fail ~"parent had no last child??" }, None => { fail ~"parent had no last child??" },
Some(last_child) if ops.eq(&child, &last_child) => { Some(last_child) if ops.tree_eq(&child, &last_child) => {
parent_tf.last_child = child_tf.prev_sibling; parent_tf.last_child = child_tf.prev_sibling;
}, },
Some(_) => {} Some(_) => {}