mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Upgrade for language changes
This commit is contained in:
parent
a7bfc99356
commit
0458783bc7
73 changed files with 755 additions and 680 deletions
4
configure
vendored
4
configure
vendored
|
@ -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}"
|
||||||
|
|
2
src/rust
2
src/rust
|
@ -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
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub impl Sub<Au,Au> for Au {
|
||||||
pure fn sub(&self, other: &Au) -> Au { Au(**self - **other) }
|
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) }
|
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) }
|
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) }
|
pure fn modulo(&self, other: &Au) -> Au { Au(**self % **other) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub impl Neg<Au> for Au {
|
||||||
pure fn neg(&self) -> Au { Au(-**self) }
|
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 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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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!")
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = @~[
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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...
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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, © layout_root.d().position,
|
layout_root.build_display_list(&builder,
|
||||||
|
© 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| {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")]
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
2
src/skia
2
src/skia
|
@ -1 +1 @@
|
||||||
Subproject commit 076938b2f416466fd9f70e4c662afe71dc52a0b9
|
Subproject commit 58b0c03955660dc381b955abddf4d53509f9a064
|
Loading…
Add table
Add a link
Reference in a new issue