Upgrade for language changes

This commit is contained in:
Patrick Walton 2013-02-08 21:50:37 -08:00
parent a7bfc99356
commit 0458783bc7
73 changed files with 755 additions and 680 deletions

4
configure vendored
View file

@ -391,7 +391,7 @@ if [ $CFG_OSTYPE = "apple-darwin" ]
then then
# pkg-config is installed in a different place on mac (via homebrew? not sure) # pkg-config is installed in a different place on mac (via homebrew? not sure)
# and the way to set this seems to be calling aclocal by hand (instead of via autoreconf) # and the way to set this seems to be calling aclocal by hand (instead of via autoreconf)
OSX_PKG_CONFIG_M4_MACROS="-I/usr/local/share/aclocal" OSX_PKG_CONFIG_M4_MACROS="-I/usr/share/aclocal -I/usr/local/share/aclocal"
LIBTOOLIZE=glibtoolize LIBTOOLIZE=glibtoolize
else else
OSX_PKG_CONFIG_M4_MACROS="" OSX_PKG_CONFIG_M4_MACROS=""
@ -400,7 +400,7 @@ fi
PIXMAN_ACLOCALCMD="aclocal ${OSX_PKG_CONFIG_M4_MACROS}" PIXMAN_ACLOCALCMD="aclocal ${OSX_PKG_CONFIG_M4_MACROS}"
CAIRO_ACLOCALCMD="aclocal ${OSX_PKG_CONFIG_M4_MACROS} -Ibuild" CAIRO_ACLOCALCMD="aclocal ${OSX_PKG_CONFIG_M4_MACROS} -Ibuild"
AUTOCMD="${LIBTOOLIZE} && autoconf && autoheader && automake --add-missing --copy --no-force" AUTOCMD="${LIBTOOLIZE} && autoconf && autoheader && automake --add-missing --copy --force"
# Copied from cairo's autogen.sh. Build fails without # Copied from cairo's autogen.sh. Build fails without
CAIRO_BOILERPLATE="touch boilerplate/Makefile.am.features && touch src/Makefile.am.features" CAIRO_BOILERPLATE="touch boilerplate/Makefile.am.features && touch src/Makefile.am.features"
PIXMAN_AUTOCMD="${PIXMAN_ACLOCALCMD} && ${AUTOCMD}" PIXMAN_AUTOCMD="${PIXMAN_ACLOCALCMD} && ${AUTOCMD}"

@ -1 +1 @@
Subproject commit e447521c1ca2dbead5b485ddc43060b282840817 Subproject commit af82457af293e2a842ba6b7759b70288da276167

@ -1 +1 @@
Subproject commit 8c20ce62b372db2015856ec7ef7d5da36da705f7 Subproject commit fb528b1232c74403c52955a5d305a9ae6d532723

@ -1 +1 @@
Subproject commit d0f334ec07a884472d3de7f5f9ab11d62193ccfa Subproject commit 349ccf644408358debab0cde6da8c574a936411e

@ -1 +1 @@
Subproject commit c6dc3d8b0a3b94b7134213a4d01599484d4a8927 Subproject commit bf9e050161c55ce06f8e7491e15ceff06079d937

@ -1 +1 @@
Subproject commit 990b2751019a750d23d22ad777fe54d786aa1ce8 Subproject commit 01d8691bdf721edebb0e563069ffb23ba123bef0

@ -1 +1 @@
Subproject commit 4ef941f09e58c122c96f15cecc7bd97e145bed01 Subproject commit f53aaa1cdc5b210d5390be71b92e7c8cc51ac8d2

@ -1 +1 @@
Subproject commit d54ba38e73e2d46f713cf148a44a829d41db44bd Subproject commit b8382613e38459101a7b42b9a1fa5dbb40c8644c

@ -1 +1 @@
Subproject commit 7d67731550afbe7657508ec6e437e2cd18161336 Subproject commit bb4952656c180cb263aa8c437b1691670a76fe66

@ -1 +1 @@
Subproject commit e0e4dab1caea0bbfa8a4e9b22b7ae04762d1d5f2 Subproject commit 7fd0efc2e7dbfdc6e7db79537ac13b2c752a2284

@ -1 +1 @@
Subproject commit 25e58c3ba2a8aed701553b811dfab639824a6553 Subproject commit 12106aba8797163a958ce97dacb2900e931f1cc5

@ -1 +1 @@
Subproject commit 77d9e83b730f8202de56699d1dd6eaeb66fd5e29 Subproject commit 0961ae2fc54e71838dd495bd91f5b7aa5afa1993

@ -1 +1 @@
Subproject commit f8782334fedc35491ee8ba0e521fc0290ecf5cc6 Subproject commit aa3af27f6ea1f08539004bdb957978bb2b15ef29

@ -1 +1 @@
Subproject commit 58fb6a2570eabc2de73727bc022e3247c99e5bba Subproject commit 4d62a3f9ac1b8ac1c4298a274b476914ded8333a

@ -1 +1 @@
Subproject commit 61ec64cbb17f0f14a2306ab9ab04565b622ccf77 Subproject commit dbc46d10beb7e2c542f90ea13952b0c5514667d7

@ -1 +1 @@
Subproject commit 5efa43df1177da86d0ef1e783650b82a0928634b Subproject commit abd987990ba5faf23137d46c642dc1fdc3606791

@ -1 +1 @@
Subproject commit bc06cf6a1771c13755051b51c919dddf73b60a5f Subproject commit 2ebaccbd8519cb11576a812a6ba5f0340fa8706f

@ -1 +1 @@
Subproject commit 1e89a5e143fc1349a945decb5e0c91ad62356e15 Subproject commit 23ba9e84d5cd849a406ee22f37db5babdff10bc9

@ -1 +1 @@
Subproject commit 352c9f8359d196e453c5e2fc8d45785b852668c9 Subproject commit 1713d537a8f9cc88ddb8b587e16720b059f9c8f8

View file

@ -90,18 +90,11 @@ pub struct DisplayList {
list: ~[~DisplayItem] list: ~[~DisplayItem]
} }
trait DisplayListMethods {
fn append_item(&mut self, item: ~DisplayItem);
fn draw_into_context(ctx: &RenderContext);
}
pub impl DisplayList { pub impl DisplayList {
static fn new() -> DisplayList { static fn new() -> DisplayList {
DisplayList { list: ~[] } DisplayList { list: ~[] }
} }
}
impl DisplayList : DisplayListMethods {
fn append_item(&mut self, item: ~DisplayItem) { fn append_item(&mut self, item: ~DisplayItem) {
// FIXME(Issue #150): crashes // FIXME(Issue #150): crashes
//debug!("Adding display item %u: %?", self.len(), item); //debug!("Adding display item %u: %?", self.len(), item);

View file

@ -4,9 +4,11 @@ use geometry::Au;
use render_context::RenderContext; use render_context::RenderContext;
use util::range::Range; use util::range::Range;
use text::glyph::{GlyphStore, GlyphIndex}; use text::glyph::{GlyphStore, GlyphIndex};
use text::shaper::ShaperMethods;
use text::{Shaper, TextRun}; use text::{Shaper, TextRun};
use azure::{AzFloat, AzScaledFontRef}; use azure::{AzFloat, AzScaledFontRef, struct__AzDrawOptions, struct__AzGlyph};
use azure::{struct__AzGlyphBuffer, struct__AzPoint};
use azure::scaled_font::ScaledFont; use azure::scaled_font::ScaledFont;
use azure::azure_hl::{BackendType, ColorPattern}; use azure::azure_hl::{BackendType, ColorPattern};
use core::dvec::DVec; use core::dvec::DVec;
@ -374,26 +376,8 @@ pub impl Font {
} }
} }
// Public API
pub trait FontMethods {
fn draw_text_into_context(rctx: &RenderContext,
run: &TextRun,
range: &Range,
baseline_origin: Point2D<Au>,
color: Color);
// This calculates run metrics for the specified character range
// within the provided textrun.
fn measure_text(&TextRun, &const Range) -> RunMetrics;
fn shape_text(@self, &str, &mut GlyphStore);
fn get_descriptor() -> FontDescriptor;
// these are used to get glyphs and advances in the case that the pub impl Font {
// shaper can't figure it out.
fn glyph_index(char) -> Option<GlyphIndex>;
fn glyph_h_advance(GlyphIndex) -> FractionalPixel;
}
pub impl Font : FontMethods {
fn draw_text_into_context(rctx: &RenderContext, fn draw_text_into_context(rctx: &RenderContext,
run: &TextRun, run: &TextRun,
range: &const Range, range: &const Range,
@ -413,7 +397,7 @@ pub impl Font : FontMethods {
let azure_pattern = pattern.azure_color_pattern; let azure_pattern = pattern.azure_color_pattern;
assert azure_pattern.is_not_null(); assert azure_pattern.is_not_null();
let options: AzDrawOptions = { let options = struct__AzDrawOptions {
mAlpha: 1f as AzFloat, mAlpha: 1f as AzFloat,
fields: 0x0200 as uint16_t fields: 0x0200 as uint16_t
}; };
@ -426,9 +410,9 @@ pub impl Font : FontMethods {
let glyph_advance = glyph.advance(); let glyph_advance = glyph.advance();
let glyph_offset = glyph.offset().get_or_default(Au::zero_point()); let glyph_offset = glyph.offset().get_or_default(Au::zero_point());
let azglyph: AzGlyph = { let azglyph = struct__AzGlyph {
mIndex: glyph.index() as uint32_t, mIndex: glyph.index() as uint32_t,
mPosition: { mPosition: struct__AzPoint {
x: (origin.x + glyph_offset.x).to_px() as AzFloat, x: (origin.x + glyph_offset.x).to_px() as AzFloat,
y: (origin.y + glyph_offset.y).to_px() as AzFloat y: (origin.y + glyph_offset.y).to_px() as AzFloat
} }
@ -441,10 +425,12 @@ pub impl Font : FontMethods {
if azglyph_buf_len == 0 { return; } // Otherwise the Quartz backend will assert. if azglyph_buf_len == 0 { return; } // Otherwise the Quartz backend will assert.
let azglyph_buf = dvec::unwrap(move azglyphs); let azglyph_buf = dvec::unwrap(move azglyphs);
let glyphbuf: AzGlyphBuffer = unsafe {{ let glyphbuf = unsafe {
struct__AzGlyphBuffer {
mGlyphs: vec::raw::to_ptr(azglyph_buf), mGlyphs: vec::raw::to_ptr(azglyph_buf),
mNumGlyphs: azglyph_buf_len as uint32_t mNumGlyphs: azglyph_buf_len as uint32_t
}}; }
};
// TODO(Issue #64): this call needs to move into azure_hl.rs // TODO(Issue #64): this call needs to move into azure_hl.rs
AzDrawTargetFillGlyphs(target.azure_draw_target, AzDrawTargetFillGlyphs(target.azure_draw_target,

View file

@ -1,4 +1,5 @@
use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle}; use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle};
use gfx_font::FontHandleMethods;
use native::FontHandle; use native::FontHandle;
use dvec::DVec; use dvec::DVec;
@ -82,13 +83,13 @@ pub impl FontList {
priv fn find_family(family_name: &str) -> Option<@FontFamily> { priv fn find_family(family_name: &str) -> Option<@FontFamily> {
// look up canonical name // look up canonical name
let family = self.family_map.find_copy(&str::from_slice(family_name)); let family = self.family_map.find(&str::from_slice(family_name));
let decision = if family.is_some() { "Found" } else { "Couldn't find" }; let decision = if family.is_some() { "Found" } else { "Couldn't find" };
debug!("FontList: %s font family with name=%s", decision, family_name); debug!("FontList: %s font family with name=%s", decision, family_name);
// TODO(Issue #188): look up localized font family names if canonical name not found // TODO(Issue #188): look up localized font family names if canonical name not found
return family; return family.map(|f| **f);
} }
} }

View file

@ -92,7 +92,7 @@ pub struct FreeTypeFontHandle {
drop { drop {
assert self.face.is_not_null(); assert self.face.is_not_null();
if !FT_Done_Face(self.face).succeeded() { if !FT_Done_Face(self.face).succeeded() {
fail ~"FT_Done_Face failed"; fail!(~"FT_Done_Face failed");
} }
} }
} }
@ -186,7 +186,6 @@ pub impl FreeTypeFontHandle {
} }
pub impl FreeTypeFontHandle : FontHandleMethods { pub impl FreeTypeFontHandle : FontHandleMethods {
// an identifier usable by FontContextHandle to recreate this FontHandle. // an identifier usable by FontContextHandle to recreate this FontHandle.
pure fn face_identifier() -> ~str { pure fn face_identifier() -> ~str {
/* FT_Get_Postscript_Name seems like a better choice here, but it /* FT_Get_Postscript_Name seems like a better choice here, but it

View file

@ -1,33 +1,43 @@
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 num::Num;
pub enum Au = i32; use core::num::NumCast;
impl Au : Num { pub struct Au(i32);
pub impl Add<Au,Au> for Au {
pure fn add(&self, other: &Au) -> Au { Au(**self + **other) } pure fn add(&self, other: &Au) -> Au { Au(**self + **other) }
pure fn sub(&self, other: &Au) -> Au { Au(**self - **other) }
pure fn mul(&self, other: &Au) -> Au { Au(**self * **other) }
pure fn div(&self, other: &Au) -> Au { Au(**self / **other) }
pure fn modulo(&self, other: &Au) -> Au { Au(**self % **other) }
pure fn neg(&self) -> Au { Au(-**self) }
pure fn to_int(&self) -> int { **self as int }
static pure fn from_int(n: int) -> Au {
Au((n & (i32::max_value as int)) as i32)
}
} }
impl Au : cmp::Ord { pub impl Sub<Au,Au> for Au {
pure fn sub(&self, other: &Au) -> Au { Au(**self - **other) }
}
pub impl Mul<Au,Au> for Au {
pure fn mul(&self, other: &Au) -> Au { Au(**self * **other) }
}
pub impl Div<Au,Au> for Au {
pure fn div(&self, other: &Au) -> Au { Au(**self / **other) }
}
pub impl Modulo<Au,Au> for Au {
pure fn modulo(&self, other: &Au) -> Au { Au(**self % **other) }
}
pub impl Neg<Au> for Au {
pure fn neg(&self) -> Au { Au(-**self) }
}
pub impl cmp::Ord for Au {
pure fn lt(&self, other: &Au) -> bool { **self < **other } pure fn lt(&self, other: &Au) -> bool { **self < **other }
pure fn le(&self, other: &Au) -> bool { **self <= **other } pure fn le(&self, other: &Au) -> bool { **self <= **other }
pure fn ge(&self, other: &Au) -> bool { **self >= **other } pure fn ge(&self, other: &Au) -> bool { **self >= **other }
pure fn gt(&self, other: &Au) -> bool { **self > **other } pure fn gt(&self, other: &Au) -> bool { **self > **other }
} }
impl Au : cmp::Eq { pub impl cmp::Eq for Au {
pure fn eq(&self, other: &Au) -> bool { **self == **other } pure fn eq(&self, other: &Au) -> bool { **self == **other }
pure fn ne(&self, other: &Au) -> bool { **self != **other } pure fn ne(&self, other: &Au) -> bool { **self != **other }
} }
@ -35,17 +45,37 @@ impl Au : cmp::Eq {
pub pure fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } } pub pure fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } }
pub pure fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } } pub pure fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } }
pub fn box<A:Copy Num>(x: A, y: A, w: A, h: A) -> Rect<A> { impl NumCast for Au {
static pure fn from<T:NumCast>(n: T) -> Au { Au(n.to_i32()) }
pure fn to_u8(&self) -> u8 { (**self).to_u8() }
pure fn to_u16(&self) -> u16 { (**self).to_u16() }
pure fn to_u32(&self) -> u32 { (**self).to_u32() }
pure fn to_u64(&self) -> u64 { (**self).to_u64() }
pure fn to_uint(&self) -> uint { (**self).to_uint() }
pure fn to_i8(&self) -> i8 { (**self).to_i8() }
pure fn to_i16(&self) -> i16 { (**self).to_i16() }
pure fn to_i32(&self) -> i32 { (**self).to_i32() }
pure fn to_i64(&self) -> i64 { (**self).to_i64() }
pure fn to_int(&self) -> int { (**self).to_int() }
pure fn to_f32(&self) -> f32 { (**self).to_f32() }
pure fn to_f64(&self) -> f64 { (**self).to_f64() }
pure fn to_float(&self) -> float { (**self).to_float() }
}
pub fn box<T:Copy + Ord + Add<T,T> + Sub<T,T>>(x: T, y: T, w: T, h: T) -> Rect<T> {
Rect(Point2D(x, y), Size2D(w, h)) Rect(Point2D(x, y), Size2D(w, h))
} }
impl Au { pub impl Au {
pub pure fn scale_by(factor: float) -> Au { pub pure fn scale_by(factor: float) -> Au {
Au(((*self as float) * factor) as i32) Au(((*self as float) * factor) as i32)
} }
static pub pure fn from_px(i: int) -> Au { static pub pure fn from_px(i: int) -> Au {
Num::from_int(i * 60) NumCast::from(i * 60)
} }
pub pure fn to_px(&const self) -> int { pub pure fn to_px(&const self) -> int {
@ -98,7 +128,7 @@ pub pure fn from_frac_px(f: float) -> Au {
} }
pub pure fn from_px(i: int) -> Au { pub pure fn from_px(i: int) -> Au {
Num::from_int(i * 60) NumCast::from(i * 60)
} }
pub pure fn to_px(au: Au) -> int { pub pure fn to_px(au: Au) -> int {

View file

@ -32,7 +32,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
1 => image.data[pixel * 4 + 1], 1 => image.data[pixel * 4 + 1],
2 => image.data[pixel * 4 + 0], 2 => image.data[pixel * 4 + 0],
3 => 0xffu8, 3 => 0xffu8,
_ => fail _ => fail!()
} }
}; };
@ -40,7 +40,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
Some(Image(image.width, image.height, image.depth, move data)) Some(Image(image.width, image.height, image.depth, move data))
} }
stb_image::ImageF32(_image) => fail ~"HDR images not implemented", stb_image::ImageF32(_image) => fail!(~"HDR images not implemented"),
stb_image::Error => None stb_image::Error => None
} }
} }

View file

@ -1,7 +1,7 @@
use io::WriterUtil; use io::WriterUtil;
use surface; use surface;
fn encode(writer: io::Writer, surface: &surface::image_surface) { fn encode(writer: io::Writer, surface: &surface::ImageSurface) {
assert surface.format == surface::fo_rgba_8888; assert surface.format == surface::fo_rgba_8888;
writer.write_u8(0u8); // identsize writer.write_u8(0u8); // identsize

View file

@ -32,11 +32,11 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
let opt_match = match getopts::getopts(args, opts) { let opt_match = match getopts::getopts(args, opts) {
result::Ok(m) => { copy m } result::Ok(m) => { copy m }
result::Err(f) => { fail getopts::fail_str(copy f) } result::Err(f) => { fail!(getopts::fail_str(copy f)) }
}; };
let urls = if opt_match.free.is_empty() { let urls = if opt_match.free.is_empty() {
fail ~"servo asks that you provide 1 or more URLs" fail!(~"servo asks that you provide 1 or more URLs")
} else { } else {
copy opt_match.free copy opt_match.free
}; };
@ -59,7 +59,7 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
} else if backend_str == ~"skia" { } else if backend_str == ~"skia" {
SkiaBackend SkiaBackend
} else { } else {
fail ~"unknown backend type" fail!(~"unknown backend type")
} }
} }
None => CairoBackend None => CairoBackend

View file

@ -14,7 +14,8 @@ use quartz::font_list::core_text::font_descriptor::{debug_descriptor};
use quartz::font::QuartzFontHandle; use quartz::font::QuartzFontHandle;
use quartz::font_context::QuartzFontContextHandle; use quartz::font_context::QuartzFontContextHandle;
use gfx_font::FontHandle; use gfx_font::{FontHandle, FontHandleMethods};
use gfx_font_context::FontContextHandleMethods;
use gfx_font_list::{FontEntry, FontFamily, FontFamilyMap}; use gfx_font_list::{FontEntry, FontFamily, FontFamilyMap};
use core::dvec::DVec; use core::dvec::DVec;

View file

@ -1,17 +1,19 @@
// The task that handles all rendering/painting.
use azure::AzFloat;
use compositor::{Compositor, LayerBufferSet}; use compositor::{Compositor, LayerBufferSet};
use font_context::FontContext; use font_context::FontContext;
use geom::matrix2d::Matrix2D;
use opts::Opts; 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 util::time::time;
use azure::AzFloat;
use core::oldcomm::*;
use core::libc::size_t; use core::libc::size_t;
use core::libc::types::common::c99::uint16_t; use core::libc::types::common::c99::uint16_t;
use core::pipes::{Port, Chan}; use core::pipes::{Chan, Port, SharedChan};
use core::task::SingleThreaded; use core::task::SingleThreaded;
use geom::matrix2d::Matrix2D;
use std::arc::ARC; use std::arc::ARC;
use std::arc; use std::arc;
use std::cell::Cell; use std::cell::Cell;
@ -22,12 +24,12 @@ pub enum Msg {
ExitMsg(pipes::Chan<()>) ExitMsg(pipes::Chan<()>)
} }
pub type RenderTask = oldcomm::Chan<Msg>; pub type RenderTask = SharedChan<Msg>;
pub fn RenderTask<C: Compositor Owned>(compositor: C, opts: Opts) -> RenderTask { pub fn RenderTask<C:Compositor + Owned>(compositor: C, opts: Opts) -> RenderTask {
let compositor_cell = Cell(move compositor); let compositor_cell = Cell(move compositor);
let opts_cell = Cell(move opts); let opts_cell = Cell(move opts);
do spawn_listener |po: oldcomm::Port<Msg>, move compositor_cell, move opts_cell| { let render_task = do spawn_listener |po: Port<Msg>| {
let (layer_buffer_set_port, layer_buffer_channel) = pipes::stream(); let (layer_buffer_set_port, layer_buffer_channel) = pipes::stream();
let compositor = compositor_cell.take(); let compositor = compositor_cell.take();
@ -58,7 +60,8 @@ pub fn RenderTask<C: Compositor Owned>(compositor: C, opts: Opts) -> RenderTask
thread_pool: move thread_pool, thread_pool: move thread_pool,
opts: opts_cell.take() opts: opts_cell.take()
}.start(); }.start();
} };
SharedChan(render_task)
} }
/// Data that needs to be kept around for each render thread. /// Data that needs to be kept around for each render thread.
@ -68,8 +71,8 @@ priv struct ThreadRenderContext {
opts: Opts, opts: Opts,
} }
priv struct Renderer<C: Compositor Owned> { priv struct Renderer<C> {
port: oldcomm::Port<Msg>, port: Port<Msg>,
compositor: C, compositor: C,
layer_buffer_set_port: Cell<pipes::Port<LayerBufferSet>>, layer_buffer_set_port: Cell<pipes::Port<LayerBufferSet>>,
thread_pool: TaskPool<ThreadRenderContext>, thread_pool: TaskPool<ThreadRenderContext>,

View file

@ -1,17 +1,15 @@
export factory; use pipes::Chan;
use oldcomm::Chan;
use task::spawn; use task::spawn;
use resource::resource_task::{ProgressMsg, Payload, Done}; use resource::resource_task::{ProgressMsg, Payload, Done, LoaderTask};
use std::net::url::Url; use std::net::url::Url;
use io::{file_reader, ReaderUtil}; use io::{file_reader, ReaderUtil};
const READ_SIZE: uint = 1024; const READ_SIZE: uint = 1024;
pub fn factory(url: Url, progress_chan: Chan<ProgressMsg>) { pub fn factory() -> LoaderTask {
let f: LoaderTask = |url, progress_chan| {
assert url.scheme == ~"file"; assert url.scheme == ~"file";
do spawn {
do spawn |move url| {
// FIXME: Resolve bug prevents us from moving the path out of the URL. // FIXME: Resolve bug prevents us from moving the path out of the URL.
match file_reader(&Path(url.path)) { match file_reader(&Path(url.path)) {
Ok(reader) => { Ok(reader) => {
@ -26,4 +24,6 @@ pub fn factory(url: Url, progress_chan: Chan<ProgressMsg>) {
} }
}; };
} }
};
f
} }

View file

@ -1,20 +1,24 @@
export factory; use pipes::{Chan, SharedChan};
use oldcomm::Chan;
use task::spawn; use task::spawn;
use resource::resource_task::{ProgressMsg, Payload, Done}; use resource::resource_task::{ProgressMsg, Payload, Done, LoaderTask};
use std::cell::Cell;
use std::net::url::Url; use std::net::url::Url;
use http_client; 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() -> LoaderTask {
let f: LoaderTask = |url, progress_chan| {
assert url.scheme == ~"http"; assert url.scheme == ~"http";
do spawn |move url| { let progress_chan = SharedChan(progress_chan);
do spawn {
debug!("http_loader: requesting via http: %?", copy url); debug!("http_loader: requesting via http: %?", copy url);
let request = uv_http_request(copy url); let request = uv_http_request(copy url);
let errored = @mut false; let errored = @mut false;
do request.begin |event, copy url| { let url = copy url;
{
let progress_chan = progress_chan.clone();
do request.begin |event| {
let url = copy url; let url = copy url;
match event { match event {
http_client::Status(*) => { } http_client::Status(*) => { }
@ -31,9 +35,12 @@ pub fn factory(url: Url, progress_chan: Chan<ProgressMsg>) {
} }
} }
} }
}
if !*errored { if !*errored {
progress_chan.send(Done(Ok(()))); progress_chan.send(Done(Ok(())));
} }
} }
};
f
} }

View file

@ -62,7 +62,7 @@ impl ImageResponseMsg: cmp::Eq {
pure fn eq(&self, other: &ImageResponseMsg) -> bool { pure fn eq(&self, other: &ImageResponseMsg) -> bool {
// FIXME: Bad copies // FIXME: Bad copies
match (self.clone(), other.clone()) { match (self.clone(), other.clone()) {
(ImageReady(*), ImageReady(*)) => fail ~"unimplemented comparison", (ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"),
(ImageNotReady, ImageNotReady) => true, (ImageNotReady, ImageNotReady) => true,
(ImageFailed, ImageFailed) => true, (ImageFailed, ImageFailed) => true,
@ -84,7 +84,9 @@ pub fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
ImageCacheTask_(resource_task, default_decoder_factory) ImageCacheTask_(resource_task, default_decoder_factory)
} }
pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFactory) -> ImageCacheTask { pub fn ImageCacheTask_(resource_task: ResourceTask,
decoder_factory: DecoderFactory)
-> ImageCacheTask {
// FIXME: Doing some dancing to avoid copying decoder_factory, our test // FIXME: Doing some dancing to avoid copying decoder_factory, our test
// version of which contains an uncopyable type which rust will currently // version of which contains an uncopyable type which rust will currently
// copy unsoundly // copy unsoundly
@ -95,9 +97,9 @@ pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFact
let port_cell = Cell(move port); let port_cell = Cell(move port);
let chan_cell = Cell(chan.clone()); let chan_cell = Cell(chan.clone());
do spawn |move port_cell, move chan_cell, move decoder_factory_cell| { do spawn {
ImageCache { ImageCache {
resource_task: resource_task, resource_task: resource_task.clone(),
decoder_factory: decoder_factory_cell.take(), decoder_factory: decoder_factory_cell.take(),
port: port_cell.take(), port: port_cell.take(),
chan: chan_cell.take(), chan: chan_cell.take(),
@ -114,9 +116,9 @@ fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
let (port, chan) = stream(); let (port, chan) = stream();
let port_cell = Cell(move port); let port_cell = Cell(move port);
do spawn |move port_cell, move resource_task| { do spawn {
let port = port_cell.take(); let port = port_cell.take();
let inner_cache = ImageCacheTask(resource_task); let inner_cache = ImageCacheTask(resource_task.clone());
loop { loop {
let msg: Msg = port.recv(); let msg: Msg = port.recv();
@ -177,7 +179,9 @@ impl ImageCache {
loop { loop {
let msg = self.port.recv(); let msg = self.port.recv();
for msg_handlers.each |handler| { (*handler)(&msg) } for msg_handlers.each |handler| {
(*handler)(&msg)
}
debug!("image_cache_task: received: %?", msg); debug!("image_cache_task: received: %?", msg);
@ -192,7 +196,7 @@ impl ImageCache {
WaitForImage(move url, move response) => { WaitForImage(move url, move response) => {
self.wait_for_image(move url, move response) self.wait_for_image(move url, move response)
} }
OnMsg(move handler) => msg_handlers += [move handler], OnMsg(move handler) => msg_handlers.push(handler),
Exit(move response) => { Exit(move response) => {
assert self.need_exit.is_none(); assert self.need_exit.is_none();
self.need_exit = Some(move response); self.need_exit = Some(move response);
@ -207,14 +211,11 @@ impl ImageCache {
// before exiting // before exiting
let mut can_exit = true; let mut can_exit = true;
for self.state_map.each_value |state| { for self.state_map.each_value |state| {
match state { match *state {
Prefetching(*) => can_exit = false, Prefetching(*) => can_exit = false,
Decoding => can_exit = false, Decoding => can_exit = false,
Init Init | Prefetched(*) | Decoded(*) | Failed => ()
| Prefetched(*)
| Decoded(*)
| Failed => ()
} }
} }
@ -231,7 +232,7 @@ impl ImageCache {
} }
priv fn get_state(url: Url) -> ImageState { priv fn get_state(url: Url) -> ImageState {
match move self.state_map.find(move url) { match move self.state_map.find(&url) {
Some(move state) => move state, Some(move state) => move state,
None => Init None => Init
} }
@ -245,14 +246,14 @@ impl ImageCache {
match self.get_state(copy url) { match self.get_state(copy url) {
Init => { Init => {
let to_cache = self.chan.clone(); let to_cache = self.chan.clone();
let resource_task = self.resource_task; let resource_task = self.resource_task.clone();
let url_cell = Cell(copy url); let url_cell = Cell(copy url);
do spawn |move to_cache, move url_cell| { do spawn {
let url = url_cell.take(); let url = url_cell.take();
debug!("image_cache_task: started fetch for %s", url.to_str()); debug!("image_cache_task: started fetch for %s", url.to_str());
let image = load_image_data(copy url, resource_task); let image = load_image_data(copy url, resource_task.clone());
let result = if image.is_ok() { let result = if image.is_ok() {
Ok(Cell(result::unwrap(move image))) Ok(Cell(result::unwrap(move image)))
@ -266,11 +267,7 @@ impl ImageCache {
self.set_state(move url, Prefetching(DoNotDecode)); self.set_state(move url, Prefetching(DoNotDecode));
} }
Prefetching(*) Prefetching(*) | Prefetched(*) | Decoding | Decoded(*) | Failed => {
| Prefetched(*)
| Decoding
| Decoded(*)
| Failed => {
// We've already begun working on this image // We've already begun working on this image
} }
} }
@ -300,14 +297,14 @@ impl ImageCache {
| Decoding | Decoding
| Decoded(*) | Decoded(*)
| Failed => { | Failed => {
fail ~"wrong state for storing prefetched image" fail!(~"wrong state for storing prefetched image")
} }
} }
} }
priv fn decode(url: Url) { priv fn decode(url: Url) {
match self.get_state(copy url) { match self.get_state(copy url) {
Init => fail ~"decoding image before prefetch", Init => fail!(~"decoding image before prefetch"),
Prefetching(DoNotDecode) => { Prefetching(DoNotDecode) => {
// We don't have the data yet, queue up the decode // We don't have the data yet, queue up the decode
@ -369,14 +366,13 @@ impl ImageCache {
| Prefetched(*) | Prefetched(*)
| Decoded(*) | Decoded(*)
| Failed => { | Failed => {
fail ~"incorrect state in store_image" fail!(~"incorrect state in store_image")
} }
} }
} }
priv fn purge_waiters(url: Url, f: fn() -> ImageResponseMsg) { priv fn purge_waiters(url: Url, f: fn() -> ImageResponseMsg) {
match self.wait_map.find(copy url) {
Some(waiters) => { Some(waiters) => {
let waiters = &mut *waiters; let waiters = &mut *waiters;
let mut new_waiters = ~[]; let mut new_waiters = ~[];
@ -387,7 +383,7 @@ impl ImageCache {
} }
*waiters <-> new_waiters; *waiters <-> new_waiters;
self.wait_map.remove(move url); self.wait_map.remove(&url);
} }
None => () None => ()
} }
@ -395,16 +391,15 @@ impl ImageCache {
priv fn get_image(url: Url, response: Chan<ImageResponseMsg>) { priv fn get_image(url: Url, response: Chan<ImageResponseMsg>) {
match self.get_state(copy url) { match self.get_state(copy url) {
Init => fail ~"request for image before prefetch", Init => fail!(~"request for image before prefetch"),
Prefetching(DoDecode) => { Prefetching(DoDecode) => {
response.send(ImageNotReady); response.send(ImageNotReady);
} }
Prefetching(DoNotDecode) Prefetching(DoNotDecode)
| Prefetched(*) => fail ~"request for image before decode", | Prefetched(*) => fail!(~"request for image before decode"),
Decoding => { Decoding => {
response.send(ImageNotReady) response.send(ImageNotReady)
@ -422,13 +417,13 @@ impl ImageCache {
priv fn wait_for_image(url: Url, response: Chan<ImageResponseMsg>) { priv fn wait_for_image(url: Url, response: Chan<ImageResponseMsg>) {
match self.get_state(copy url) { match self.get_state(copy url) {
Init => fail ~"request for image before prefetch", Init => fail!(~"request for image before prefetch"),
Prefetching(DoNotDecode) | Prefetched(*) => fail ~"request for image before decode", Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
Prefetching(DoDecode) | Decoding => { Prefetching(DoDecode) | Decoding => {
// We don't have this image yet // We don't have this image yet
match self.wait_map.find(copy url) { match self.wait_map.find(&url) {
Some(waiters) => { Some(waiters) => {
vec::push(&mut *waiters, move response); vec::push(&mut *waiters, move response);
} }
@ -466,8 +461,8 @@ impl ImageCacheTask: ImageCacheTaskClient {
} }
fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<~[u8], ()> { fn load_image_data(url: Url, resource_task: ResourceTask) -> Result<~[u8], ()> {
let response_port = oldcomm::Port(); let (response_port, response_chan) = stream();
resource_task.send(resource_task::Load(move url, response_port.chan())); resource_task.send(resource_task::Load(move url, response_chan));
let mut image_data = ~[]; let mut image_data = ~[];
@ -491,8 +486,8 @@ fn default_decoder_factory() -> ~fn(&[u8]) -> Option<Image> {
} }
#[cfg(test)] #[cfg(test)]
fn mock_resource_task(on_load: ~fn(resource: oldcomm::Chan<resource_task::ProgressMsg>)) -> ResourceTask { fn mock_resource_task(on_load: ~fn(resource: Chan<resource_task::ProgressMsg>)) -> ResourceTask {
do spawn_listener |port: oldcomm::Port<resource_task::ControlMsg>, move on_load| { do spawn_listener |port: Port<resource_task::ControlMsg>, move on_load| {
loop { loop {
match port.recv() { match port.recv() {
resource_task::Load(_, response) => { resource_task::Load(_, response) => {
@ -532,7 +527,7 @@ fn should_fail_if_unprefetched_image_is_requested() {
#[test] #[test]
fn should_request_url_from_resource_task_on_prefetch() { fn should_request_url_from_resource_task_on_prefetch() {
let url_requested = oldcomm::Port(); let url_requested = Port();
let url_requested_chan = url_requested.chan(); let url_requested_chan = url_requested.chan();
let mock_resource_task = do mock_resource_task |response| { let mock_resource_task = do mock_resource_task |response| {

View file

@ -133,7 +133,7 @@ pub impl LocalImageCache {
} }
priv fn get_state(url: &Url) -> @ImageState { priv fn get_state(url: &Url) -> @ImageState {
match self.state_map.find(copy *url) { match self.state_map.find(url) {
Some(state) => state, Some(state) => state,
None => { None => {
let new_state = @ImageState { let new_state = @ImageState {

View file

@ -4,8 +4,9 @@ A task that takes a URL and streams back the binary data
*/ */
use oldcomm::{Chan, Port}; use pipes::{Chan, Port, SharedChan};
use resource::util::spawn_listener; use resource::util::spawn_listener;
use std::cell::Cell;
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}; use super::{file_loader, http_loader};
@ -17,6 +18,7 @@ pub enum ControlMsg {
} }
/// Messages sent in response to a `Load` message /// Messages sent in response to a `Load` message
#[deriving_eq]
pub enum ProgressMsg { pub enum ProgressMsg {
/// Binary data - there may be multiple of these /// Binary data - there may be multiple of these
Payload(~[u8]), Payload(~[u8]),
@ -24,24 +26,8 @@ pub enum ProgressMsg {
Done(Result<(), ()>) Done(Result<(), ()>)
} }
impl ProgressMsg: cmp::Eq {
pure fn eq(&self, other: &ProgressMsg) -> bool {
// FIXME: Bad copies
match (copy *self, copy *other) {
(Payload(a), Payload(b)) => a == b,
(Done(a), Done(b)) => a == b,
(Payload(*), _)
| (Done(*), _) => false
}
}
pure fn ne(&self, other: &ProgressMsg) -> bool {
return !(*self).eq(other);
}
}
/// Handle to a resource task /// Handle to a resource task
pub type ResourceTask = Chan<ControlMsg>; pub type ResourceTask = SharedChan<ControlMsg>;
/** /**
Creates a task to load a specific resource Creates a task to load a specific resource
@ -49,7 +35,9 @@ Creates a task to load a specific resource
The ResourceManager delegates loading to a different type of loader task for The ResourceManager delegates loading to a different type of loader task for
each URL scheme each URL scheme
*/ */
type LoaderTaskFactory = fn~(url: Url, Chan<ProgressMsg>); type LoaderTaskFactory = ~fn() -> ~fn(url: Url, Chan<ProgressMsg>);
pub type LoaderTask = ~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 {
@ -63,10 +51,12 @@ pub fn ResourceTask() -> ResourceTask {
} }
fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask { fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask {
do spawn_listener |from_client, move loaders| { let loaders_cell = Cell(loaders);
let chan = do spawn_listener |from_client| {
// TODO: change copy to move once we can move out of closures // TODO: change copy to move once we can move out of closures
ResourceManager(from_client, copy loaders).start() ResourceManager(from_client, loaders_cell.take()).start()
} };
SharedChan(chan)
} }
pub struct ResourceManager { pub struct ResourceManager {
@ -113,11 +103,14 @@ impl ResourceManager {
} }
} }
fn get_loader_factory(url: &Url) -> Option<LoaderTaskFactory> { fn get_loader_factory(url: &Url) -> Option<LoaderTask> {
for self.loaders.each |scheme_loader| { for self.loaders.each |scheme_loader| {
let (scheme, loader_factory) = copy *scheme_loader; match *scheme_loader {
if scheme == url.scheme { (ref scheme, ref loader_factory) => {
return Some(move loader_factory); if (*scheme) == url.scheme {
return Some((*loader_factory)());
}
}
} }
} }
return None; return None;

View file

@ -1,12 +1,12 @@
pub fn spawn_listener<A: Owned>( use core::pipes::{Chan, Port};
f: fn~(oldcomm::Port<A>)) -> oldcomm::Chan<A> { use core::pipes;
let setup_po = oldcomm::Port();
let setup_ch = oldcomm::Chan(&setup_po); pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
let (setup_po, setup_ch) = pipes::stream();
do task::spawn |move f| { do task::spawn |move f| {
let po = oldcomm::Port(); let (po, ch) = pipes::stream();
let ch = oldcomm::Chan(&po); setup_ch.send(ch);
oldcomm::send(setup_ch, ch);
f(move po); f(move po);
} }
oldcomm::recv(setup_po) setup_po.recv()
} }

View file

@ -1,27 +1,11 @@
use geom::size::Size2D; use geom::size::Size2D;
#[deriving_eq]
pub enum format { pub enum format {
fo_rgba_8888 fo_rgba_8888
// TODO: RGB 565, others? // TODO: RGB 565, others?
} }
impl format: cmp::Eq {
pure fn eq(&self, other: &format) -> bool {
match (*self, *other) {
(fo_rgba_8888, fo_rgba_8888) => true,
}
}
pure fn ne(&self, other: &format) -> bool {
return !self.eq(other);
}
}
pub type image_surface = {
size: Size2D<int>,
format: format,
buffer: ~[u8]
};
impl format { impl format {
fn bpp() -> uint { fn bpp() -> uint {
match self { match self {
@ -30,11 +14,19 @@ impl format {
} }
} }
pub fn image_surface(size: Size2D<int>, format: format) -> image_surface { pub struct ImageSurface {
{ size: Size2D<int>,
format: format,
buffer: ~[u8]
}
impl ImageSurface {
static pub fn new(size: Size2D<int>, format: format) -> ImageSurface {
ImageSurface {
size: copy size, size: copy size,
format: format, format: format,
buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8) buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8)
} }
}
} }

View file

@ -6,10 +6,10 @@ use geometry;
use core; use core;
use core::cmp::{Ord, Eq}; use core::cmp::{Ord, Eq};
use core::dvec::DVec; use core::dvec::DVec;
use core::num::NumCast;
use core::u16; use core::u16;
use geom::point::Point2D; use geom::point::Point2D;
use std::sort; use std::sort;
use num::Num;
// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing // GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing
@ -174,7 +174,7 @@ impl GlyphEntry {
#[inline(always)] #[inline(always)]
pure fn advance() -> Au { pure fn advance() -> Au {
//assert self.is_simple(); //assert self.is_simple();
Num::from_int(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as int) NumCast::from((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT)
} }
pure fn index() -> GlyphIndex { pure fn index() -> GlyphIndex {
@ -375,7 +375,7 @@ impl DetailedGlyphStore {
// FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred. // FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred.
let records : &[DetailedGlyphRecord] = self.detail_lookup; let records : &[DetailedGlyphRecord] = self.detail_lookup;
match records.binary_search_index(&key) { match records.binary_search_index(&key) {
None => fail ~"Invalid index not found in detailed glyph lookup table!", None => fail!(~"Invalid index not found in detailed glyph lookup table!"),
Some(i) => { Some(i) => {
assert i + (count as uint) <= self.detail_buffer.len(); assert i + (count as uint) <= self.detail_buffer.len();
// return a view into the buffer // return a view into the buffer
@ -384,7 +384,10 @@ impl DetailedGlyphStore {
} }
} }
pure fn get_detailed_glyph_with_index(&self, entry_offset: uint, detail_offset: u16) -> &self/DetailedGlyph { pure fn get_detailed_glyph_with_index(&self,
entry_offset: uint,
detail_offset: u16)
-> &self/DetailedGlyph {
assert (detail_offset as uint) <= self.detail_buffer.len(); assert (detail_offset as uint) <= self.detail_buffer.len();
assert self.lookup_is_sorted; assert self.lookup_is_sorted;
@ -396,7 +399,7 @@ impl DetailedGlyphStore {
// FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred. // FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred.
let records : &[DetailedGlyphRecord] = self.detail_lookup; let records : &[DetailedGlyphRecord] = self.detail_lookup;
match records.binary_search_index(&key) { match records.binary_search_index(&key) {
None => fail ~"Invalid index not found in detailed glyph lookup table!", None => fail!(~"Invalid index not found in detailed glyph lookup table!"),
Some(i) => { Some(i) => {
assert i + (detail_offset as uint) < self.detail_buffer.len(); assert i + (detail_offset as uint) < self.detail_buffer.len();
&self.detail_buffer[i+(detail_offset as uint)] &self.detail_buffer[i+(detail_offset as uint)]

View file

@ -4,7 +4,7 @@ use geom::Point2D;
use geometry::Au; use geometry::Au;
use font::{Font, FontTable, FontTableTag}; use font::{Font, FontTable, FontTableMethods, FontTableTag};
use text::glyph::{GlyphStore, GlyphIndex, GlyphData}; use text::glyph::{GlyphStore, GlyphIndex, GlyphData};
use text::shaper::ShaperMethods; use text::shaper::ShaperMethods;
@ -202,7 +202,7 @@ pub impl HarfbuzzShaper {
} }
} }
pub impl HarfbuzzShaper : ShaperMethods { impl ShaperMethods for HarfbuzzShaper {
/** /**
Calculate the layout metrics associated with a some given text Calculate the layout metrics associated with a some given text
when rendered in a specific font. when rendered in a specific font.

View file

@ -12,7 +12,6 @@ pub type Shaper/& = harfbuzz::shaper::HarfbuzzShaper;
pub trait ShaperMethods { pub trait ShaperMethods {
fn shape_text(text: &str, glyphs: &mut GlyphStore); fn shape_text(text: &str, glyphs: &mut GlyphStore);
} }
// TODO(Issue #163): this is a workaround for static methods and // TODO(Issue #163): this is a workaround for static methods and

View file

@ -28,7 +28,7 @@ impl SendableTextRun {
pub fn deserialize(&self, fctx: @FontContext) -> TextRun { pub fn deserialize(&self, fctx: @FontContext) -> TextRun {
let font = match fctx.get_font_by_descriptor(&self.font) { let font = match fctx.get_font_by_descriptor(&self.font) {
Ok(f) => f, Ok(f) => f,
Err(_) => fail fmt!("Font descriptor deserialization failed! desc=%?", self.font) Err(_) => fail!(fmt!("Font descriptor deserialization failed! desc=%?", self.font))
}; };
TextRun { TextRun {

View file

@ -1,14 +1,14 @@
use core::cmp::*; use core::cmp::*;
pub trait Cache<K: Copy Eq, V: Copy> { pub trait Cache<K: Copy Eq, V: Copy> {
static fn new(size: uint) -> self; static fn new(size: uint) -> Self;
fn insert(key: &K, value: V); fn insert(key: &K, value: V);
fn find(key: &K) -> Option<V>; fn find(key: &K) -> Option<V>;
fn find_or_create(key: &K, blk: pure fn&(&K) -> V) -> V; fn find_or_create(key: &K, blk: pure fn&(&K) -> V) -> V;
fn evict_all(); fn evict_all();
} }
pub struct MonoCache<K: Copy Eq, V: Copy> { pub struct MonoCache<K, V> {
mut entry: Option<(K,V)>, mut entry: Option<(K,V)>,
} }

View file

@ -88,8 +88,8 @@ pub impl Range {
let overlap = other.end() - self.begin(); let overlap = other.end() - self.begin();
return OverlapsEnd(overlap); return OverlapsEnd(overlap);
} }
fail fmt!("relation_to_range(): didn't classify self=%?, other=%?", fail!(fmt!("relation_to_range(): didn't classify self=%?, other=%?",
self, other); self, other));
} }
fn repair_after_coalesced_range(&mut self, other: &const Range) { fn repair_after_coalesced_range(&mut self, other: &const Range) {
@ -103,8 +103,10 @@ pub impl Range {
Coincides | ContainedBy => { self.reset(other.begin(), 1); }, Coincides | ContainedBy => { self.reset(other.begin(), 1); },
Contains => { self.extend_by(-(other.length() as int)); }, Contains => { self.extend_by(-(other.length() as int)); },
OverlapsBegin(overlap) => { self.extend_by(1 - (overlap as int)); }, OverlapsBegin(overlap) => { self.extend_by(1 - (overlap as int)); },
OverlapsEnd(overlap) => OverlapsEnd(overlap) => {
{ self.reset(other.begin(), self.length() - overlap + 1); } let len = self.length() - overlap + 1;
self.reset(other.begin(), len);
}
}; };
debug!("repair_after_coalesced_range: new range: ---- %?", self); debug!("repair_after_coalesced_range: new range: ---- %?", self);
} }

View file

@ -1,7 +1,7 @@
use core::path::Path; use core::path::Path;
use std::map::HashMap;
use std::net::url; use std::net::url;
use std::net::url::Url; use std::net::url::Url;
use std::oldmap::HashMap;
/** /**
Create a URL object from a string. Does various helpful browsery things like Create a URL object from a string. Does various helpful browsery things like
@ -98,7 +98,7 @@ mod make_url_tests {
} }
pub type UrlMap<T: Copy> = HashMap<Url, T>; pub type UrlMap<T> = HashMap<Url, T>;
pub fn url_map<T: Copy>() -> UrlMap<T> { pub fn url_map<T: Copy>() -> UrlMap<T> {
use core::to_str::ToStr; use core::to_str::ToStr;

View file

@ -13,7 +13,7 @@ use layout::layout_task::{AddStylesheet, BuildData, BuildMsg, Damage, LayoutTask
use layout::layout_task::{MatchSelectorsDamage, NoDamage, ReflowDamage}; use layout::layout_task::{MatchSelectorsDamage, NoDamage, ReflowDamage};
use util::task::spawn_listener; use util::task::spawn_listener;
use core::oldcomm::{Port, Chan, listen, select2}; use core::pipes::{Port, Chan, SharedChan, select2};
use core::either; use core::either;
use core::task::{SingleThreaded, spawn, task}; use core::task::{SingleThreaded, spawn, task};
use core::io::{println, read_whole_file}; use core::io::{println, read_whole_file};
@ -28,7 +28,7 @@ use js::global::{global_class, debug_fns};
use js::glue::bindgen::RUST_JSVAL_TO_OBJECT; use js::glue::bindgen::RUST_JSVAL_TO_OBJECT;
use js::jsapi::{JSContext, JSVal}; use js::jsapi::{JSContext, JSVal};
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate}; use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
use js::rust::{compartment, cx, methods}; use js::rust::{Compartment, Cx};
use jsrt = js::rust::rt; use jsrt = js::rust::rt;
use newcss::stylesheet::Stylesheet; use newcss::stylesheet::Stylesheet;
use std::arc::{ARC, clone}; use std::arc::{ARC, clone};
@ -49,29 +49,30 @@ pub enum PingMsg {
PongMsg PongMsg
} }
pub type ContentTask = pipes::SharedChan<ControlMsg>; pub type ContentTask = SharedChan<ControlMsg>;
pub fn ContentTask(layout_task: LayoutTask, pub fn ContentTask(layout_task: LayoutTask,
dom_event_port: pipes::Port<Event>, dom_event_port: Port<Event>,
dom_event_chan: pipes::SharedChan<Event>, dom_event_chan: SharedChan<Event>,
resource_task: ResourceTask, resource_task: ResourceTask,
img_cache_task: ImageCacheTask) -> ContentTask { img_cache_task: ImageCacheTask)
-> ContentTask {
let (control_port, control_chan) = pipes::stream(); let (control_port, control_chan) = pipes::stream();
let control_chan = pipes::SharedChan(move control_chan); let control_chan = SharedChan(control_chan);
let control_chan_copy = control_chan.clone(); let control_chan_copy = control_chan.clone();
let control_port = Cell(move control_port); let control_port = Cell(control_port);
let dom_event_port = Cell(move dom_event_port); let dom_event_port = Cell(dom_event_port);
let dom_event_chan = Cell(move dom_event_chan); let dom_event_chan = Cell(dom_event_chan);
do task().sched_mode(SingleThreaded).spawn |move layout_task, move control_port, do task().sched_mode(SingleThreaded).spawn {
move control_chan_copy, move resource_task, let content = Content(layout_task.clone(),
move img_cache_task, move dom_event_port, control_port.take(),
move dom_event_chan| { control_chan_copy.clone(),
let content = Content(layout_task, control_port.take(), control_chan_copy.clone(), resource_task.clone(),
resource_task, img_cache_task.clone(), img_cache_task.clone(),
dom_event_port.take(), dom_event_chan.take()); dom_event_port.take(),
dom_event_chan.take());
content.start(); content.start();
} }
@ -90,7 +91,7 @@ pub struct Content {
scope: NodeScope, scope: NodeScope,
jsrt: jsrt, jsrt: jsrt,
cx: cx, cx: @Cx,
mut document: Option<@Document>, mut document: Option<@Document>,
mut window: Option<@Window>, mut window: Option<@Window>,
@ -99,7 +100,7 @@ pub struct Content {
resource_task: ResourceTask, resource_task: ResourceTask,
compartment: Option<compartment>, compartment: Option<@mut Compartment>,
// What parts of layout are dirty. // What parts of layout are dirty.
mut damage: Damage, mut damage: Damage,
@ -111,8 +112,8 @@ pub fn Content(layout_task: LayoutTask,
resource_task: ResourceTask, resource_task: ResourceTask,
img_cache_task: ImageCacheTask, img_cache_task: ImageCacheTask,
event_port: pipes::Port<Event>, event_port: pipes::Port<Event>,
event_chan: pipes::SharedChan<Event>) -> @Content { event_chan: pipes::SharedChan<Event>)
-> @Content {
let jsrt = jsrt(); let jsrt = jsrt();
let cx = jsrt.cx(); let cx = jsrt.cx();
@ -161,7 +162,6 @@ pub fn task_from_context(cx: *JSContext) -> *Content {
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
impl Content { impl Content {
fn start() { fn start() {
while self.handle_msg() { while self.handle_msg() {
// Go on ... // Go on ...
@ -185,7 +185,7 @@ impl Content {
let result = html::hubbub_html_parser::parse_html(self.scope, let result = html::hubbub_html_parser::parse_html(self.scope,
copy url, copy url,
self.resource_task, self.resource_task.clone(),
self.image_cache_task.clone()); self.image_cache_task.clone());
let root = result.root; let root = result.root;
@ -286,7 +286,7 @@ impl Content {
join_port.recv(); join_port.recv();
debug!("content: layout joined"); debug!("content: layout joined");
} }
None => fail ~"reader forked but no join port?" None => fail!(~"reader forked but no join port?")
} }
self.scope.reader_joined(); self.scope.reader_joined();
@ -333,8 +333,8 @@ impl Content {
self.relayout(self.document.get(), &(copy self.doc_url).get()); self.relayout(self.document.get(), &(copy self.doc_url).get());
self.join_layout(); self.join_layout();
let response_port = Port(); let (response_port, response_chan) = pipes::stream();
self.layout_task.send(layout_task::QueryMsg(query, response_port.chan())); self.layout_task.send(layout_task::QueryMsg(query, response_chan));
return response_port.recv() return response_port.recv()
} }

View file

@ -1,14 +1,15 @@
/** // High-level interface to CSS selector matching.
* High-level interface to CSS selector matching.
*/
use std::arc::{ARC, get, clone};
use dom::node::{Node, NodeTree};
use newcss::select::{SelectCtx, SelectResults};
use newcss::complete::CompleteSelectResults;
use layout::context::LayoutContext;
use css::select_handler::NodeSelectHandler;
trait MatchMethods { use css::node_util::NodeUtil;
use css::select_handler::NodeSelectHandler;
use dom::node::{Node, NodeTree};
use layout::context::LayoutContext;
use newcss::complete::CompleteSelectResults;
use newcss::select::{SelectCtx, SelectResults};
use std::arc::{ARC, get, clone};
pub trait MatchMethods {
fn restyle_subtree(select_ctx: &SelectCtx); fn restyle_subtree(select_ctx: &SelectCtx);
} }

View file

@ -1,8 +1,11 @@
// Style retrieval from DOM elements.
use css::node_util::NodeUtil;
use dom::node::Node; use dom::node::Node;
use newcss::complete::CompleteStyle; use newcss::complete::CompleteStyle;
/// Node mixin providing `style` method that returns a `NodeStyle` /// Node mixin providing `style` method that returns a `NodeStyle`
trait StyledNode { pub trait StyledNode {
fn style(&self) -> CompleteStyle/&self; fn style(&self) -> CompleteStyle/&self;
} }

View file

@ -2,12 +2,12 @@ use dom::node::Node;
use newcss::complete::CompleteSelectResults; use newcss::complete::CompleteSelectResults;
use std::cell::Cell; use std::cell::Cell;
trait NodeUtil { pub trait NodeUtil {
fn get_css_select_results() -> &self/CompleteSelectResults; fn get_css_select_results() -> &self/CompleteSelectResults;
fn set_css_select_results(decl : CompleteSelectResults); fn set_css_select_results(decl : CompleteSelectResults);
} }
impl Node: NodeUtil { impl NodeUtil for Node {
/** /**
* Provides the computed style for the given node. If CSS selector * Provides the computed style for the given node. If CSS selector
* Returns the style results for the given node. If CSS selector * Returns the style results for the given node. If CSS selector
@ -17,12 +17,12 @@ impl Node: NodeUtil {
*/ */
fn get_css_select_results() -> &self/CompleteSelectResults { fn get_css_select_results() -> &self/CompleteSelectResults {
if !self.has_aux() { if !self.has_aux() {
fail ~"style() called on a node without aux data!"; fail!(~"style() called on a node without aux data!");
} }
unsafe { &*self.aux( |x| { unsafe { &*self.aux( |x| {
match x.style { match x.style {
Some(ref style) => ptr::to_unsafe_ptr(style), Some(ref style) => ptr::to_unsafe_ptr(style),
None => fail ~"style() called on node without a style!" None => fail!(~"style() called on node without a style!")
} }
})} })}
} }

View file

@ -9,7 +9,7 @@ pub struct NodeSelectHandler {
fn with_node_name<R>(data: &NodeData, f: &fn(&str) -> R) -> R { fn with_node_name<R>(data: &NodeData, f: &fn(&str) -> R) -> R {
match *data.kind { match *data.kind {
Element(ref data) => f(data.tag_name), Element(ref data) => f(data.tag_name),
_ => fail ~"attempting to style non-element node" _ => fail!(~"attempting to style non-element node")
} }
} }
@ -75,7 +75,7 @@ impl NodeSelectHandler: SelectHandler<Node> {
do node.read |data| { do node.read |data| {
match *data.kind { match *data.kind {
Element(ref data) => data.with_attr("id", f), Element(ref data) => data.with_attr("id", f),
_ => fail ~"attempting to style non-element node" _ => fail!(~"attempting to style non-element node")
} }
} }
} }
@ -91,7 +91,7 @@ impl NodeSelectHandler: SelectHandler<Node> {
} }
} }
} }
_ => fail ~"attempting to style non-element node" _ => fail!(~"attempting to style non-element node")
} }
} }
} }

View file

@ -1,4 +1,4 @@
use js::rust::{compartment, bare_compartment, methods, jsobj}; use js::rust::{Compartment, jsobj};
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED,
JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS}; JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp};
@ -62,8 +62,7 @@ enum Element = int;
return 1; return 1;
}*/ }*/
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
-> JSBool {
unsafe { unsafe {
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp)); let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
if obj.is_null() { if obj.is_null() {
@ -92,7 +91,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
} }
} }
pub fn init(compartment: &bare_compartment, doc: @Document) { pub fn init(compartment: @mut Compartment, doc: @Document) {
let obj = utils::define_empty_prototype(~"Document", None, compartment); let obj = utils::define_empty_prototype(~"Document", None, compartment);
let attrs = @~[ let attrs = @~[

View file

@ -1,4 +1,4 @@
use js::rust::{bare_compartment, methods, jsobj}; use js::rust::{Compartment, jsobj};
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, JSPROP_NATIVE_ACCESSORS}; JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec};
@ -29,7 +29,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
} }
} }
pub fn init(compartment: &bare_compartment) { pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Element", Some(~"Node"), compartment); let obj = utils::define_empty_prototype(~"Element", Some(~"Node"), compartment);
let attrs = @~[ let attrs = @~[
{name: compartment.add_name(~"tagName"), {name: compartment.add_name(~"tagName"),
@ -87,10 +87,10 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
} }
// TODO: if nothing is being rendered(?), return zero dimensions // TODO: if nothing is being rendered(?), return zero dimensions
} }
_ => fail ~"why is this not an image element?" _ => fail!(~"why is this not an image element?")
} }
} }
_ => fail ~"why is this not an element?" _ => fail!(~"why is this not an element?")
} }
}); });
*vp = RUST_INT_TO_JSVAL( *vp = RUST_INT_TO_JSVAL(
@ -117,10 +117,10 @@ extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
let arg = ptr::offset(JS_ARGV(cx, cast::reinterpret_cast(&vp)), 0); let arg = ptr::offset(JS_ARGV(cx, cast::reinterpret_cast(&vp)), 0);
ed.set_attr(~"width", int::str(RUST_JSVAL_TO_INT(*arg) as int)) ed.set_attr(~"width", int::str(RUST_JSVAL_TO_INT(*arg) as int))
} }
_ => fail ~"why is this not an image element?" _ => fail!(~"why is this not an image element?")
} }
} }
_ => fail ~"why is this not an element?" _ => fail!(~"why is this not an element?")
} }
}; };
return 1; return 1;
@ -166,7 +166,7 @@ pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj {
_ => ~"HTMLElement" _ => ~"HTMLElement"
} }
} }
_ => fail ~"element::create only handles elements" _ => fail!(~"element::create only handles elements")
} }
}); });

View file

@ -1,4 +1,4 @@
use js::rust::{bare_compartment, methods, jsobj}; use js::rust::{Compartment, jsobj};
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, JSPROP_NATIVE_ACCESSORS}; JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec};
@ -18,7 +18,7 @@ use super::utils;
use super::element; use super::element;
use js; use js;
pub fn init(compartment: &bare_compartment) { pub fn init(compartment: @mut Compartment) {
let obj = utils::define_empty_prototype(~"Node", None, compartment); let obj = utils::define_empty_prototype(~"Node", None, compartment);
let attrs = @~[ let attrs = @~[
@ -49,18 +49,10 @@ pub fn init(compartment: &bare_compartment) {
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj { pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj {
do scope.write(&node) |nd| { do scope.write(&node) |nd| {
match nd.kind { match nd.kind {
~Element(*) => { ~Element(*) => element::create(cx, node, scope),
element::create(cx, node, scope) ~Text(*) => fail!(~"no text node bindings yet"),
} ~Comment(*) => fail!(~"no comment node bindings yet"),
~Text(*) => { ~Doctype(*) => fail!(~"no doctype node bindings yet")
fail ~"no text node bindings yet";
}
~Comment(*) => {
fail ~"no comment node bindings yet";
}
~Doctype(*) => {
fail ~"no doctype node bindings yet";
}
} }
} }
} }

View file

@ -1,5 +1,5 @@
use js; use js;
use js::rust::{compartment, bare_compartment, methods}; use js::rust::Compartment;
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};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp};
@ -70,7 +70,7 @@ pub unsafe fn domstring_to_jsval(cx: *JSContext, string: &DOMString) -> JSVal {
} }
} }
pub fn get_compartment(cx: *JSContext) -> compartment { pub fn get_compartment(cx: *JSContext) -> @mut Compartment {
unsafe { unsafe {
let content = task_from_context(cx); let content = task_from_context(cx);
let compartment = option::expect((*content).compartment, let compartment = option::expect((*content).compartment,
@ -96,9 +96,10 @@ extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSB
return 1; return 1;
} }
pub fn prototype_jsclass(name: ~str) -> @fn(compartment: &bare_compartment) -> JSClass { pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
let f: @fn(&bare_compartment) -> JSClass = |compartment: &bare_compartment, move name| { let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment, move name| {
{name: compartment.add_name(copy name), JSClass {
name: compartment.add_name(copy name),
flags: 0, flags: 0,
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8, addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8, delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
@ -120,16 +121,17 @@ pub fn prototype_jsclass(name: ~str) -> @fn(compartment: &bare_compartment) -> J
null(), null(), null(), null(), null(), // 25 null(), null(), null(), null(), null(), // 25
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; 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: @mut Compartment) -> JSClass {
let f: @fn(&bare_compartment) -> JSClass = let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment, move name| {
|compartment: &bare_compartment, move name| { JSClass {
{name: compartment.add_name(copy name), name: compartment.add_name(copy name),
flags: JSCLASS_HAS_RESERVED_SLOTS(1), flags: JSCLASS_HAS_RESERVED_SLOTS(1),
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8, addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8, delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
@ -151,13 +153,14 @@ pub fn instance_jsclass(name: ~str, finalize: *u8)
null(), null(), null(), null(), null(), // 25 null(), null(), null(), null(), null(), // 25
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; 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: @mut Compartment)
-> js::rust::jsobj { -> js::rust::jsobj {
compartment.register_class(prototype_jsclass(copy name)); compartment.register_class(prototype_jsclass(copy name));

View file

@ -1,23 +1,29 @@
use js::rust::{bare_compartment, methods}; // DOM bindings for the Window object.
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
JS_THIS_OBJECT, JS_SET_RVAL};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties, JS_EncodeString, JS_free};
use js::glue::bindgen::*;
use js::global::jsval_to_rust_str;
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub};
use js::glue::bindgen::RUST_JSVAL_TO_INT;
use ptr::null;
use libc::c_uint;
use dom::bindings::utils::{rust_box, squirrel_away, jsval_to_str};
use dom::bindings::node::create; use dom::bindings::node::create;
use dom::window::{Window, TimerMessage_Fire}; use dom::bindings::utils::{rust_box, squirrel_away, jsval_to_str};
use dom::node::Node; use dom::node::Node;
use core::dvec::DVec; use dom::window::{Window, TimerMessage_Fire};
use super::utils; use super::utils;
use core::dvec::DVec;
use core::libc::c_uint;
use core::ptr::null;
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub};
use js::crust::{JS_ResolveStub};
use js::global::jsval_to_rust_str;
use js::glue::bindgen::*;
use js::glue::bindgen::RUST_JSVAL_TO_INT;
use js::jsapi::bindgen::{JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties};
use js::jsapi::bindgen::{JS_EncodeString, JS_free};
use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSFunctionSpec};
use js::jsapi::{JSNativeWrapper};
use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JS_SET_RVAL};
extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {
let argv = JS_ARGV(cx, vp); let argv = JS_ARGV(cx, vp);
@ -69,7 +75,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
} }
} }
pub fn init(compartment: &bare_compartment, win: @Window) { pub fn init(compartment: @mut Compartment, win: @Window) {
let proto = utils::define_empty_prototype(~"Window", None, compartment); let proto = utils::define_empty_prototype(~"Window", None, compartment);
compartment.register_class(utils::instance_jsclass(~"WindowInstance", finalize)); compartment.register_class(utils::instance_jsclass(~"WindowInstance", finalize));
@ -78,27 +84,40 @@ pub fn init(compartment: &bare_compartment, win: @Window) {
~"Window", null())); ~"Window", null()));
/* Define methods on a window */ /* Define methods on a window */
let methods = ~[{name: compartment.add_name(~"alert"), let methods = [
call: {op: alert, info: null()}, JSFunctionSpec {
name: compartment.add_name(~"alert"),
call: JSNativeWrapper { op: alert, info: null() },
nargs: 1, nargs: 1,
flags: 0, flags: 0,
selfHostedName: null()}, selfHostedName: null()
{name: compartment.add_name(~"setTimeout"), },
call: {op: setTimeout, info: null()}, JSFunctionSpec {
name: compartment.add_name(~"setTimeout"),
call: JSNativeWrapper { op: setTimeout, info: null() },
nargs: 2, nargs: 2,
flags: 0, flags: 0,
selfHostedName: null()}, selfHostedName: null()
{name: compartment.add_name(~"close"), },
call: {op: close, info: null()}, JSFunctionSpec {
name: compartment.add_name(~"close"),
call: JSNativeWrapper { op: close, info: null() },
nargs: 2, nargs: 2,
flags: 0, flags: 0,
selfHostedName: null()}]; selfHostedName: null()
},
vec::as_imm_buf(methods, |fns, _len| { JSFunctionSpec {
JS_DefineFunctions(compartment.cx.ptr, proto.ptr, fns); name: null(),
}); call: JSNativeWrapper { op: null(), info: null() },
nargs: 0,
flags: 0,
selfHostedName: null()
}
];
unsafe { unsafe {
JS_DefineFunctions(compartment.cx.ptr, proto.ptr, &methods[0]);
let raw_ptr: *libc::c_void = cast::reinterpret_cast(&squirrel_away(win)); let raw_ptr: *libc::c_void = cast::reinterpret_cast(&squirrel_away(win));
JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr)); JS_SetReservedSlot(obj.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
} }

View file

@ -8,7 +8,7 @@ use geom::size::Size2D;
use js::crust::*; use js::crust::*;
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL; use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, JSVal, JSBool}; use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, JSVal, JSBool};
use js::rust::{bare_compartment, compartment, methods}; use js::rust::Compartment;
use js::{JSPROP_ENUMERATE, JSPROP_SHARED}; use js::{JSPROP_ENUMERATE, JSPROP_SHARED};
use layout::debug::DebugMethods; use layout::debug::DebugMethods;
use layout::flow::FlowContext; use layout::flow::FlowContext;
@ -115,8 +115,7 @@ pub fn DoctypeData(name: ~str, public_id: Option<~str>,
pub fn define_bindings(compartment: &bare_compartment, doc: @Document, pub fn define_bindings(compartment: @mut Compartment, doc: @Document, win: @Window) {
win: @Window) {
bindings::window::init(compartment, win); bindings::window::init(compartment, win);
bindings::document::init(compartment, doc); bindings::document::init(compartment, doc);
bindings::node::init(compartment); bindings::node::init(compartment);
@ -142,7 +141,7 @@ pub fn NodeScope() -> NodeScope {
cow::Scope() cow::Scope()
} }
trait NodeScopeExtensions { pub trait NodeScopeExtensions {
fn new_node(+k: NodeKind) -> Node; fn new_node(+k: NodeKind) -> Node;
} }

View file

@ -1,4 +1,4 @@
use oldcomm::{Port, Chan}; use core::pipes::{Port, Chan};
use content::content_task::{ControlMsg, Timer, ExitMsg}; use content::content_task::{ControlMsg, Timer, ExitMsg};
use js::jsapi::JSVal; use js::jsapi::JSVal;
use dvec::DVec; use dvec::DVec;
@ -62,8 +62,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.
timer::delayed_send(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

@ -16,15 +16,15 @@ use gfx::render_task;
use std::cell::Cell; use std::cell::Cell;
use std::net::url::Url; use std::net::url::Url;
pub type EngineTask = oldcomm::Chan<Msg>; pub type EngineTask = Chan<Msg>;
pub enum Msg { pub enum Msg {
LoadURLMsg(Url), LoadURLMsg(Url),
ExitMsg(Chan<()>) ExitMsg(Chan<()>)
} }
pub struct Engine<C:Compositor Owned Copy> { pub struct Engine<C> {
request_port: oldcomm::Port<Msg>, request_port: Port<Msg>,
compositor: C, compositor: C,
render_task: RenderTask, render_task: RenderTask,
resource_task: ResourceTask, resource_task: ResourceTask,
@ -33,30 +33,31 @@ pub struct Engine<C:Compositor Owned Copy> {
content_task: ContentTask content_task: ContentTask
} }
pub fn Engine<C:Compositor Owned Copy>(compositor: C, pub fn Engine<C:Compositor + Owned + Clone>(compositor: C,
opts: &Opts, opts: &Opts,
dom_event_port: pipes::Port<Event>, dom_event_port: pipes::Port<Event>,
dom_event_chan: pipes::SharedChan<Event>, dom_event_chan: pipes::SharedChan<Event>,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask) -> EngineTask { image_cache_task: ImageCacheTask)
-> EngineTask {
let dom_event_port = Cell(move dom_event_port); let dom_event_port = Cell(dom_event_port);
let dom_event_chan = Cell(move dom_event_chan); let dom_event_chan = Cell(dom_event_chan);
let opts = Cell(copy *opts); let opts = Cell(copy *opts);
do spawn_listener::<Msg> |request, move dom_event_port, move dom_event_chan, do spawn_listener::<Msg> |request| {
move image_cache_task, move opts| { let render_task = RenderTask(compositor.clone(), opts.with_ref(|o| copy *o));
let render_task = RenderTask(compositor, opts.with_ref(|o| copy *o)); let layout_task = LayoutTask(render_task.clone(), image_cache_task.clone(), opts.take());
let layout_task = LayoutTask(render_task, image_cache_task.clone(), opts.take()); let content_task = ContentTask(layout_task.clone(),
let content_task = ContentTask(layout_task, dom_event_port.take(),
dom_event_port.take(), dom_event_chan.take(), dom_event_chan.take(),
resource_task, image_cache_task.clone()); resource_task.clone(),
image_cache_task.clone());
Engine { Engine {
request_port: request, request_port: request,
compositor: compositor, compositor: compositor.clone(),
render_task: render_task, render_task: render_task,
resource_task: resource_task, resource_task: resource_task.clone(),
image_cache_task: image_cache_task.clone(), image_cache_task: image_cache_task.clone(),
layout_task: move layout_task, layout_task: move layout_task,
content_task: move content_task content_task: move content_task
@ -64,7 +65,7 @@ pub fn Engine<C:Compositor Owned Copy>(compositor: C,
} }
} }
impl<C: Compositor Copy Owned> Engine<C> { impl<C:Compositor + Owned + Clone> Engine<C> {
fn run() { fn run() {
while self.handle_request(self.request_port.recv()) { while self.handle_request(self.request_port.recv()) {
// Go on... // Go on...

View file

@ -4,13 +4,14 @@ Some little helpers for hooking up the HTML parser with the CSS parser
use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done}; use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
use core::pipes::{Port, Chan};
use core::pipes;
use core::str; use core::str;
use newcss::stylesheet::Stylesheet; use newcss::stylesheet::Stylesheet;
use newcss::util::DataStream; 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 {
@ -19,9 +20,9 @@ pub enum StylesheetProvenance {
} }
pub fn spawn_css_parser(provenance: StylesheetProvenance, pub fn spawn_css_parser(provenance: StylesheetProvenance,
resource_task: ResourceTask) -> oldcomm::Port<Stylesheet> { resource_task: ResourceTask)
let result_port = oldcomm::Port(); -> Port<Stylesheet> {
let result_chan = oldcomm::Chan(&result_port); let (result_port, result_chan) = pipes::stream();
let provenance_cell = Cell(move provenance); let provenance_cell = Cell(move provenance);
do task::spawn |move provenance_cell, copy resource_task| { do task::spawn |move provenance_cell, copy resource_task| {
@ -32,8 +33,9 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance,
} }
}; };
let sheet = Stylesheet::new(move url, data_stream(provenance_cell.take(), resource_task)); let sheet = Stylesheet::new(url, data_stream(provenance_cell.take(),
result_chan.send(move sheet); resource_task.clone()));
result_chan.send(sheet);
} }
return result_port; return result_port;
@ -42,8 +44,8 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance,
fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> DataStream { fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) -> DataStream {
match move provenance { match move provenance {
UrlProvenance(move url) => { UrlProvenance(move url) => {
let input_port = Port(); let (input_port, input_chan) = pipes::stream();
resource_task.send(Load(move url, input_port.chan())); resource_task.send(Load(move url, input_chan));
resource_port_to_data_stream(input_port) resource_port_to_data_stream(input_port)
} }
InlineProvenance(_, move data) => { InlineProvenance(_, move data) => {
@ -52,7 +54,7 @@ fn data_stream(provenance: StylesheetProvenance, resource_task: ResourceTask) ->
} }
} }
fn resource_port_to_data_stream(input_port: oldcomm::Port<ProgressMsg>) -> DataStream { fn resource_port_to_data_stream(input_port: Port<ProgressMsg>) -> DataStream {
return || { return || {
match input_port.recv() { match input_port.recv() {
Payload(move data) => Some(move data), Payload(move data) => Some(move data),

View file

@ -4,13 +4,14 @@ use content::content_task::ContentTask;
use dom::cow; use dom::cow;
use dom::element::*; use dom::element::*;
use dom::event::{Event, ReflowEvent}; use dom::event::{Event, ReflowEvent};
use dom::node::{Comment, Doctype, DoctypeData, Element, Node, NodeScope, Text}; use dom::node::{Comment, Doctype, DoctypeData, Element, Node, NodeScope, NodeScopeExtensions};
use dom::node::{Text};
use resource::image_cache_task::ImageCacheTask; use resource::image_cache_task::ImageCacheTask;
use resource::image_cache_task; use resource::image_cache_task;
use resource::resource_task::{Done, Load, Payload, ResourceTask}; use resource::resource_task::{Done, Load, Payload, ResourceTask};
use util::task::{spawn_listener, spawn_conversation}; use util::task::{spawn_listener, spawn_conversation};
use core::oldcomm::{Chan, Port}; use core::pipes::{Chan, Port, SharedChan};
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser}; use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
use hubbub::hubbub::Attribute; use hubbub::hubbub::Attribute;
use hubbub::hubbub; use hubbub::hubbub;
@ -32,8 +33,8 @@ enum JSMessage {
struct HtmlParserResult { struct HtmlParserResult {
root: Node, root: Node,
style_port: oldcomm::Port<Option<Stylesheet>>, style_port: Port<Option<Stylesheet>>,
js_port: oldcomm::Port<JSResult>, js_port: Port<JSResult>,
} }
/** /**
@ -51,15 +52,15 @@ spawned, collates them, and sends them to the given result channel.
* `from_parent` - A port on which to receive new links. * `from_parent` - A port on which to receive new links.
*/ */
fn css_link_listener(to_parent : oldcomm::Chan<Option<Stylesheet>>, fn css_link_listener(to_parent: Chan<Option<Stylesheet>>,
from_parent : oldcomm::Port<CSSMessage>, from_parent: Port<CSSMessage>,
resource_task: ResourceTask) { resource_task: ResourceTask) {
let mut result_vec = ~[]; let mut result_vec = ~[];
loop { loop {
match from_parent.recv() { match from_parent.recv() {
CSSTaskNewFile(move provenance) => { CSSTaskNewFile(provenance) => {
result_vec.push(spawn_css_parser(move provenance, copy resource_task)); result_vec.push(spawn_css_parser(provenance, resource_task.clone()));
} }
CSSTaskExit => { CSSTaskExit => {
break; break;
@ -75,19 +76,20 @@ fn css_link_listener(to_parent : oldcomm::Chan<Option<Stylesheet>>,
to_parent.send(None); to_parent.send(None);
} }
fn js_script_listener(to_parent : oldcomm::Chan<~[~[u8]]>, from_parent : oldcomm::Port<JSMessage>, fn js_script_listener(to_parent: Chan<~[~[u8]]>,
from_parent: Port<JSMessage>,
resource_task: ResourceTask) { resource_task: ResourceTask) {
let mut result_vec = ~[]; let mut result_vec = ~[];
loop { loop {
match from_parent.recv() { match from_parent.recv() {
JSTaskNewFile(move url) => { JSTaskNewFile(move url) => {
let result_port = oldcomm::Port(); let (result_port, result_chan) = pipes::stream();
let result_chan = oldcomm::Chan(&result_port); let resource_task = resource_task.clone();
do task::spawn |move url| { do task::spawn {
let input_port = Port(); let (input_port, input_chan) = pipes::stream();
// TODO: change copy to move once we can move into closures // TODO: change copy to move once we can move into closures
resource_task.send(Load(copy url, input_port.chan())); resource_task.send(Load(copy url, input_chan));
let mut buf = ~[]; let mut buf = ~[];
loop { loop {
@ -166,18 +168,22 @@ pub fn parse_html(scope: NodeScope,
resource_task: ResourceTask, resource_task: ResourceTask,
image_cache_task: ImageCacheTask) -> HtmlParserResult { image_cache_task: ImageCacheTask) -> HtmlParserResult {
// Spawn a CSS parser to receive links to CSS style sheets. // Spawn a CSS parser to receive links to CSS style sheets.
let (css_port, css_chan): (oldcomm::Port<Option<Stylesheet>>, oldcomm::Chan<CSSMessage>) = let resource_task2 = resource_task.clone();
do spawn_conversation |css_port: oldcomm::Port<CSSMessage>, let (css_port, css_chan): (Port<Option<Stylesheet>>, Chan<CSSMessage>) =
css_chan: oldcomm::Chan<Option<Stylesheet>>| { do spawn_conversation |css_port: Port<CSSMessage>,
css_link_listener(css_chan, css_port, resource_task); css_chan: Chan<Option<Stylesheet>>| {
css_link_listener(css_chan, css_port, resource_task2.clone());
}; };
let css_chan = SharedChan(css_chan);
// Spawn a JS parser to receive JavaScript. // Spawn a JS parser to receive JavaScript.
let (js_port, js_chan): (oldcomm::Port<JSResult>, oldcomm::Chan<JSMessage>) = let resource_task2 = resource_task.clone();
do spawn_conversation |js_port: oldcomm::Port<JSMessage>, let (js_port, js_chan): (Port<JSResult>, Chan<JSMessage>) =
js_chan: oldcomm::Chan<JSResult>| { do spawn_conversation |js_port: Port<JSMessage>,
js_script_listener(js_chan, js_port, resource_task); js_chan: Chan<JSResult>| {
js_script_listener(js_chan, js_port, resource_task2.clone());
}; };
let js_chan = SharedChan(js_chan);
let (scope, url) = (@copy scope, @move url); let (scope, url) = (@copy scope, @move url);
@ -192,6 +198,7 @@ pub fn parse_html(scope: NodeScope,
// Performs various actions necessary after appending has taken place. Currently, this consists // Performs various actions necessary after appending has taken place. Currently, this consists
// of processing inline stylesheets, but in the future it might perform prefetching, etc. // of processing inline stylesheets, but in the future it might perform prefetching, etc.
let css_chan2 = css_chan.clone();
let append_hook: @fn(Node, Node) = |parent_node, child_node| { let append_hook: @fn(Node, Node) = |parent_node, child_node| {
do scope.read(&parent_node) |parent_node_contents| { do scope.read(&parent_node) |parent_node_contents| {
do scope.read(&child_node) |child_node_contents| { do scope.read(&child_node) |child_node_contents| {
@ -203,7 +210,7 @@ pub fn parse_html(scope: NodeScope,
let url = url::from_str("http://example.com/"); // FIXME let url = url::from_str("http://example.com/"); // FIXME
let provenance = InlineProvenance(result::unwrap(move url), let provenance = InlineProvenance(result::unwrap(move url),
copy *data); copy *data);
css_chan.send(CSSTaskNewFile(move provenance)); css_chan2.send(CSSTaskNewFile(move provenance));
} }
_ => {} // Nothing to do. _ => {} // Nothing to do.
} }
@ -214,6 +221,7 @@ pub fn parse_html(scope: NodeScope,
} }
}; };
let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
parser.set_tree_handler(@hubbub::TreeHandler { parser.set_tree_handler(@hubbub::TreeHandler {
create_comment: |data: ~str| { create_comment: |data: ~str| {
debug!("create comment"); debug!("create comment");
@ -257,8 +265,8 @@ pub fn parse_html(scope: NodeScope,
(Some(move rel), Some(move href)) => { (Some(move rel), Some(move href)) => {
if rel == ~"stylesheet" { if rel == ~"stylesheet" {
debug!("found CSS stylesheet: %s", href); debug!("found CSS stylesheet: %s", href);
css_chan.send(CSSTaskNewFile(UrlProvenance(make_url(move href, css_chan2.send(CSSTaskNewFile(UrlProvenance(make_url(
Some(copy *url))))); href, Some(copy *url)))));
} }
} }
_ => {} _ => {}
@ -341,7 +349,10 @@ pub fn parse_html(scope: NodeScope,
complete_script: |script| { complete_script: |script| {
// A little function for holding this lint attr // A little function for holding this lint attr
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
fn complete_script(scope: &NodeScope, script: hubbub::NodeDataPtr, url: &Url, js_chan: &oldcomm::Chan<JSMessage>) { fn complete_script(scope: &NodeScope,
script: hubbub::NodeDataPtr,
url: &Url,
js_chan: SharedChan<JSMessage>) {
unsafe { unsafe {
do scope.read(&cow::wrap(cast::transmute(script))) |node_contents| { do scope.read(&cow::wrap(cast::transmute(script))) |node_contents| {
match *node_contents.kind { match *node_contents.kind {
@ -360,14 +371,14 @@ pub fn parse_html(scope: NodeScope,
} }
} }
} }
complete_script(scope, script, url, &js_chan); complete_script(scope, script, url, js_chan2.clone());
debug!("complete script"); debug!("complete script");
} }
}); });
debug!("set tree handler"); debug!("set tree handler");
let input_port = Port(); let (input_port, input_chan) = pipes::stream();
resource_task.send(Load(copy *url, input_port.chan())); resource_task.send(Load(copy *url, input_chan));
debug!("loaded page"); debug!("loaded page");
loop { loop {
match input_port.recv() { match input_port.recv() {

View file

@ -1,16 +1,20 @@
use au = gfx::geometry; // Block layout.
use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::inline::InlineLayout;
use newcss::values::*; use newcss::values::*;
use util::tree;
use au = gfx::geometry;
use core::mutable::Mut;
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 gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::geometry::Au; use gfx::geometry::Au;
use layout::box::{RenderBox};
use layout::context::LayoutContext;
use layout::display_list_builder::DisplayListBuilder;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use util::tree;
use core::mutable::Mut;
pub struct BlockFlowData { pub struct BlockFlowData {
mut box: Option<@RenderBox> mut box: Option<@RenderBox>
@ -22,15 +26,18 @@ pub fn BlockFlowData() -> BlockFlowData {
} }
} }
trait BlockLayout { pub trait BlockLayout {
pure fn starts_block_flow() -> bool; pure fn starts_block_flow() -> bool;
pure fn with_block_box(@self, fn(box: &@RenderBox) -> ()) -> (); pure fn with_block_box(@self, fn(box: &@RenderBox) -> ()) -> ();
fn bubble_widths_block(@self, ctx: &LayoutContext); fn bubble_widths_block(@self, ctx: &LayoutContext);
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,
c: &Point2D<Au>, d: &Mut<DisplayList>); a: &DisplayListBuilder,
b: &Rect<Au>,
c: &Point2D<Au>,
d: &Mut<DisplayList>);
} }
impl FlowContext : BlockLayout { impl FlowContext : BlockLayout {
@ -54,7 +61,7 @@ impl FlowContext : BlockLayout {
let mut box = self.root().box; let mut box = self.root().box;
box.iter(cb); box.iter(cb);
}, },
_ => fail fmt!("Tried to do something with_block_box(), but this is a %?", self) _ => fail!(fmt!("Tried to do something with_block_box(), but this is a %?", self))
} }
} }

View file

@ -1,5 +1,6 @@
/* Fundamental layout structures and algorithms. */ /* Fundamental layout structures and algorithms. */
use css::node_style::StyledNode;
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement}; use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree}; use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -8,23 +9,6 @@ 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 layout;
use util::tree::ReadMethods;
use core::mutable::Mut;
use arc = std::arc;
use core::managed;
use core::dvec::DVec;
use core::to_str::ToStr;
use core::rand;
use core::task::spawn;
use geom::{Point2D, Rect, Size2D};
use gfx;
use gfx::display_list::{DisplayItem, DisplayList};
use gfx::font::{FontStyle, FontWeight300};
use gfx::geometry::Au;
use gfx::image::base::Image;
use gfx::image::holder::ImageHolder;
use gfx::text::text_run::TextRun;
use gfx::util::range::*;
use newcss::color::{Color, rgba, rgb}; use newcss::color::{Color, rgba, rgb};
use newcss::complete::CompleteStyle; use newcss::complete::CompleteStyle;
use newcss::units::{BoxSizing, Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif}; use newcss::units::{BoxSizing, Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif};
@ -33,7 +17,25 @@ use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium, CSSDisplay};
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily, CSSPositionAbsolute}; use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily, CSSPositionAbsolute};
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal}; use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, Specified}; use newcss::values::{CSSFontStyleOblique, CSSTextAlign, Specified};
use util::tree::ReadMethods;
use core::dvec::DVec;
use core::managed;
use core::mutable::Mut;
use core::rand;
use core::task::spawn;
use core::to_str::ToStr;
use geom::{Point2D, Rect, Size2D};
use gfx::display_list::{DisplayItem, DisplayList};
use gfx::font::{FontStyle, FontWeight300};
use gfx::geometry::Au;
use gfx::image::base::Image;
use gfx::image::holder::ImageHolder;
use gfx::text::text_run::TextRun;
use gfx::util::range::*;
use gfx;
use std::arc::ARC; use std::arc::ARC;
use std::arc;
use std::net::url::Url; use std::net::url::Url;
/** /**
@ -165,7 +167,7 @@ impl RenderBox {
match self { match self {
@GenericBox(*) => CannotSplit(self), @GenericBox(*) => CannotSplit(self),
@ImageBox(*) => CannotSplit(self), @ImageBox(*) => CannotSplit(self),
@UnscannedTextBox(*) => fail ~"WAT: shouldn't be an unscanned text box here.", @UnscannedTextBox(*) => fail!(~"WAT: shouldn't be an unscanned text box here."),
@TextBox(_,data) => { @TextBox(_,data) => {
let mut pieces_processed_count : uint = 0; let mut pieces_processed_count : uint = 0;
@ -249,7 +251,7 @@ impl RenderBox {
// 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_or_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.")
} }
} }
@ -281,7 +283,7 @@ impl RenderBox {
max_line_width max_line_width
}, },
&UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here." &UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here.")
} }
} }
@ -333,7 +335,7 @@ impl RenderBox {
&TextBox(*) => { &TextBox(*) => {
copy self.d().position copy self.d().position
}, },
&UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here." &UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here.")
} }
} }
@ -401,7 +403,7 @@ impl RenderBox {
self.add_bgcolor_to_list(list, &abs_box_bounds); self.add_bgcolor_to_list(list, &abs_box_bounds);
match self { match self {
@UnscannedTextBox(*) => fail ~"Shouldn't see unscanned boxes here.", @UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here."),
@TextBox(_,data) => { @TextBox(_,data) => {
do list.borrow_mut |list| { do list.borrow_mut |list| {
let nearest_ancestor_element = self.nearest_ancestor_element(); let nearest_ancestor_element = self.nearest_ancestor_element();
@ -606,7 +608,7 @@ impl RenderBox {
let mut node = self.d().node; let mut node = self.d().node;
while !node.is_element() { while !node.is_element() {
match NodeTree.get_parent(&node) { match NodeTree.get_parent(&node) {
None => fail ~"no nearest element?!", None => fail!(~"no nearest element?!"),
Some(move parent) => node = move parent, Some(move parent) => node = move parent,
} }
} }

View file

@ -6,6 +6,7 @@ use dom::node::{Comment, Doctype, Element, Text, Node, LayoutData};
use layout::box::*; use layout::box::*;
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::{BoxedDebugMethods, DebugMethods};
use layout::flow::*; use layout::flow::*;
use layout::inline::InlineFlowData; use layout::inline::InlineFlowData;
use layout::root::RootFlowData; use layout::root::RootFlowData;
@ -370,7 +371,7 @@ impl LayoutTreeBuilder {
fn fixup_split_inline(_foo: @FlowContext) { fn fixup_split_inline(_foo: @FlowContext) {
// TODO: finish me. // TODO: finish me.
fail ~"TODO: handle case where an inline is split by a block" fail!(~"TODO: handle case where an inline is split by a block")
} }
/** entry point for box creation. Should only be /** entry point for box creation. Should only be
@ -435,9 +436,9 @@ impl LayoutTreeBuilder {
self.make_generic_box(layout_ctx, node, ctx) self.make_generic_box(layout_ctx, node, ctx)
} }
}, },
_ => fail ~"WAT error: why couldn't we make an image box?" _ => fail!(~"WAT error: why couldn't we make an image box?")
}, },
_ => fail ~"WAT error: why couldn't we make an image box?" _ => fail!(~"WAT error: why couldn't we make an image box?")
} }
} }
@ -447,7 +448,7 @@ impl LayoutTreeBuilder {
do node.read |n| { do node.read |n| {
match n.kind { match n.kind {
~Text(ref string) => @UnscannedTextBox(RenderBoxData(node, ctx, self.next_box_id()), copy *string), ~Text(ref string) => @UnscannedTextBox(RenderBoxData(node, ctx, self.next_box_id()), copy *string),
_ => fail ~"WAT error: why couldn't we make a text box?" _ => fail!(~"WAT error: why couldn't we make a text box?")
} }
} }
} }
@ -455,14 +456,19 @@ impl LayoutTreeBuilder {
fn decide_box_type(node: Node, display: CSSDisplay) -> RenderBoxType { fn decide_box_type(node: Node, display: CSSDisplay) -> RenderBoxType {
do node.read |n| { do node.read |n| {
match n.kind { match n.kind {
~Doctype(*) | ~Comment(*) => fail ~"Hey, doctypes and comments shouldn't get here! They are display:none!", ~Doctype(*) | ~Comment(*) => {
fail!(~"Hey, doctypes and comments shouldn't get here! \
They are display:none!")
}
~Text(*) => RenderBox_Text, ~Text(*) => RenderBox_Text,
~Element(ref element) => { ~Element(ref element) => {
match (&element.kind, display) { match (&element.kind, display) {
(&~HTMLImageElement(ref d), _) if d.image.is_some() => RenderBox_Image, (&~HTMLImageElement(ref d), _) if d.image.is_some() => RenderBox_Image,
// (_, Specified(_)) => GenericBox, // (_, Specified(_)) => GenericBox,
(_, _) => RenderBox_Generic // TODO: replace this with the commented lines (_, _) => RenderBox_Generic // TODO: replace this with the commented lines
// (_, _) => fail ~"Can't create box for Node with non-specified 'display' type" //(_, _) => {
// fail!(~"Can't create box for Node with non-specified 'display' type")
//}
} }
} }
} }

View file

@ -1,5 +1,3 @@
export DisplayListBuilder;
use newcss::values::Specified; use newcss::values::Specified;
use newcss::values::{CSSBackgroundColorColor, CSSBackgroundColorTransparent}; use newcss::values::{CSSBackgroundColorColor, CSSBackgroundColorTransparent};
use dom::node::{Text, NodeScope}; use dom::node::{Text, NodeScope};
@ -31,16 +29,20 @@ pub struct DisplayListBuilder {
ctx: &LayoutContext, ctx: &LayoutContext,
} }
pub 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,
fn build_display_list_for_child(@self, a: &DisplayListBuilder, b: @FlowContext, a: &DisplayListBuilder,
c: &Rect<Au>, d: &Point2D<Au>, e: &Mut<DisplayList>); b: @FlowContext,
c: &Rect<Au>,
d: &Point2D<Au>,
e: &Mut<DisplayList>);
} }
impl FlowContext: FlowDisplayListBuilderMethods { impl FlowDisplayListBuilderMethods for FlowContext {
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);

View file

@ -1,12 +1,12 @@
use core; use core;
use dom::node::Node; use dom::node::Node;
use layout::block::BlockFlowData; use layout::block::{BlockFlowData, BlockLayout};
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::BoxedDebugMethods; use layout::debug::BoxedDebugMethods;
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use layout::inline::{InlineFlowData, NodeRange}; use layout::inline::{InlineFlowData, InlineLayout, NodeRange};
use layout::root::RootFlowData; use layout::root::{RootFlowData, RootLayout};
use util::tree; use util::tree;
use core::mutable::Mut; use core::mutable::Mut;
use core::dvec::DVec; use core::dvec::DVec;
@ -109,21 +109,21 @@ impl FlowContext {
pure fn inline(&self) -> &self/InlineFlowData { pure fn inline(&self) -> &self/InlineFlowData {
match *self { match *self {
InlineFlow(_, ref i) => i, InlineFlow(_, ref i) => i,
_ => fail fmt!("Tried to access inline data of non-inline: f%d", self.d().id) _ => fail!(fmt!("Tried to access inline data of non-inline: f%d", self.d().id))
} }
} }
pure fn block(&self) -> &self/BlockFlowData { pure fn block(&self) -> &self/BlockFlowData {
match *self { match *self {
BlockFlow(_, ref b) => b, BlockFlow(_, ref b) => b,
_ => fail fmt!("Tried to access block data of non-block: f%d", self.d().id) _ => fail!(fmt!("Tried to access block data of non-block: f%d", self.d().id))
} }
} }
pure fn root(&self) -> &self/RootFlowData { pure fn root(&self) -> &self/RootFlowData {
match *self { match *self {
RootFlow(_, ref r) => r, RootFlow(_, ref r) => r,
_ => fail fmt!("Tried to access root data of non-root: f%d", self.d().id) _ => fail!(fmt!("Tried to access root data of non-root: f%d", self.d().id))
} }
} }
@ -132,7 +132,7 @@ impl FlowContext {
@BlockFlow(*) => self.bubble_widths_block(ctx), @BlockFlow(*) => self.bubble_widths_block(ctx),
@InlineFlow(*) => self.bubble_widths_inline(ctx), @InlineFlow(*) => self.bubble_widths_inline(ctx),
@RootFlow(*) => self.bubble_widths_root(ctx), @RootFlow(*) => self.bubble_widths_root(ctx),
_ => fail fmt!("Tried to bubble_widths of flow: f%d", self.d().id) _ => fail!(fmt!("Tried to bubble_widths of flow: f%d", self.d().id))
} }
} }
@ -141,7 +141,7 @@ impl FlowContext {
@BlockFlow(*) => self.assign_widths_block(ctx), @BlockFlow(*) => self.assign_widths_block(ctx),
@InlineFlow(*) => self.assign_widths_inline(ctx), @InlineFlow(*) => self.assign_widths_inline(ctx),
@RootFlow(*) => self.assign_widths_root(ctx), @RootFlow(*) => self.assign_widths_root(ctx),
_ => fail fmt!("Tried to assign_widths of flow: f%d", self.d().id) _ => fail!(fmt!("Tried to assign_widths of flow: f%d", self.d().id))
} }
} }
@ -150,7 +150,7 @@ impl FlowContext {
@BlockFlow(*) => self.assign_height_block(ctx), @BlockFlow(*) => self.assign_height_block(ctx),
@InlineFlow(*) => self.assign_height_inline(ctx), @InlineFlow(*) => self.assign_height_inline(ctx),
@RootFlow(*) => self.assign_height_root(ctx), @RootFlow(*) => self.assign_height_root(ctx),
_ => fail fmt!("Tried to assign_height of flow: f%d", self.d().id) _ => fail!(fmt!("Tried to assign_height of flow: f%d", self.d().id))
} }
} }
@ -162,7 +162,7 @@ impl FlowContext {
@RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list), @RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
@BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list), @BlockFlow(*) => self.build_display_list_block(builder, dirty, offset, list),
@InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list), @InlineFlow(*) => self.build_display_list_inline(builder, dirty, offset, list),
_ => fail fmt!("Tried to build_display_list_recurse of flow: %?", self) _ => fail!(fmt!("Tried to build_display_list_recurse of flow: %?", self))
} }
} }
@ -173,7 +173,7 @@ impl FlowContext {
RootFlow(*) => option::map_default(&self.root().box, seed, |box| { cb(seed, *box) }), RootFlow(*) => option::map_default(&self.root().box, seed, |box| { cb(seed, *box) }),
BlockFlow(*) => option::map_default(&self.block().box, seed, |box| { cb(seed, *box) }), BlockFlow(*) => option::map_default(&self.block().box, seed, |box| { cb(seed, *box) }),
InlineFlow(*) => do self.inline().boxes.foldl(seed) |acc, box| { cb(*acc, *box) }, InlineFlow(*) => do self.inline().boxes.foldl(seed) |acc, box| { cb(*acc, *box) },
_ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self) _ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
} }
} }
@ -190,7 +190,7 @@ impl FlowContext {
RootFlow(*) => do self.root().box.iter |box| { cb(*box); }, RootFlow(*) => do self.root().box.iter |box| { cb(*box); },
BlockFlow(*) => do self.block().box.iter |box| { cb(*box); }, BlockFlow(*) => do self.block().box.iter |box| { cb(*box); },
InlineFlow(*) => for self.inline().boxes.each |box| { cb(*box); }, InlineFlow(*) => for self.inline().boxes.each |box| { cb(*box); },
_ => fail fmt!("Don't know how to iterate node's RenderBoxes for %?", self) _ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
} }
} }

View file

@ -2,13 +2,13 @@ use core;
use dom::node::Node; use dom::node::Node;
use layout::box::*; use layout::box::*;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::{BoxedDebugMethods, DebugMethods};
use layout::flow::{FlowContext, InlineFlow}; use layout::flow::{FlowContext, InlineFlow};
use layout::text::TextBoxData; use layout::text::{TextBoxData, UnscannedMethods};
use util::tree; use util::tree;
use core::dlist::DList; use core::dlist::DList;
use core::dvec::DVec; use core::dvec::DVec;
use core::num::Num;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx::font::FontStyle; use gfx::font::FontStyle;
use gfx::geometry::Au; use gfx::geometry::Au;
@ -227,7 +227,9 @@ priv impl TextRunScanner {
}; };
match (is_singleton, is_text_clump) { match (is_singleton, is_text_clump) {
(false, false) => fail ~"WAT: can't coalesce non-text nodes in flush_clump_to_list()!", (false, false) => {
fail!(~"WAT: can't coalesce non-text nodes in flush_clump_to_list()!")
}
(true, false) => { (true, false) => {
debug!("TextRunScanner: pushing single non-text box in range: %?", self.clump); debug!("TextRunScanner: pushing single non-text box in range: %?", self.clump);
out_boxes.push(in_boxes[self.clump.begin()]); out_boxes.push(in_boxes[self.clump.begin()]);
@ -323,7 +325,7 @@ priv impl TextRunScanner {
struct LineboxScanner { struct LineboxScanner {
flow: @FlowContext, flow: @FlowContext,
new_boxes: DVec<@RenderBox>, new_boxes: DVec<@RenderBox>,
work_list: @DList<@RenderBox>, work_list: @mut DList<@RenderBox>,
pending_line: {mut range: Range, mut width: Au}, pending_line: {mut range: Range, mut width: Au},
line_spans: DVec<Range>, line_spans: DVec<Range>,
} }
@ -341,19 +343,19 @@ fn LineboxScanner(inline: @FlowContext) -> LineboxScanner {
} }
impl LineboxScanner { impl LineboxScanner {
priv fn reset_scanner() { priv fn reset_scanner(&mut self) {
debug!("Resetting line box scanner's state for flow f%d.", self.flow.d().id); debug!("Resetting line box scanner's state for flow f%d.", self.flow.d().id);
self.line_spans.set(~[]); self.line_spans.set(~[]);
self.new_boxes.set(~[]); self.new_boxes.set(~[]);
self.reset_linebox(); self.reset_linebox();
} }
priv fn reset_linebox() { priv fn reset_linebox(&mut self) {
self.pending_line.range.reset(0,0); self.pending_line.range.reset(0,0);
self.pending_line.width = Au(0); self.pending_line.width = Au(0);
} }
pub fn scan_for_lines(ctx: &LayoutContext) { pub fn scan_for_lines(&mut self, ctx: &LayoutContext) {
self.reset_scanner(); self.reset_scanner();
let boxes = &self.flow.inline().boxes; let boxes = &self.flow.inline().boxes;
@ -394,7 +396,7 @@ impl LineboxScanner {
self.swap_out_results(); self.swap_out_results();
} }
priv fn swap_out_results() { priv fn swap_out_results(&mut self) {
debug!("LineboxScanner: Propagating scanned lines[n=%u] to inline flow f%d", debug!("LineboxScanner: Propagating scanned lines[n=%u] to inline flow f%d",
self.line_spans.len(), self.flow.d().id); self.line_spans.len(), self.flow.d().id);
@ -408,7 +410,7 @@ impl LineboxScanner {
}; };
} }
priv fn flush_current_line() { priv fn flush_current_line(&mut self) {
debug!("LineboxScanner: Flushing line %u: %?", debug!("LineboxScanner: Flushing line %u: %?",
self.line_spans.len(), self.pending_line); self.line_spans.len(), self.pending_line);
// set box horizontal offsets // set box horizontal offsets
@ -465,7 +467,7 @@ impl LineboxScanner {
} }
// return value: whether any box was appended. // return value: whether any box was appended.
priv fn try_append_to_line(ctx: &LayoutContext, in_box: @RenderBox) -> bool { priv fn try_append_to_line(&mut self, ctx: &LayoutContext, in_box: @RenderBox) -> bool {
let remaining_width = self.flow.d().position.size.width - self.pending_line.width; let remaining_width = self.flow.d().position.size.width - self.pending_line.width;
let in_box_width = in_box.d().position.size.width; let in_box_width = in_box.d().position.size.width;
let line_is_empty: bool = self.pending_line.range.length() == 0; let line_is_empty: bool = self.pending_line.range.length() == 0;
@ -545,7 +547,7 @@ impl LineboxScanner {
} }
// unconditional push // unconditional push
priv fn push_box_to_line(box: @RenderBox) { priv fn push_box_to_line(&mut self, box: @RenderBox) {
debug!("LineboxScanner: Pushing box b%d to line %u", box.d().id, self.line_spans.len()); debug!("LineboxScanner: Pushing box b%d to line %u", box.d().id, self.line_spans.len());
if self.pending_line.range.length() == 0 { if self.pending_line.range.length() == 0 {
@ -579,7 +581,7 @@ pub fn InlineFlowData() -> InlineFlowData {
} }
} }
trait InlineLayout { pub trait InlineLayout {
pure fn starts_inline_flow() -> bool; pure fn starts_inline_flow() -> bool;
fn bubble_widths_inline(@self, ctx: &LayoutContext); fn bubble_widths_inline(@self, ctx: &LayoutContext);
@ -630,7 +632,7 @@ impl FlowContext : InlineLayout {
}, },
// TODO(Issue #225): different cases for 'inline-block', other replaced content // TODO(Issue #225): different cases for 'inline-block', other replaced content
@GenericBox(*) => Au::from_px(45), @GenericBox(*) => Au::from_px(45),
_ => fail fmt!("Tried to assign width to unknown Box variant: %?", box) _ => fail!(fmt!("Tried to assign width to unknown Box variant: %?", box))
}; };
} // for boxes.each |box| } // for boxes.each |box|
@ -670,7 +672,10 @@ impl FlowContext : InlineLayout {
}, },
// TODO(Issue #225): different cases for 'inline-block', other replaced content // TODO(Issue #225): different cases for 'inline-block', other replaced content
@GenericBox(*) => Au::from_px(30), @GenericBox(*) => Au::from_px(30),
_ => fail fmt!("Tried to assign height to unknown Box variant: %s", cur_box.debug_str()) _ => {
fail!(fmt!("Tried to assign height to unknown Box variant: %s",
cur_box.debug_str()))
}
}; };
// compute bounding rect, with left baseline as origin. // compute bounding rect, with left baseline as origin.
@ -691,7 +696,10 @@ impl FlowContext : InlineLayout {
let text_bounds = data.run.metrics_for_range(&const data.range).bounding_box; let text_bounds = data.run.metrics_for_range(&const data.range).bounding_box;
text_bounds.translate(&Point2D(cur_box.d().position.origin.x, Au(0))) text_bounds.translate(&Point2D(cur_box.d().position.origin.x, Au(0)))
}, },
_ => fail fmt!("Tried to compute bounding box of unknown Box variant: %s", cur_box.debug_str()) _ => {
fail!(fmt!("Tried to compute bounding box of unknown Box variant: %s",
cur_box.debug_str()))
}
}; };
debug!("assign_height_inline: bounding box for box b%d = %?", cur_box.d().id, bounding_box); debug!("assign_height_inline: bounding box for box b%d = %?", cur_box.d().id, bounding_box);
linebox_bounding_box = linebox_bounding_box.union(&bounding_box); linebox_bounding_box = linebox_bounding_box.union(&bounding_box);

View file

@ -1,23 +1,24 @@
/** /// The layout task. Performs layout on the DOM, builds display lists and sends them to be
The layout task. Performs layout on the DOM, builds display lists and sends them to be /// rendered.
rendered.
*/
use content::content_task; use content::content_task;
use css::matching::MatchMethods;
use css::select::new_css_select_ctx; use css::select::new_css_select_ctx;
use dom::event::{Event, ReflowEvent}; use dom::event::{Event, ReflowEvent};
use dom::node::{Node, LayoutData}; use dom::node::{Node, LayoutData};
use layout::aux::LayoutAuxMethods;
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::box_builder::LayoutTreeBuilder; use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list_builder::DisplayListBuilder; use layout::debug::{BoxedDebugMethods, DebugMethods};
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::traverse::*; use layout::traverse::*;
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg}; use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg};
use resource::local_image_cache::LocalImageCache; use resource::local_image_cache::LocalImageCache;
use util::time::time;
use util::task::spawn_listener; use util::task::spawn_listener;
use util::time::time;
use core::oldcomm::*; // FIXME: Bad! Pipe-ify me. use core::pipes::{Chan, Port, SharedChan};
use core::dvec::DVec; use core::dvec::DVec;
use core::mutable::Mut; use core::mutable::Mut;
use core::task::*; use core::task::*;
@ -34,12 +35,11 @@ use gfx::render_task::{RenderMsg, RenderTask};
use newcss::select::SelectCtx; use newcss::select::SelectCtx;
use newcss::stylesheet::Stylesheet; use newcss::stylesheet::Stylesheet;
use newcss::types::OriginAuthor; use newcss::types::OriginAuthor;
use opt = core::option;
use std::arc::ARC; use std::arc::ARC;
use std::cell::Cell; use std::cell::Cell;
use std::net::url::Url; use std::net::url::Url;
pub type LayoutTask = oldcomm::Chan<Msg>; pub type LayoutTask = SharedChan<Msg>;
pub enum LayoutQuery { pub enum LayoutQuery {
ContentBox(Node) ContentBox(Node)
@ -54,7 +54,7 @@ enum LayoutQueryResponse_ {
pub enum Msg { pub enum Msg {
AddStylesheet(Stylesheet), AddStylesheet(Stylesheet),
BuildMsg(BuildData), BuildMsg(BuildData),
QueryMsg(LayoutQuery, oldcomm::Chan<LayoutQueryResponse>), QueryMsg(LayoutQuery, Chan<LayoutQueryResponse>),
ExitMsg ExitMsg
} }
@ -88,16 +88,16 @@ pub struct BuildData {
pub fn LayoutTask(render_task: RenderTask, pub fn LayoutTask(render_task: RenderTask,
img_cache_task: ImageCacheTask, img_cache_task: ImageCacheTask,
opts: Opts) -> LayoutTask { opts: Opts) -> LayoutTask {
do spawn_listener::<Msg> |from_content, move img_cache_task, move opts| { SharedChan(spawn_listener::<Msg>(|from_content| {
Layout(render_task, img_cache_task.clone(), from_content, &opts).start(); Layout(render_task.clone(), img_cache_task.clone(), from_content, &opts).start();
} }))
} }
struct Layout { struct Layout {
render_task: RenderTask, render_task: RenderTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
local_image_cache: @LocalImageCache, local_image_cache: @LocalImageCache,
from_content: oldcomm::Port<Msg>, from_content: Port<Msg>,
font_ctx: @FontContext, font_ctx: @FontContext,
// This is used to root auxilliary RCU reader data // This is used to root auxilliary RCU reader data
@ -107,9 +107,9 @@ struct Layout {
fn Layout(render_task: RenderTask, fn Layout(render_task: RenderTask,
image_cache_task: ImageCacheTask, image_cache_task: ImageCacheTask,
from_content: oldcomm::Port<Msg>, from_content: Port<Msg>,
opts: &Opts) -> Layout { opts: &Opts)
-> Layout {
let fctx = @FontContext::new(opts.render_backend, true); let fctx = @FontContext::new(opts.render_backend, true);
Layout { Layout {
@ -146,8 +146,9 @@ impl Layout {
} }
QueryMsg(query, chan) => { QueryMsg(query, chan) => {
let chan = Cell(chan);
do time("layout: querying layout") { do time("layout: querying layout") {
self.handle_query(query, chan) self.handle_query(query, chan.take())
} }
} }
ExitMsg => { ExitMsg => {
@ -213,7 +214,7 @@ impl Layout {
let layout_root: @FlowContext = match builder.construct_trees(&layout_ctx, let layout_root: @FlowContext = match builder.construct_trees(&layout_ctx,
*node) { *node) {
Ok(root) => root, Ok(root) => root,
Err(*) => fail ~"Root flow should always exist" Err(*) => fail!(~"Root flow should always exist")
}; };
debug!("layout: constructed Flow tree"); debug!("layout: constructed Flow tree");
@ -238,7 +239,8 @@ impl Layout {
// TODO: set options on the builder before building // TODO: set options on the builder before building
// TODO: be smarter about what needs painting // TODO: be smarter about what needs painting
layout_root.build_display_list(&builder, &copy layout_root.d().position, layout_root.build_display_list(&builder,
&copy layout_root.d().position,
&display_list); &display_list);
let render_layer = RenderLayer { let render_layer = RenderLayer {
@ -256,7 +258,7 @@ impl Layout {
fn handle_query(query: LayoutQuery, fn handle_query(query: LayoutQuery,
reply_chan: oldcomm::Chan<LayoutQueryResponse>) { reply_chan: Chan<LayoutQueryResponse>) {
match query { match query {
ContentBox(node) => { ContentBox(node) => {
let response = do node.aux |a| { let response = do node.aux |a| {

View file

@ -4,6 +4,7 @@ use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::geometry::Au; use gfx::geometry::Au;
use layout::block::BlockLayout;
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
@ -21,7 +22,7 @@ pub fn RootFlowData() -> RootFlowData {
} }
} }
trait RootLayout { pub trait RootLayout {
pure fn starts_root_flow() -> bool; pure fn starts_root_flow() -> bool;
fn bubble_widths_root(@self, ctx: &LayoutContext); fn bubble_widths_root(@self, ctx: &LayoutContext);

View file

@ -32,15 +32,15 @@ pub fn adapt_textbox_with_range(box_data: &RenderBoxData, run: @TextRun,
@TextBox(move new_box_data, move new_text_data) @TextBox(move new_box_data, move new_text_data)
} }
trait UnscannedMethods { pub trait UnscannedMethods {
pure fn raw_text() -> ~str; pure fn raw_text(&self) -> ~str;
} }
impl RenderBox : UnscannedMethods { impl RenderBox : UnscannedMethods {
pure fn raw_text() -> ~str { pure fn raw_text(&self) -> ~str {
match &self { match self {
&UnscannedTextBox(_, ref s) => copy *s, &UnscannedTextBox(_, ref s) => copy *s,
_ => fail ~"unsupported operation: box.raw_text() on non-unscanned text box." _ => fail!(~"unsupported operation: box.raw_text() on non-unscanned text box.")
} }
} }
} }

View file

@ -4,7 +4,7 @@ use platform::resize_rate_limiter::ResizeRateLimiter;
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods}; use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::dvec::DVec; use core::dvec::DVec;
use core::pipes::Chan; use core::pipes::{Chan, SharedChan, Port};
use core::task::TaskBuilder; use core::task::TaskBuilder;
use core::util; use core::util;
use geom::matrix::{Matrix4, identity}; use geom::matrix::{Matrix4, identity};
@ -23,7 +23,15 @@ use sharegl;
use sharegl::ShareGlContext; use sharegl::ShareGlContext;
pub struct OSMain { pub struct OSMain {
chan: oldcomm::Chan<Msg> chan: SharedChan<Msg>
}
impl Clone for OSMain {
fn clone(&self) -> OSMain {
OSMain {
chan: self.chan.clone()
}
}
} }
// FIXME: Move me over to opts.rs. // FIXME: Move me over to opts.rs.
@ -45,9 +53,10 @@ pub enum Msg {
} }
pub fn OSMain(dom_event_chan: pipes::SharedChan<Event>, opts: Opts) -> OSMain { pub fn OSMain(dom_event_chan: pipes::SharedChan<Event>, opts: Opts) -> OSMain {
let dom_event_chan = Cell(move dom_event_chan); let dom_event_chan = Cell(dom_event_chan);
OSMain { OSMain {
chan: do on_osmain::<Msg> |po, move dom_event_chan, move opts| { chan: SharedChan(on_osmain::<Msg>(|po, move dom_event_chan, move opts| {
let po = Cell(po);
do platform::runmain { do platform::runmain {
debug!("preparing to enter main loop"); debug!("preparing to enter main loop");
@ -58,9 +67,9 @@ pub fn OSMain(dom_event_chan: pipes::SharedChan<Event>, opts: Opts) -> OSMain {
None => mode = GlutMode None => mode = GlutMode
} }
mainloop(mode, po, dom_event_chan.take(), &opts); mainloop(mode, po.take(), dom_event_chan.take(), &opts);
}
} }
}))
} }
} }
@ -86,10 +95,10 @@ impl AzureDrawTargetImageData : layers::layers::ImageData {
} }
fn mainloop(mode: Mode, fn mainloop(mode: Mode,
po: oldcomm::Port<Msg>, po: Port<Msg>,
dom_event_chan: pipes::SharedChan<Event>, dom_event_chan: SharedChan<Event>,
opts: &Opts) { opts: &Opts) {
let key_handlers: @DVec<pipes::Chan<()>> = @DVec(); let key_handlers: @DVec<Chan<()>> = @DVec();
let window; let window;
match mode { match mode {
@ -101,7 +110,8 @@ fn mainloop(mode: Mode,
window = GlutWindow(move glut_window); window = GlutWindow(move glut_window);
} }
ShareMode => { ShareMode => {
let share_context: ShareGlContext = sharegl::base::ShareContext::new(Size2D(800, 600)); let size = Size2D(800, 600);
let share_context: ShareGlContext = sharegl::base::ShareContext::new(size);
io::println(fmt!("Sharing ID is %d", share_context.id())); io::println(fmt!("Sharing ID is %d", share_context.id()));
window = ShareWindow(move share_context); window = ShareWindow(move share_context);
} }
@ -114,20 +124,21 @@ fn mainloop(mode: Mode,
let root_layer = @layers::layers::ContainerLayer(); let root_layer = @layers::layers::ContainerLayer();
let original_layer_transform; let original_layer_transform;
{ {
let image_data = @layers::layers::BasicImageData::new( let image_data = @layers::layers::BasicImageData::new(Size2D(0u, 0u),
Size2D(0u, 0u), 0, layers::layers::RGB24Format, ~[]); 0,
layers::layers::RGB24Format,
~[]);
let image = @layers::layers::Image::new(image_data as @layers::layers::ImageData); let image = @layers::layers::Image::new(image_data as @layers::layers::ImageData);
let image_layer = @layers::layers::ImageLayer(image); let image_layer = @layers::layers::ImageLayer(image);
original_layer_transform = image_layer.common.transform; original_layer_transform = image_layer.common.transform;
image_layer.common.set_transform(original_layer_transform.scale(&800.0f32, &600.0f32, image_layer.common.set_transform(original_layer_transform.scale(800.0, 600.0, 1.0));
&1f32));
root_layer.add_child(layers::layers::ImageLayerKind(image_layer)); root_layer.add_child(layers::layers::ImageLayerKind(image_layer));
} }
let scene = @layers::scene::Scene(layers::layers::ContainerLayerKind(root_layer), let scene = @layers::scene::Scene(layers::layers::ContainerLayerKind(root_layer),
Size2D(800.0f32, 600.0f32), Size2D(800.0, 600.0),
identity(0.0f32)); identity());
let done = @mut false; let done = @mut false;
let resize_rate_limiter = @ResizeRateLimiter(move dom_event_chan); let resize_rate_limiter = @ResizeRateLimiter(move dom_event_chan);
@ -185,7 +196,7 @@ fn mainloop(mode: Mode,
} }
} }
Some(_) => { Some(_) => {
fail ~"found unexpected layer kind" fail!(~"found unexpected layer kind")
} }
}; };
@ -193,8 +204,8 @@ fn mainloop(mode: Mode,
let x = buffer.rect.origin.x as f32; let x = buffer.rect.origin.x as f32;
let y = buffer.rect.origin.y as f32; let y = buffer.rect.origin.y as f32;
image_layer.common.set_transform( image_layer.common.set_transform(
original_layer_transform.translate(&x, &y, &0.0f32) original_layer_transform.translate(x, y, 0.0)
.scale(&(width as f32), &(height as f32), &1.0f32)); .scale(width as f32, height as f32, 1.0));
} }
surfaces.front.layer_buffer_set.buffers = move buffers; surfaces.front.layer_buffer_set.buffers = move buffers;
} }
@ -264,7 +275,7 @@ fn mainloop(mode: Mode,
Implementation to allow the osmain channel to be used as a graphics Implementation to allow the osmain channel to be used as a graphics
compositor for the renderer compositor for the renderer
*/ */
impl OSMain : Compositor { impl Compositor for OSMain {
fn begin_drawing(next_dt: pipes::Chan<LayerBufferSet>) { fn begin_drawing(next_dt: pipes::Chan<LayerBufferSet>) {
self.chan.send(BeginDrawing(move next_dt)) self.chan.send(BeginDrawing(move next_dt))
} }
@ -337,16 +348,14 @@ fn Surface(backend: BackendType) -> Surface {
} }
/// A function for spawning into the platform's main thread /// A function for spawning into the platform's main thread
fn on_osmain<T: Owned>(f: fn~(po: oldcomm::Port<T>)) -> oldcomm::Chan<T> { fn on_osmain<T: Owned>(f: fn~(po: Port<T>)) -> Chan<T> {
let setup_po = oldcomm::Port(); let (setup_po, setup_ch) = pipes::stream();
let setup_ch = oldcomm::Chan(&setup_po);
do task::task().sched_mode(task::PlatformThread).spawn |move f| { do task::task().sched_mode(task::PlatformThread).spawn |move f| {
let po = oldcomm::Port(); let (po, ch) = pipes::stream();
let ch = oldcomm::Chan(&po); setup_ch.send(ch);
oldcomm::send(setup_ch, ch);
f(move po); f(move po);
} }
oldcomm::recv(setup_po) setup_po.recv()
} }
// #[cfg(target_os = "linux")] // #[cfg(target_os = "linux")]

View file

@ -7,6 +7,8 @@
#[license = "MPL"]; #[license = "MPL"];
#[crate_type = "lib"]; #[crate_type = "lib"];
#[legacy_records];
extern mod azure; extern mod azure;
extern mod cairo; extern mod cairo;
extern mod geom; extern mod geom;
@ -94,7 +96,6 @@ extern mod core_text;
use engine::{Engine, ExitMsg, LoadURLMsg}; // FIXME: "ExitMsg" is pollution. use engine::{Engine, ExitMsg, LoadURLMsg}; // FIXME: "ExitMsg" is pollution.
use platform::osmain::{AddKeyHandler, OSMain}; use platform::osmain::{AddKeyHandler, OSMain};
use core::oldcomm::*; // FIXME: Bad!
use core::option::swap_unwrap; use core::option::swap_unwrap;
use core::pipes::{Port, Chan}; use core::pipes::{Port, Chan};
@ -115,9 +116,9 @@ fn run(opts: &Opts) {
match &opts.render_mode { match &opts.render_mode {
&Screen => run_pipeline_screen(opts), &Screen => run_pipeline_screen(opts),
&Png(ref outfile) => { &Png(ref outfile) => {
assert opts.urls.is_not_empty(); assert !opts.urls.is_empty();
if opts.urls.len() > 1u { if opts.urls.len() > 1u {
fail ~"servo asks that you stick to a single URL in PNG output mode" fail!(~"servo asks that you stick to a single URL in PNG output mode")
} }
run_pipeline_png(opts, *outfile) run_pipeline_png(opts, *outfile)
} }
@ -137,9 +138,13 @@ fn run_pipeline_screen(opts: &Opts) {
// Create a servo instance // Create a servo instance
let resource_task = ResourceTask(); let resource_task = ResourceTask();
let image_cache_task = ImageCacheTask(copy resource_task); let image_cache_task = ImageCacheTask(resource_task.clone());
let engine_task = Engine(osmain, opts, move dom_event_port, move dom_event_chan, let engine_task = Engine(osmain.clone(),
move resource_task, move image_cache_task); opts,
dom_event_port,
dom_event_chan,
resource_task,
image_cache_task);
for opts.urls.each |filename| { for opts.urls.each |filename| {
let url = make_url(copy *filename, None); let url = make_url(copy *filename, None);
@ -163,7 +168,7 @@ fn run_pipeline_screen(opts: &Opts) {
} }
fn run_pipeline_png(_opts: &Opts, _outfile: &str) { fn run_pipeline_png(_opts: &Opts, _outfile: &str) {
fail ~"PNG compositor is broken"; fail!(~"PNG compositor is broken");
} }
#[cfg(broken)] #[cfg(broken)]
@ -190,7 +195,7 @@ fn run_pipeline_png(url: ~str, outfile: &str) {
match buffered_file_writer(&Path(outfile)) { match buffered_file_writer(&Path(outfile)) {
Ok(writer) => writer.write(pngdata_from_compositor.recv()), Ok(writer) => writer.write(pngdata_from_compositor.recv()),
Err(e) => fail e Err(e) => fail!(e)
} }
let (exit_chan, exit_response_from_engine) = pipes::stream(); let (exit_chan, exit_response_from_engine) = pipes::stream();

View file

@ -1,25 +1,23 @@
use core::pipes::{Chan, Port};
use core::pipes;
use core::task; use core::task;
use std::cell::Cell;
pub fn spawn_listener<A: Owned>( pub fn spawn_listener<A: Owned>(f: fn~(Port<A>)) -> Chan<A> {
f: fn~(oldcomm::Port<A>)) -> oldcomm::Chan<A> { let (setup_po, setup_ch) = pipes::stream();
let setup_po = oldcomm::Port(); do task::spawn {
let setup_ch = oldcomm::Chan(&setup_po); let (po, ch) = pipes::stream();
do task::spawn |move f| { setup_ch.send(ch);
let po = oldcomm::Port(); f(po);
let ch = oldcomm::Chan(&po);
oldcomm::send(setup_ch, ch);
f(move po);
} }
oldcomm::recv(setup_po) setup_po.recv()
} }
pub fn spawn_conversation<A: Owned, B: Owned> pub fn spawn_conversation<A: Owned, B: Owned>(f: fn~(Port<A>, Chan<B>)) -> (Port<B>, Chan<A>) {
(f: fn~(oldcomm::Port<A>, oldcomm::Chan<B>)) let (from_child, to_parent) = pipes::stream();
-> (oldcomm::Port<B>, oldcomm::Chan<A>) { let to_parent = Cell(to_parent);
let from_child = oldcomm::Port(); let to_child = do spawn_listener |from_parent| {
let to_parent = oldcomm::Chan(&from_child); f(from_parent, to_parent.take())
let to_child = do spawn_listener |move f, from_parent| {
f(from_parent, to_parent)
}; };
(from_child, to_child) (from_child, to_child)
} }

View file

@ -71,7 +71,7 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
ops.with_tree_fields(&child, |child_tf| { ops.with_tree_fields(&child, |child_tf| {
match child_tf.parent { match child_tf.parent {
Some(_) => { fail ~"Already has a parent"; } Some(_) => { fail!(~"Already has a parent"); }
None => { child_tf.parent = Some(parent); } None => { child_tf.parent = Some(parent); }
} }
@ -100,14 +100,14 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) { pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
do ops.with_tree_fields(&child) |child_tf| { do ops.with_tree_fields(&child) |child_tf| {
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.tree_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.tree_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;
}, },
@ -115,7 +115,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.tree_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;
}, },

@ -1 +1 @@
Subproject commit 791badb957c59d3ec8929c536b4b94a2296755fd Subproject commit 355fdfa0e715ef7cc11156071c6b4fbcf4ede057

@ -1 +1 @@
Subproject commit 076938b2f416466fd9f70e4c662afe71dc52a0b9 Subproject commit 58b0c03955660dc381b955abddf4d53509f9a064