mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Rust upgrade.
This commit is contained in:
parent
772c670bea
commit
b7b9197b46
31 changed files with 530 additions and 469 deletions
2
src/rust
2
src/rust
|
@ -1 +1 @@
|
||||||
Subproject commit 0e29e21281512f71d33a87995002bd438c5b42f1
|
Subproject commit e447521c1ca2dbead5b485ddc43060b282840817
|
|
@ -1 +1 @@
|
||||||
Subproject commit 16b5d87d37b2ce377b919de20c6a45fdf9e052dc
|
Subproject commit a8bdb2f58bf415deb5a1bf1407f17bcd09f2d965
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0439b988200eadfcb581b6b488331a9d4c5caba0
|
Subproject commit a583fefac118e354ff5cd3acf575f8267fd07c39
|
|
@ -1 +1 @@
|
||||||
Subproject commit aff506ba29bd34e8980ad7c3286a7cdc4e8207ae
|
Subproject commit 7d67731550afbe7657508ec6e437e2cd18161336
|
|
@ -1 +1 @@
|
||||||
Subproject commit b33e9dbc11895d4e30ac4abde60e2d24a182930e
|
Subproject commit 25e58c3ba2a8aed701553b811dfab639824a6553
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7d1872b89050332e957504a66ee38d73773efaf1
|
Subproject commit 77d9e83b730f8202de56699d1dd6eaeb66fd5e29
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5b39316c0b9f37417a7a5863dcfb03b007bd3634
|
Subproject commit 5af98808471802fe193175adb246bea2eb809fa0
|
|
@ -1 +1 @@
|
||||||
Subproject commit 96e92609d0f250ae3222b9ba99f2e00acc5ec0fb
|
Subproject commit 5efa43df1177da86d0ef1e783650b82a0928634b
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8657c14771908eb8577dfbe0fff5e85e3f1990da
|
Subproject commit bc06cf6a1771c13755051b51c919dddf73b60a5f
|
|
@ -1 +1 @@
|
||||||
Subproject commit b51ce8cca8aa9db6b9a65612b3366cd78457173e
|
Subproject commit 1e89a5e143fc1349a945decb5e0c91ad62356e15
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6653d7ed1163f9007682eb65cd221f258d4d0d5b
|
Subproject commit 26ac8e118161430025d8074259ed05ccef1baf14
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7eb84c523889efc97b96eaf80c82208c07e74423
|
Subproject commit 352c9f8359d196e453c5e2fc8d45785b852668c9
|
|
@ -71,12 +71,14 @@ trait FontTableTagConversions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontTableTag : FontTableTagConversions {
|
impl FontTableTag : FontTableTagConversions {
|
||||||
pub pure fn tag_to_str() -> ~str unsafe {
|
pub pure fn tag_to_str() -> ~str {
|
||||||
let reversed = str::raw::from_buf_len(cast::transmute(&self), 4);
|
unsafe {
|
||||||
return str::from_chars([reversed.char_at(3),
|
let reversed = str::raw::from_buf_len(cast::transmute(&self), 4);
|
||||||
reversed.char_at(2),
|
return str::from_chars([reversed.char_at(3),
|
||||||
reversed.char_at(1),
|
reversed.char_at(2),
|
||||||
reversed.char_at(0)]);
|
reversed.char_at(1),
|
||||||
|
reversed.char_at(0)]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ use util::cache::MonoCache;
|
||||||
|
|
||||||
use azure::azure_hl::BackendType;
|
use azure::azure_hl::BackendType;
|
||||||
use core::dvec::DVec;
|
use core::dvec::DVec;
|
||||||
use core::send_map::linear::LinearMap;
|
use core::hashmap::linear::LinearMap;
|
||||||
use core::send_map::linear;
|
use core::hashmap::linear;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use quartz;
|
use quartz;
|
||||||
|
@ -122,7 +122,7 @@ pub impl FontContext {
|
||||||
// FIXME: Need a find_like() in LinearMap.
|
// FIXME: Need a find_like() in LinearMap.
|
||||||
let family = family.to_str();
|
let family = family.to_str();
|
||||||
debug!("(transform family) searching for `%s`", family);
|
debug!("(transform family) searching for `%s`", family);
|
||||||
match self.generic_fonts.find_ref(&family) {
|
match self.generic_fonts.find(&family) {
|
||||||
None => move family,
|
None => move family,
|
||||||
Some(move mapped_family) => copy *mapped_family
|
Some(move mapped_family) => copy *mapped_family
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle};
|
||||||
use native::FontHandle;
|
use native::FontHandle;
|
||||||
|
|
||||||
use dvec::DVec;
|
use dvec::DVec;
|
||||||
use core::send_map::{linear, SendMap};
|
use core::hashmap::linear;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use fontconfig;
|
use fontconfig;
|
||||||
|
@ -46,7 +46,7 @@ pub impl FontList {
|
||||||
let handle = result::unwrap(FontListHandle::new(fctx));
|
let handle = result::unwrap(FontListHandle::new(fctx));
|
||||||
let list = FontList {
|
let list = FontList {
|
||||||
handle: move handle,
|
handle: move handle,
|
||||||
family_map: linear::LinearMap(),
|
family_map: linear::LinearMap::new(),
|
||||||
};
|
};
|
||||||
list.refresh(fctx);
|
list.refresh(fctx);
|
||||||
return move list;
|
return move list;
|
||||||
|
@ -82,7 +82,7 @@ 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(&str::from_slice(family_name));
|
let family = self.family_map.find_copy(&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);
|
||||||
|
|
|
@ -22,7 +22,7 @@ use self::fontconfig::fontconfig::bindgen::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::dvec::DVec;
|
use core::dvec::DVec;
|
||||||
use core::send_map::{linear, SendMap};
|
use core::hashmap::linear;
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use ptr::Ptr;
|
use ptr::Ptr;
|
||||||
use native;
|
use native;
|
||||||
|
@ -37,7 +37,7 @@ pub impl FontconfigFontListHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_available_families() -> FontFamilyMap {
|
fn get_available_families() -> FontFamilyMap {
|
||||||
let mut family_map : FontFamilyMap = linear::LinearMap();
|
let mut family_map : FontFamilyMap = linear::LinearMap::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
let config = FcConfigGetCurrent();
|
let config = FcConfigGetCurrent();
|
||||||
let fontSet = FcConfigGetFonts(config, FcSetSystem);
|
let fontSet = FcConfigGetFonts(config, FcSetSystem);
|
||||||
|
@ -122,38 +122,40 @@ pub impl FontconfigFontListHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_from_identifier(name: ~str) -> Result<~str, ()> unsafe {
|
pub fn path_from_identifier(name: ~str) -> Result<~str, ()> {
|
||||||
let config = FcConfigGetCurrent();
|
unsafe {
|
||||||
let pattern = FcPatternCreate();
|
let config = FcConfigGetCurrent();
|
||||||
let res = do str::as_c_str("family") |FC_FAMILY| {
|
let pattern = FcPatternCreate();
|
||||||
do str::as_c_str(name) |family| {
|
let res = do str::as_c_str("family") |FC_FAMILY| {
|
||||||
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
|
do str::as_c_str(name) |family| {
|
||||||
|
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if res != 1 {
|
||||||
|
debug!("adding family to pattern failed");
|
||||||
|
return Err(());
|
||||||
}
|
}
|
||||||
};
|
|
||||||
if res != 1 {
|
|
||||||
debug!("adding family to pattern failed");
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
|
if FcConfigSubstitute(config, pattern, FcMatchPattern) != 1 {
|
||||||
debug!("substitution failed");
|
debug!("substitution failed");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
FcDefaultSubstitute(pattern);
|
FcDefaultSubstitute(pattern);
|
||||||
let result = FcResultNoMatch;
|
let result = FcResultNoMatch;
|
||||||
let result_pattern = FcFontMatch(config, pattern, &result);
|
let result_pattern = FcFontMatch(config, pattern, &result);
|
||||||
if result != FcResultMatch && result_pattern.is_null() {
|
if result != FcResultMatch && result_pattern.is_null() {
|
||||||
debug!("obtaining match to pattern failed");
|
debug!("obtaining match to pattern failed");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let file: *FcChar8 = ptr::null();
|
let file: *FcChar8 = ptr::null();
|
||||||
let res = do str::as_c_str("file") |FC_FILE| {
|
let res = do str::as_c_str("file") |FC_FILE| {
|
||||||
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
|
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
|
||||||
};
|
};
|
||||||
if res != FcResultMatch {
|
if res != FcResultMatch {
|
||||||
debug!("getting filename for font failed");
|
debug!("getting filename for font failed");
|
||||||
return Err(());
|
return Err(());
|
||||||
|
}
|
||||||
|
Ok(str::raw::from_buf(file as *u8))
|
||||||
}
|
}
|
||||||
Ok(str::raw::from_buf(file as *u8))
|
|
||||||
}
|
}
|
|
@ -301,8 +301,10 @@ pub impl FreeTypeFontHandle : FontHandleMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FreeTypeFontHandle {
|
pub impl FreeTypeFontHandle {
|
||||||
priv fn get_face_rec() -> &self/FT_FaceRec unsafe {
|
priv fn get_face_rec() -> &self/FT_FaceRec {
|
||||||
&(*self.face)
|
unsafe {
|
||||||
|
&(*self.face)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn font_units_to_au(value: float) -> Au {
|
priv fn font_units_to_au(value: float) -> Au {
|
||||||
|
|
|
@ -50,7 +50,7 @@ pub impl FreeTypeFontContextHandle : FontContextHandleMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_font_from_identifier(name: ~str, style: UsedFontStyle)
|
fn create_font_from_identifier(name: ~str, style: UsedFontStyle)
|
||||||
-> Result<FontHandle, ()> unsafe {
|
-> Result<FontHandle, ()> {
|
||||||
debug!("Creating font handle for %s", name);
|
debug!("Creating font handle for %s", name);
|
||||||
do path_from_identifier(name).chain |file_name| {
|
do path_from_identifier(name).chain |file_name| {
|
||||||
debug!("Opening font face %s", file_name);
|
debug!("Opening font face %s", file_name);
|
||||||
|
|
|
@ -3,7 +3,7 @@ use stb_image = stb_image::image;
|
||||||
// FIXME: Images must not be copied every frame. Instead we should atomically
|
// FIXME: Images must not be copied every frame. Instead we should atomically
|
||||||
// reference count them.
|
// reference count them.
|
||||||
|
|
||||||
pub type Image = stb_image::Image;
|
pub type Image = stb_image::Image<u8>;
|
||||||
|
|
||||||
pub fn Image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image {
|
pub fn Image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image {
|
||||||
stb_image::new_image(width, height, depth, move data)
|
stb_image::new_image(width, height, depth, move data)
|
||||||
|
@ -20,24 +20,27 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
||||||
// Can't remember why we do this. Maybe it's what cairo wants
|
// Can't remember why we do this. Maybe it's what cairo wants
|
||||||
const FORCE_DEPTH: uint = 4;
|
const FORCE_DEPTH: uint = 4;
|
||||||
|
|
||||||
do stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH).map |image| {
|
match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) {
|
||||||
|
stb_image::ImageU8(image) => {
|
||||||
|
assert image.depth == 4;
|
||||||
|
// Do color space conversion :(
|
||||||
|
let data = do vec::from_fn(image.width * image.height * 4) |i| {
|
||||||
|
let color = i % 4;
|
||||||
|
let pixel = i / 4;
|
||||||
|
match color {
|
||||||
|
0 => image.data[pixel * 4 + 2],
|
||||||
|
1 => image.data[pixel * 4 + 1],
|
||||||
|
2 => image.data[pixel * 4 + 0],
|
||||||
|
3 => 0xffu8,
|
||||||
|
_ => fail
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
assert image.depth == 4;
|
assert image.data.len() == data.len();
|
||||||
// Do color space conversion :(
|
|
||||||
let data = do vec::from_fn(image.width * image.height * 4) |i| {
|
|
||||||
let color = i % 4;
|
|
||||||
let pixel = i / 4;
|
|
||||||
match color {
|
|
||||||
0 => image.data[pixel * 4 + 2],
|
|
||||||
1 => image.data[pixel * 4 + 1],
|
|
||||||
2 => image.data[pixel * 4 + 0],
|
|
||||||
3 => 0xffu8,
|
|
||||||
_ => fail
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert image.data.len() == data.len();
|
Some(Image(image.width, image.height, image.depth, move data))
|
||||||
|
}
|
||||||
Image(image.width, image.height, image.depth, move data)
|
stb_image::ImageF32(_image) => fail ~"HDR images not implemented",
|
||||||
|
stb_image::Error => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,9 +416,9 @@ impl DetailedGlyphStore {
|
||||||
// Thar be dragons here. You have been warned. (Tips accepted.)
|
// Thar be dragons here. You have been warned. (Tips accepted.)
|
||||||
let mut unsorted_records : ~[DetailedGlyphRecord] = ~[];
|
let mut unsorted_records : ~[DetailedGlyphRecord] = ~[];
|
||||||
core::util::swap(&mut self.detail_lookup, &mut unsorted_records);
|
core::util::swap(&mut self.detail_lookup, &mut unsorted_records);
|
||||||
let mut_records : ~[mut DetailedGlyphRecord] = vec::to_mut(move unsorted_records);
|
let mut_records : ~[mut DetailedGlyphRecord] = vec::cast_to_mut(move unsorted_records);
|
||||||
sort::quick_sort3(mut_records);
|
sort::quick_sort3(mut_records);
|
||||||
let mut sorted_records = vec::from_mut(move mut_records);
|
let mut sorted_records = vec::cast_from_mut(move mut_records);
|
||||||
core::util::swap(&mut self.detail_lookup, &mut sorted_records);
|
core::util::swap(&mut self.detail_lookup, &mut sorted_records);
|
||||||
|
|
||||||
self.lookup_is_sorted = true;
|
self.lookup_is_sorted = true;
|
||||||
|
|
|
@ -77,35 +77,39 @@ pub struct ShapedGlyphEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl ShapedGlyphData {
|
pub impl ShapedGlyphData {
|
||||||
static pure fn new(buffer: *hb_buffer_t) -> ShapedGlyphData unsafe {
|
static pure fn new(buffer: *hb_buffer_t) -> ShapedGlyphData {
|
||||||
let glyph_count = 0 as c_uint;
|
unsafe {
|
||||||
let glyph_infos = hb_buffer_get_glyph_infos(buffer, ptr::to_unsafe_ptr(&glyph_count));
|
let glyph_count = 0 as c_uint;
|
||||||
let glyph_count = glyph_count as uint;
|
let glyph_infos = hb_buffer_get_glyph_infos(buffer, ptr::to_unsafe_ptr(&glyph_count));
|
||||||
assert glyph_infos.is_not_null();
|
let glyph_count = glyph_count as uint;
|
||||||
let pos_count = 0 as c_uint;
|
assert glyph_infos.is_not_null();
|
||||||
let pos_infos = hb_buffer_get_glyph_positions(buffer, ptr::to_unsafe_ptr(&pos_count));
|
let pos_count = 0 as c_uint;
|
||||||
assert pos_infos.is_not_null();
|
let pos_infos = hb_buffer_get_glyph_positions(buffer, ptr::to_unsafe_ptr(&pos_count));
|
||||||
assert glyph_count == pos_count as uint;
|
assert pos_infos.is_not_null();
|
||||||
|
assert glyph_count == pos_count as uint;
|
||||||
|
|
||||||
ShapedGlyphData {
|
ShapedGlyphData {
|
||||||
count: glyph_count,
|
count: glyph_count,
|
||||||
glyph_infos: glyph_infos,
|
glyph_infos: glyph_infos,
|
||||||
pos_infos: pos_infos,
|
pos_infos: pos_infos,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
priv pure fn byte_offset_of_glyph(&const self, i: uint) -> uint unsafe {
|
priv pure fn byte_offset_of_glyph(&const self, i: uint) -> uint {
|
||||||
assert i < self.count;
|
assert i < self.count;
|
||||||
|
|
||||||
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
||||||
return (*glyph_info_i).cluster as uint;
|
unsafe {
|
||||||
|
(*glyph_info_i).cluster as uint
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pure fn len() -> uint { self.count }
|
pure fn len() -> uint { self.count }
|
||||||
|
|
||||||
// Returns shaped glyph data for one glyph, and updates the y-position of the pen.
|
// Returns shaped glyph data for one glyph, and updates the y-position of the pen.
|
||||||
fn get_entry_for_glyph(i: uint, y_pos: &mut Au) -> ShapedGlyphEntry unsafe {
|
fn get_entry_for_glyph(i: uint, y_pos: &mut Au) -> ShapedGlyphEntry {
|
||||||
assert i < self.count;
|
assert i < self.count;
|
||||||
|
|
||||||
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
||||||
|
@ -126,11 +130,13 @@ pub impl ShapedGlyphData {
|
||||||
Some(Point2D(x_offset, y_pos - y_offset))
|
Some(Point2D(x_offset, y_pos - y_offset))
|
||||||
};
|
};
|
||||||
|
|
||||||
ShapedGlyphEntry {
|
unsafe {
|
||||||
cluster: (*glyph_info_i).cluster as uint,
|
ShapedGlyphEntry {
|
||||||
codepoint: (*glyph_info_i).codepoint as GlyphIndex,
|
cluster: (*glyph_info_i).cluster as uint,
|
||||||
advance: x_advance,
|
codepoint: (*glyph_info_i).codepoint as GlyphIndex,
|
||||||
offset: move offset,
|
advance: x_advance,
|
||||||
|
offset: move offset,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,47 +449,53 @@ extern fn glyph_func(_font: *hb_font_t,
|
||||||
unicode: hb_codepoint_t,
|
unicode: hb_codepoint_t,
|
||||||
_variant_selector: hb_codepoint_t,
|
_variant_selector: hb_codepoint_t,
|
||||||
glyph: *mut hb_codepoint_t,
|
glyph: *mut hb_codepoint_t,
|
||||||
_user_data: *c_void) -> hb_bool_t unsafe {
|
_user_data: *c_void) -> hb_bool_t {
|
||||||
let font: *Font = font_data as *Font;
|
let font: *Font = font_data as *Font;
|
||||||
assert font.is_not_null();
|
assert font.is_not_null();
|
||||||
return match (*font).glyph_index(unicode as char) {
|
unsafe {
|
||||||
Some(g) => { *glyph = g as hb_codepoint_t; true },
|
return match (*font).glyph_index(unicode as char) {
|
||||||
None => false
|
Some(g) => { *glyph = g as hb_codepoint_t; true },
|
||||||
} as hb_bool_t;
|
None => false
|
||||||
|
} as hb_bool_t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn glyph_h_advance_func(_font: *hb_font_t,
|
extern fn glyph_h_advance_func(_font: *hb_font_t,
|
||||||
font_data: *c_void,
|
font_data: *c_void,
|
||||||
glyph: hb_codepoint_t,
|
glyph: hb_codepoint_t,
|
||||||
_user_data: *c_void) -> hb_position_t unsafe {
|
_user_data: *c_void) -> hb_position_t {
|
||||||
let font: *Font = font_data as *Font;
|
let font: *Font = font_data as *Font;
|
||||||
assert font.is_not_null();
|
assert font.is_not_null();
|
||||||
|
|
||||||
let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
|
unsafe {
|
||||||
HarfbuzzShaper::float_to_fixed(advance)
|
let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
|
||||||
|
HarfbuzzShaper::float_to_fixed(advance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback to get a font table out of a font.
|
// Callback to get a font table out of a font.
|
||||||
extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t unsafe {
|
extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t {
|
||||||
let font: *Font = user_data as *Font;
|
unsafe {
|
||||||
assert font.is_not_null();
|
let font: *Font = user_data as *Font;
|
||||||
|
assert font.is_not_null();
|
||||||
|
|
||||||
// TODO(Issue #197): reuse font table data, which will change the unsound trickery here.
|
// TODO(Issue #197): reuse font table data, which will change the unsound trickery here.
|
||||||
match (*font).get_table_for_tag(tag as FontTableTag) {
|
match (*font).get_table_for_tag(tag as FontTableTag) {
|
||||||
None => return ptr::null(),
|
None => return ptr::null(),
|
||||||
Some(ref font_table) => {
|
Some(ref font_table) => {
|
||||||
let skinny_font_table = ~font_table;
|
let skinny_font_table = ~font_table;
|
||||||
let skinny_font_table_ptr = ptr::to_unsafe_ptr(skinny_font_table);
|
let skinny_font_table_ptr = ptr::to_unsafe_ptr(skinny_font_table);
|
||||||
let mut blob: *hb_blob_t = ptr::null();
|
let mut blob: *hb_blob_t = ptr::null();
|
||||||
(*skinny_font_table_ptr).with_buffer(|buf: *u8, len: uint| {
|
(*skinny_font_table_ptr).with_buffer(|buf: *u8, len: uint| {
|
||||||
blob = hb_blob_create(buf as *c_char,
|
blob = hb_blob_create(buf as *c_char,
|
||||||
len as c_uint,
|
len as c_uint,
|
||||||
HB_MEMORY_MODE_READONLY,
|
HB_MEMORY_MODE_READONLY,
|
||||||
cast::transmute(skinny_font_table_ptr), // private context for below.
|
cast::transmute(skinny_font_table_ptr), // private context for below.
|
||||||
destroy_blob_func); // HarfBuzz calls this when blob not needed.
|
destroy_blob_func); // HarfBuzz calls this when blob not needed.
|
||||||
});
|
});
|
||||||
assert blob.is_not_null();
|
assert blob.is_not_null();
|
||||||
return blob;
|
return blob;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,7 +504,7 @@ extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_vo
|
||||||
// In particular, we'll need to cast to a boxed, rather than owned, FontTable.
|
// In particular, we'll need to cast to a boxed, rather than owned, FontTable.
|
||||||
|
|
||||||
// even better, should cache the harfbuzz blobs directly instead of recreating a lot.
|
// even better, should cache the harfbuzz blobs directly instead of recreating a lot.
|
||||||
extern fn destroy_blob_func(user_data: *c_void) unsafe {
|
extern fn destroy_blob_func(user_data: *c_void) {
|
||||||
// this will cause drop to run.
|
// this will cause drop to run.
|
||||||
let _wrapper : &~FontTable = cast::transmute(user_data);
|
let _wrapper : &~FontTable = unsafe { cast::transmute(user_data) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,8 +153,10 @@ pub fn Content(layout_task: LayoutTask,
|
||||||
content
|
content
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_from_context(cx: *JSContext) -> *Content unsafe {
|
pub fn task_from_context(cx: *JSContext) -> *Content {
|
||||||
cast::reinterpret_cast(&JS_GetContextPrivate(cx))
|
unsafe {
|
||||||
|
cast::reinterpret_cast(&JS_GetContextPrivate(cx))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
|
|
|
@ -63,17 +63,19 @@ enum Element = int;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
||||||
-> JSBool unsafe {
|
-> JSBool {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
unsafe {
|
||||||
if obj.is_null() {
|
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
||||||
return 0;
|
if obj.is_null() {
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
let box = unwrap(obj);
|
let box = unwrap(obj);
|
||||||
let node = (*box).payload.root;
|
let node = (*box).payload.root;
|
||||||
let scope = (*box).payload.scope;
|
let scope = (*box).payload.scope;
|
||||||
*vp = RUST_OBJECT_TO_JSVAL(node::create(cx, node, scope).ptr);
|
*vp = RUST_OBJECT_TO_JSVAL(node::create(cx, node, scope).ptr);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Document> {
|
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Document> {
|
||||||
|
|
|
@ -65,62 +65,66 @@ pub fn init(compartment: &bare_compartment) {
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
||||||
-> JSBool unsafe {
|
-> JSBool {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
unsafe {
|
||||||
if obj.is_null() {
|
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
||||||
return 0;
|
if obj.is_null() {
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
let bundle = unwrap(obj);
|
|
||||||
let node = (*bundle).payload.node;
|
|
||||||
let scope = (*bundle).payload.scope;
|
|
||||||
let width = scope.write(&node, |nd| {
|
|
||||||
match &nd.kind {
|
|
||||||
&~Element(ref ed) => {
|
|
||||||
match &ed.kind {
|
|
||||||
&~HTMLImageElement(*) => {
|
|
||||||
let content = task_from_context(cx);
|
|
||||||
match (*content).query_layout(layout_task::ContentBox(node)) {
|
|
||||||
Ok(rect) => rect.width,
|
|
||||||
Err(()) => 0,
|
|
||||||
}
|
|
||||||
// TODO: if nothing is being rendered(?), return zero dimensions
|
|
||||||
}
|
|
||||||
_ => fail ~"why is this not an image element?"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => fail ~"why is this not an element?"
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
*vp = RUST_INT_TO_JSVAL(
|
let bundle = unwrap(obj);
|
||||||
(width & (i32::max_value as int)) as libc::c_int);
|
let node = (*bundle).payload.node;
|
||||||
return 1;
|
let scope = (*bundle).payload.scope;
|
||||||
|
let width = scope.write(&node, |nd| {
|
||||||
|
match &nd.kind {
|
||||||
|
&~Element(ref ed) => {
|
||||||
|
match &ed.kind {
|
||||||
|
&~HTMLImageElement(*) => {
|
||||||
|
let content = task_from_context(cx);
|
||||||
|
match (*content).query_layout(layout_task::ContentBox(node)) {
|
||||||
|
Ok(rect) => rect.width,
|
||||||
|
Err(()) => 0,
|
||||||
|
}
|
||||||
|
// TODO: if nothing is being rendered(?), return zero dimensions
|
||||||
|
}
|
||||||
|
_ => fail ~"why is this not an image element?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => fail ~"why is this not an element?"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*vp = RUST_INT_TO_JSVAL(
|
||||||
|
(width & (i32::max_value as int)) as libc::c_int);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
||||||
-> JSBool unsafe {
|
-> JSBool {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
unsafe {
|
||||||
if obj.is_null() {
|
let obj = JS_THIS_OBJECT(cx, cast::reinterpret_cast(&vp));
|
||||||
return 0;
|
if obj.is_null() {
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
let bundle = unwrap(obj);
|
|
||||||
do (*bundle).payload.scope.write(&(*bundle).payload.node) |nd| {
|
|
||||||
match nd.kind {
|
|
||||||
~Element(ref ed) => {
|
|
||||||
match ed.kind {
|
|
||||||
~HTMLImageElement(*) => {
|
|
||||||
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))
|
|
||||||
},
|
|
||||||
_ => fail ~"why is this not an image element?"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => fail ~"why is this not an element?"
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
return 1;
|
let bundle = unwrap(obj);
|
||||||
|
do (*bundle).payload.scope.write(&(*bundle).payload.node) |nd| {
|
||||||
|
match nd.kind {
|
||||||
|
~Element(ref ed) => {
|
||||||
|
match ed.kind {
|
||||||
|
~HTMLImageElement(*) => {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
_ => fail ~"why is this not an image element?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => fail ~"why is this not an element?"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
|
@ -150,7 +154,7 @@ extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe {
|
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj {
|
||||||
let proto = scope.write(&node, |nd| {
|
let proto = scope.write(&node, |nd| {
|
||||||
match &nd.kind {
|
match &nd.kind {
|
||||||
&~Element(ref ed) => {
|
&~Element(ref ed) => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub fn init(compartment: &bare_compartment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe {
|
pub fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj {
|
||||||
do scope.write(&node) |nd| {
|
do scope.write(&node) |nd| {
|
||||||
match nd.kind {
|
match nd.kind {
|
||||||
~Element(*) => {
|
~Element(*) => {
|
||||||
|
|
|
@ -32,24 +32,28 @@ extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
1_i32
|
1_i32
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool unsafe {
|
extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
let argv = JS_ARGV(cx, vp);
|
unsafe {
|
||||||
assert (argc >= 2);
|
let argv = JS_ARGV(cx, vp);
|
||||||
|
assert (argc >= 2);
|
||||||
|
|
||||||
//TODO: don't crash when passed a non-integer value for the timeout
|
//TODO: don't crash when passed a non-integer value for the timeout
|
||||||
|
|
||||||
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.setTimeout(
|
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.setTimeout(
|
||||||
RUST_JSVAL_TO_INT(*ptr::offset(argv, 1)) as int,
|
RUST_JSVAL_TO_INT(*ptr::offset(argv, 1)) as int,
|
||||||
argc, argv);
|
argc, argv);
|
||||||
|
|
||||||
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn close(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool unsafe {
|
extern fn close(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.close();
|
unsafe {
|
||||||
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
(*unwrap(JS_THIS_OBJECT(cx, vp))).payload.close();
|
||||||
return 1;
|
JS_SET_RVAL(cx, vp, JSVAL_NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
|
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
|
||||||
|
|
|
@ -72,8 +72,10 @@ type ScopeData<T,A> = {
|
||||||
struct ScopeResource<T,A> {
|
struct ScopeResource<T,A> {
|
||||||
d : ScopeData<T,A>,
|
d : ScopeData<T,A>,
|
||||||
|
|
||||||
drop unsafe {
|
drop {
|
||||||
for self.d.free_list.each |h| { free_handle(*h); }
|
unsafe {
|
||||||
|
for self.d.free_list.each |h| { free_handle(*h); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,15 +95,15 @@ pub enum Handle<T,A> {
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
impl<T,A> Handle<T,A> {
|
impl<T,A> Handle<T,A> {
|
||||||
fn read_ptr() -> *T unsafe { (**self).read_ptr }
|
fn read_ptr() -> *T { unsafe { (**self).read_ptr } }
|
||||||
fn write_ptr() -> *mut T unsafe { (**self).write_ptr }
|
fn write_ptr() -> *mut T { unsafe { (**self).write_ptr } }
|
||||||
fn read_aux() -> *A unsafe { (**self).read_aux }
|
fn read_aux() -> *A { unsafe { (**self).read_aux } }
|
||||||
fn next_dirty() -> Handle<T,A> unsafe { (**self).next_dirty }
|
fn next_dirty() -> Handle<T,A> { unsafe { (**self).next_dirty } }
|
||||||
|
|
||||||
fn set_read_ptr(t: *T) unsafe { (**self).read_ptr = t; }
|
fn set_read_ptr(t: *T) { unsafe { (**self).read_ptr = t; } }
|
||||||
fn set_write_ptr(t: *mut T) unsafe { (**self).write_ptr = t; }
|
fn set_write_ptr(t: *mut T) { unsafe { (**self).write_ptr = t; } }
|
||||||
fn set_read_aux(t: *A) unsafe { (**self).read_aux = t; }
|
fn set_read_aux(t: *A) { unsafe { (**self).read_aux = t; } }
|
||||||
fn set_next_dirty(h: Handle<T,A>) unsafe { (**self).next_dirty = h; }
|
fn set_next_dirty(h: Handle<T,A>) { unsafe { (**self).next_dirty = h; } }
|
||||||
|
|
||||||
pure fn is_null() -> bool { (*self).is_null() }
|
pure fn is_null() -> bool { (*self).is_null() }
|
||||||
fn is_not_null() -> bool { (*self).is_not_null() }
|
fn is_not_null() -> bool { (*self).is_not_null() }
|
||||||
|
@ -109,27 +111,35 @@ impl<T,A> Handle<T,A> {
|
||||||
|
|
||||||
impl<T:Owned,A> Handle<T,A> {
|
impl<T:Owned,A> Handle<T,A> {
|
||||||
/// Access the reader's view of the handle's data
|
/// Access the reader's view of the handle's data
|
||||||
fn read<U>(f: fn(&T) -> U) -> U unsafe {
|
fn read<U>(f: fn(&T) -> U) -> U {
|
||||||
f(&*self.read_ptr())
|
unsafe {
|
||||||
|
f(&*self.read_ptr())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if auxiliary data is associated with this handle
|
/// True if auxiliary data is associated with this handle
|
||||||
fn has_aux() -> bool unsafe {
|
fn has_aux() -> bool {
|
||||||
self.read_aux().is_not_null()
|
unsafe {
|
||||||
|
self.read_aux().is_not_null()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the auxiliary data associated with this handle.
|
/** Set the auxiliary data associated with this handle.
|
||||||
|
|
||||||
**Warning:** the reader is responsible for keeping this data live!
|
**Warning:** the reader is responsible for keeping this data live!
|
||||||
*/
|
*/
|
||||||
fn set_aux(p: @A) unsafe {
|
fn set_aux(p: @A) {
|
||||||
(**self).read_aux = ptr::to_unsafe_ptr(&*p);
|
unsafe {
|
||||||
|
(**self).read_aux = ptr::to_unsafe_ptr(&*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the auxiliary data associated with this handle
|
/// Access the auxiliary data associated with this handle
|
||||||
fn aux<U>(f: fn(&A) -> U) -> U unsafe {
|
fn aux<U>(f: fn(&A) -> U) -> U {
|
||||||
assert self.has_aux();
|
unsafe {
|
||||||
f(&*self.read_aux())
|
assert self.has_aux();
|
||||||
|
f(&*self.read_aux())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,16 +150,18 @@ impl <T: Owned,A> Handle<T,A> : cmp::Eq {
|
||||||
|
|
||||||
// Private methods
|
// Private methods
|
||||||
impl<T: Copy Owned,A> Scope<T,A> {
|
impl<T: Copy Owned,A> Scope<T,A> {
|
||||||
fn clone(v: *T) -> *T unsafe {
|
fn clone(v: *T) -> *T {
|
||||||
let n: *mut T =
|
unsafe {
|
||||||
cast::reinterpret_cast(&libc::calloc(sys::size_of::<T>() as size_t, 1u as size_t));
|
let n: *mut T =
|
||||||
|
cast::reinterpret_cast(&libc::calloc(sys::size_of::<T>() as size_t, 1u as size_t));
|
||||||
|
|
||||||
// n.b.: this assignment will run the drop glue for <T,A>. *Hopefully* the fact that
|
// n.b.: this assignment will run the drop glue for <T,A>. *Hopefully* the fact that
|
||||||
// everything is initialized to NULL by calloc will make this ok. We may have to make the
|
// everything is initialized to NULL by calloc will make this ok. We may have to make the
|
||||||
// take glue be tolerant of this.
|
// take glue be tolerant of this.
|
||||||
*n = unsafe{*v};
|
*n = unsafe{*v};
|
||||||
|
|
||||||
return cast::reinterpret_cast(&n);
|
return cast::reinterpret_cast(&n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,18 +207,20 @@ impl<T:Copy Owned,A> Scope<T,A> {
|
||||||
self.d.layout_active = true;
|
self.d.layout_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reader_joined() unsafe {
|
fn reader_joined() {
|
||||||
assert self.d.layout_active;
|
assert self.d.layout_active;
|
||||||
|
|
||||||
if self.d.first_dirty.is_not_null() {
|
if (/*bad*/copy self.d.first_dirty).is_not_null() {
|
||||||
let mut handle = self.d.first_dirty;
|
let mut handle = self.d.first_dirty;
|
||||||
while (*handle).is_not_null() {
|
while (*handle).is_not_null() {
|
||||||
free(handle.read_ptr());
|
unsafe {
|
||||||
|
free(handle.read_ptr());
|
||||||
|
|
||||||
handle.set_read_ptr(cast::reinterpret_cast(&handle.write_ptr()));
|
handle.set_read_ptr(cast::reinterpret_cast(&handle.write_ptr()));
|
||||||
let next_handle = handle.next_dirty();
|
let next_handle = handle.next_dirty();
|
||||||
handle.set_next_dirty(null_handle());
|
handle.set_next_dirty(null_handle());
|
||||||
handle = next_handle;
|
handle = next_handle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.d.first_dirty = null_handle();
|
self.d.first_dirty = null_handle();
|
||||||
}
|
}
|
||||||
|
@ -215,40 +229,46 @@ impl<T:Copy Owned,A> Scope<T,A> {
|
||||||
self.d.layout_active = false;
|
self.d.layout_active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read<U>(h: &Handle<T,A>, f: fn(&T) -> U) -> U unsafe {
|
fn read<U>(h: &Handle<T,A>, f: fn(&T) -> U) -> U {
|
||||||
// Use the write_ptr, which may be more up to date than the read_ptr or may not
|
// Use the write_ptr, which may be more up to date than the read_ptr or may not
|
||||||
f(&*h.write_ptr())
|
unsafe {
|
||||||
|
f(&*h.write_ptr())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write<U>(h: &Handle<T,A>, f: fn(&T) -> U) -> U unsafe {
|
fn write<U>(h: &Handle<T,A>, f: fn(&T) -> U) -> U {
|
||||||
let const_read_ptr = ptr::const_offset(h.read_ptr(), 0);
|
unsafe {
|
||||||
let const_write_ptr = ptr::const_offset(h.write_ptr(), 0);
|
let const_read_ptr = ptr::const_offset(h.read_ptr(), 0);
|
||||||
if self.d.layout_active && const_read_ptr == const_write_ptr {
|
let const_write_ptr = ptr::const_offset(h.write_ptr(), 0);
|
||||||
debug!("marking handle %? as dirty", h);
|
if self.d.layout_active && const_read_ptr == const_write_ptr {
|
||||||
h.set_write_ptr(cast::reinterpret_cast(&self.clone(h.read_ptr())));
|
debug!("marking handle %? as dirty", h);
|
||||||
h.set_next_dirty(self.d.first_dirty);
|
h.set_write_ptr(cast::reinterpret_cast(&self.clone(h.read_ptr())));
|
||||||
self.d.first_dirty = *h;
|
h.set_next_dirty(self.d.first_dirty);
|
||||||
|
self.d.first_dirty = *h;
|
||||||
|
}
|
||||||
|
f(&*h.write_ptr())
|
||||||
}
|
}
|
||||||
f(&*h.write_ptr())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: This could avoid a deep copy by taking ownership of `v`
|
// FIXME: This could avoid a deep copy by taking ownership of `v`
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
fn handle(v: &T) -> Handle<T,A> unsafe {
|
fn handle(v: &T) -> Handle<T,A> {
|
||||||
debug!("vv: %?", *v);
|
unsafe {
|
||||||
let d: *HandleData<T,A> =
|
|
||||||
cast::reinterpret_cast(
|
|
||||||
&libc::malloc(sys::size_of::<HandleData<T,A>>() as size_t));
|
|
||||||
(*d).read_ptr = self.clone(ptr::to_unsafe_ptr(v));
|
|
||||||
(*d).write_ptr = cast::reinterpret_cast(&(*d).read_ptr);
|
|
||||||
(*d).read_aux = ptr::null();
|
|
||||||
(*d).next_dirty = null_handle();
|
|
||||||
let h = _Handle(d);
|
|
||||||
push(&mut self.d.free_list, h);
|
|
||||||
do self.read(&h) |v| {
|
|
||||||
debug!("vv: %?", *v);
|
debug!("vv: %?", *v);
|
||||||
|
let d: *HandleData<T,A> =
|
||||||
|
cast::reinterpret_cast(
|
||||||
|
&libc::malloc(sys::size_of::<HandleData<T,A>>() as size_t));
|
||||||
|
(*d).read_ptr = self.clone(ptr::to_unsafe_ptr(v));
|
||||||
|
(*d).write_ptr = cast::reinterpret_cast(&(*d).read_ptr);
|
||||||
|
(*d).read_aux = ptr::null();
|
||||||
|
(*d).next_dirty = null_handle();
|
||||||
|
let h = _Handle(d);
|
||||||
|
push(&mut self.d.free_list, h);
|
||||||
|
do self.read(&h) |v| {
|
||||||
|
debug!("vv: %?", *v);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
}
|
}
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,10 @@ impl Node : DebugMethods {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pure fn debug_str(&self) -> ~str unsafe {
|
pure fn debug_str(&self) -> ~str {
|
||||||
do self.read |n| { fmt!("%?", n.kind) }
|
unsafe {
|
||||||
|
do self.read |n| { fmt!("%?", n.kind) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,19 +28,21 @@ pub struct TimerData {
|
||||||
args: DVec<JSVal>,
|
args: DVec<JSVal>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn TimerData(argc: libc::c_uint, argv: *JSVal) -> TimerData unsafe {
|
pub fn TimerData(argc: libc::c_uint, argv: *JSVal) -> TimerData {
|
||||||
let data = TimerData {
|
unsafe {
|
||||||
funval : *argv,
|
let data = TimerData {
|
||||||
args : DVec(),
|
funval : *argv,
|
||||||
};
|
args : DVec(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut i = 2;
|
let mut i = 2;
|
||||||
while i < argc as uint {
|
while i < argc as uint {
|
||||||
data.args.push(*ptr::offset(argv, i));
|
data.args.push(*ptr::offset(argv, i));
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
move data
|
move data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: delayed_send shouldn't require Copy
|
// FIXME: delayed_send shouldn't require Copy
|
||||||
|
|
|
@ -164,7 +164,7 @@ fn build_element_kind(tag: &str) -> ~ElementKind {
|
||||||
pub fn parse_html(scope: NodeScope,
|
pub fn parse_html(scope: NodeScope,
|
||||||
url: Url,
|
url: Url,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask) -> HtmlParserResult unsafe {
|
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 (css_port, css_chan): (oldcomm::Port<Option<Stylesheet>>, oldcomm::Chan<CSSMessage>) =
|
||||||
do spawn_conversation |css_port: oldcomm::Port<CSSMessage>,
|
do spawn_conversation |css_port: oldcomm::Port<CSSMessage>,
|
||||||
|
@ -181,206 +181,210 @@ pub fn parse_html(scope: NodeScope,
|
||||||
|
|
||||||
let (scope, url) = (@copy scope, @move url);
|
let (scope, url) = (@copy scope, @move url);
|
||||||
|
|
||||||
// Build the root node.
|
unsafe {
|
||||||
let root = scope.new_node(Element(ElementData(~"html", ~HTMLDivElement)));
|
// Build the root node.
|
||||||
debug!("created new node");
|
let root = scope.new_node(Element(ElementData(~"html", ~HTMLDivElement)));
|
||||||
let parser = hubbub::Parser("UTF-8", false);
|
debug!("created new node");
|
||||||
debug!("created parser");
|
let parser = hubbub::Parser("UTF-8", false);
|
||||||
parser.set_document_node(cast::transmute(cow::unwrap(root)));
|
debug!("created parser");
|
||||||
parser.enable_scripting(true);
|
parser.set_document_node(cast::transmute(cow::unwrap(root)));
|
||||||
|
parser.enable_scripting(true);
|
||||||
|
|
||||||
// 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 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| {
|
||||||
match (&parent_node_contents.kind, &child_node_contents.kind) {
|
match (&parent_node_contents.kind, &child_node_contents.kind) {
|
||||||
(&~Element(ref element), &~Text(ref data)) => {
|
(&~Element(ref element), &~Text(ref data)) => {
|
||||||
match element.kind {
|
match element.kind {
|
||||||
~HTMLStyleElement => {
|
~HTMLStyleElement => {
|
||||||
debug!("found inline CSS stylesheet");
|
debug!("found inline CSS stylesheet");
|
||||||
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_chan.send(CSSTaskNewFile(move provenance));
|
||||||
}
|
|
||||||
_ => {} // Nothing to do.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {} // Nothing to do.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
parser.set_tree_handler(@hubbub::TreeHandler {
|
|
||||||
create_comment: |data: ~str| {
|
|
||||||
debug!("create comment");
|
|
||||||
let new_node = scope.new_node(Comment(move data));
|
|
||||||
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
|
||||||
},
|
|
||||||
create_doctype: |doctype: ~hubbub::Doctype| {
|
|
||||||
debug!("create doctype");
|
|
||||||
// TODO: remove copying here by using struct pattern matching to
|
|
||||||
// move all ~strs at once (blocked on Rust #3845, #3846, #3847)
|
|
||||||
let public_id = match &doctype.public_id {
|
|
||||||
&None => None,
|
|
||||||
&Some(ref id) => Some(copy *id)
|
|
||||||
};
|
|
||||||
let system_id = match &doctype.system_id {
|
|
||||||
&None => None,
|
|
||||||
&Some(ref id) => Some(copy *id)
|
|
||||||
};
|
|
||||||
let data = DoctypeData(copy doctype.name, move public_id, move system_id,
|
|
||||||
copy doctype.force_quirks);
|
|
||||||
let new_node = scope.new_node(Doctype(move data));
|
|
||||||
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
|
||||||
},
|
|
||||||
create_element: |tag: ~hubbub::Tag, move image_cache_task| {
|
|
||||||
debug!("create element");
|
|
||||||
// TODO: remove copying here by using struct pattern matching to
|
|
||||||
// move all ~strs at once (blocked on Rust #3845, #3846, #3847)
|
|
||||||
let elem_kind = build_element_kind(tag.name);
|
|
||||||
let elem = ElementData(copy tag.name, move elem_kind);
|
|
||||||
|
|
||||||
debug!("-- attach attrs");
|
|
||||||
for tag.attributes.each |attr| {
|
|
||||||
elem.attrs.push(~Attr(copy attr.name, copy attr.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn additional parsing, network loads, etc. from tag and attrs
|
|
||||||
match elem.kind {
|
|
||||||
//Handle CSS style sheets from <link> elements
|
|
||||||
~HTMLLinkElement => {
|
|
||||||
match (elem.get_attr(~"rel"), elem.get_attr(~"href")) {
|
|
||||||
(Some(move rel), Some(move href)) => {
|
|
||||||
if rel == ~"stylesheet" {
|
|
||||||
debug!("found CSS stylesheet: %s", href);
|
|
||||||
css_chan.send(CSSTaskNewFile(UrlProvenance(make_url(move href,
|
|
||||||
Some(copy *url)))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
~HTMLImageElement(ref d) => {
|
|
||||||
do elem.get_attr(~"src").iter |img_url_str| {
|
|
||||||
let img_url = make_url(copy *img_url_str, Some(copy *url));
|
|
||||||
d.image = Some(copy img_url);
|
|
||||||
// inform the image cache to load this, but don't store a handle.
|
|
||||||
// TODO (Issue #84): don't prefetch if we are within a <noscript> tag.
|
|
||||||
image_cache_task.send(image_cache_task::Prefetch(move img_url));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//TODO (Issue #86): handle inline styles ('style' attr)
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
let node = scope.new_node(Element(move elem));
|
|
||||||
unsafe { cast::transmute(cow::unwrap(node)) }
|
|
||||||
},
|
|
||||||
create_text: |data: ~str| {
|
|
||||||
debug!("create text");
|
|
||||||
let new_node = scope.new_node(Text(move data));
|
|
||||||
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
|
||||||
},
|
|
||||||
ref_node: |_node| {},
|
|
||||||
unref_node: |_node| {},
|
|
||||||
append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| unsafe {
|
|
||||||
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
|
|
||||||
unsafe {
|
|
||||||
let p: Node = cow::wrap(cast::transmute(parent));
|
|
||||||
let c: Node = cow::wrap(cast::transmute(child));
|
|
||||||
scope.add_child(p, c);
|
|
||||||
append_hook(p, c);
|
|
||||||
}
|
|
||||||
child
|
|
||||||
},
|
|
||||||
insert_before: |_parent, _child| {
|
|
||||||
debug!("insert before");
|
|
||||||
0u
|
|
||||||
},
|
|
||||||
remove_child: |_parent, _child| {
|
|
||||||
debug!("remove child");
|
|
||||||
0u
|
|
||||||
},
|
|
||||||
clone_node: |node, deep| {
|
|
||||||
debug!("clone node");
|
|
||||||
unsafe {
|
|
||||||
if deep { error!("-- deep clone unimplemented"); }
|
|
||||||
let n: Node = cow::wrap(cast::transmute(node));
|
|
||||||
let data = n.read(|read_data| copy *read_data.kind);
|
|
||||||
let new_node = scope.new_node(move data);
|
|
||||||
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
reparent_children: |_node, _new_parent| {
|
|
||||||
debug!("reparent children");
|
|
||||||
0u
|
|
||||||
},
|
|
||||||
get_parent: |_node, _element_only| {
|
|
||||||
debug!("get parent");
|
|
||||||
0u
|
|
||||||
},
|
|
||||||
has_children: |_node| {
|
|
||||||
debug!("has children");
|
|
||||||
false
|
|
||||||
},
|
|
||||||
form_associate: |_form, _node| {
|
|
||||||
debug!("form associate");
|
|
||||||
},
|
|
||||||
add_attributes: |_node, _attributes| {
|
|
||||||
debug!("add attributes");
|
|
||||||
},
|
|
||||||
set_quirks_mode: |_mode| {
|
|
||||||
debug!("set quirks mode");
|
|
||||||
},
|
|
||||||
encoding_change: |_encname| {
|
|
||||||
debug!("encoding change");
|
|
||||||
},
|
|
||||||
complete_script: |script| {
|
|
||||||
// A little function for holding this lint attr
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
fn complete_script(scope: &NodeScope, script: hubbub::NodeDataPtr, url: &Url, js_chan: &oldcomm::Chan<JSMessage>) unsafe {
|
|
||||||
do scope.read(&cow::wrap(cast::transmute(script))) |node_contents| {
|
|
||||||
match *node_contents.kind {
|
|
||||||
Element(ref element) if element.tag_name == ~"script" => {
|
|
||||||
match element.get_attr(~"src") {
|
|
||||||
Some(move src) => {
|
|
||||||
debug!("found script: %s", src);
|
|
||||||
let new_url = make_url(move src, Some(copy *url));
|
|
||||||
js_chan.send(JSTaskNewFile(move new_url));
|
|
||||||
}
|
}
|
||||||
None => {}
|
_ => {} // Nothing to do.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {} // Nothing to do.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
complete_script(scope, script, url, &js_chan);
|
};
|
||||||
debug!("complete script");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
debug!("set tree handler");
|
|
||||||
|
|
||||||
let input_port = Port();
|
parser.set_tree_handler(@hubbub::TreeHandler {
|
||||||
resource_task.send(Load(copy *url, input_port.chan()));
|
create_comment: |data: ~str| {
|
||||||
debug!("loaded page");
|
debug!("create comment");
|
||||||
loop {
|
let new_node = scope.new_node(Comment(move data));
|
||||||
match input_port.recv() {
|
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
||||||
Payload(data) => {
|
},
|
||||||
debug!("received data");
|
create_doctype: |doctype: ~hubbub::Doctype| {
|
||||||
parser.parse_chunk(data);
|
debug!("create doctype");
|
||||||
|
// TODO: remove copying here by using struct pattern matching to
|
||||||
|
// move all ~strs at once (blocked on Rust #3845, #3846, #3847)
|
||||||
|
let public_id = match &doctype.public_id {
|
||||||
|
&None => None,
|
||||||
|
&Some(ref id) => Some(copy *id)
|
||||||
|
};
|
||||||
|
let system_id = match &doctype.system_id {
|
||||||
|
&None => None,
|
||||||
|
&Some(ref id) => Some(copy *id)
|
||||||
|
};
|
||||||
|
let data = DoctypeData(copy doctype.name, move public_id, move system_id,
|
||||||
|
copy doctype.force_quirks);
|
||||||
|
let new_node = scope.new_node(Doctype(move data));
|
||||||
|
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
||||||
|
},
|
||||||
|
create_element: |tag: ~hubbub::Tag, move image_cache_task| {
|
||||||
|
debug!("create element");
|
||||||
|
// TODO: remove copying here by using struct pattern matching to
|
||||||
|
// move all ~strs at once (blocked on Rust #3845, #3846, #3847)
|
||||||
|
let elem_kind = build_element_kind(tag.name);
|
||||||
|
let elem = ElementData(copy tag.name, move elem_kind);
|
||||||
|
|
||||||
|
debug!("-- attach attrs");
|
||||||
|
for tag.attributes.each |attr| {
|
||||||
|
elem.attrs.push(~Attr(copy attr.name, copy attr.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn additional parsing, network loads, etc. from tag and attrs
|
||||||
|
match elem.kind {
|
||||||
|
//Handle CSS style sheets from <link> elements
|
||||||
|
~HTMLLinkElement => {
|
||||||
|
match (elem.get_attr(~"rel"), elem.get_attr(~"href")) {
|
||||||
|
(Some(move rel), Some(move href)) => {
|
||||||
|
if rel == ~"stylesheet" {
|
||||||
|
debug!("found CSS stylesheet: %s", href);
|
||||||
|
css_chan.send(CSSTaskNewFile(UrlProvenance(make_url(move href,
|
||||||
|
Some(copy *url)))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
~HTMLImageElement(ref d) => {
|
||||||
|
do elem.get_attr(~"src").iter |img_url_str| {
|
||||||
|
let img_url = make_url(copy *img_url_str, Some(copy *url));
|
||||||
|
d.image = Some(copy img_url);
|
||||||
|
// inform the image cache to load this, but don't store a handle.
|
||||||
|
// TODO (Issue #84): don't prefetch if we are within a <noscript> tag.
|
||||||
|
image_cache_task.send(image_cache_task::Prefetch(move img_url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO (Issue #86): handle inline styles ('style' attr)
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
let node = scope.new_node(Element(move elem));
|
||||||
|
unsafe { cast::transmute(cow::unwrap(node)) }
|
||||||
|
},
|
||||||
|
create_text: |data: ~str| {
|
||||||
|
debug!("create text");
|
||||||
|
let new_node = scope.new_node(Text(move data));
|
||||||
|
unsafe { cast::transmute(cow::unwrap(new_node)) }
|
||||||
|
},
|
||||||
|
ref_node: |_node| {},
|
||||||
|
unref_node: |_node| {},
|
||||||
|
append_child: |parent: hubbub::NodeDataPtr, child: hubbub::NodeDataPtr| {
|
||||||
|
unsafe {
|
||||||
|
debug!("append child %x %x", cast::transmute(parent), cast::transmute(child));
|
||||||
|
let p: Node = cow::wrap(cast::transmute(parent));
|
||||||
|
let c: Node = cow::wrap(cast::transmute(child));
|
||||||
|
scope.add_child(p, c);
|
||||||
|
append_hook(p, c);
|
||||||
|
}
|
||||||
|
child
|
||||||
|
},
|
||||||
|
insert_before: |_parent, _child| {
|
||||||
|
debug!("insert before");
|
||||||
|
0u
|
||||||
|
},
|
||||||
|
remove_child: |_parent, _child| {
|
||||||
|
debug!("remove child");
|
||||||
|
0u
|
||||||
|
},
|
||||||
|
clone_node: |node, deep| {
|
||||||
|
debug!("clone node");
|
||||||
|
unsafe {
|
||||||
|
if deep { error!("-- deep clone unimplemented"); }
|
||||||
|
let n: Node = cow::wrap(cast::transmute(node));
|
||||||
|
let data = n.read(|read_data| copy *read_data.kind);
|
||||||
|
let new_node = scope.new_node(move data);
|
||||||
|
cast::transmute(cow::unwrap(new_node))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
reparent_children: |_node, _new_parent| {
|
||||||
|
debug!("reparent children");
|
||||||
|
0u
|
||||||
|
},
|
||||||
|
get_parent: |_node, _element_only| {
|
||||||
|
debug!("get parent");
|
||||||
|
0u
|
||||||
|
},
|
||||||
|
has_children: |_node| {
|
||||||
|
debug!("has children");
|
||||||
|
false
|
||||||
|
},
|
||||||
|
form_associate: |_form, _node| {
|
||||||
|
debug!("form associate");
|
||||||
|
},
|
||||||
|
add_attributes: |_node, _attributes| {
|
||||||
|
debug!("add attributes");
|
||||||
|
},
|
||||||
|
set_quirks_mode: |_mode| {
|
||||||
|
debug!("set quirks mode");
|
||||||
|
},
|
||||||
|
encoding_change: |_encname| {
|
||||||
|
debug!("encoding change");
|
||||||
|
},
|
||||||
|
complete_script: |script| {
|
||||||
|
// A little function for holding this lint attr
|
||||||
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
|
fn complete_script(scope: &NodeScope, script: hubbub::NodeDataPtr, url: &Url, js_chan: &oldcomm::Chan<JSMessage>) {
|
||||||
|
unsafe {
|
||||||
|
do scope.read(&cow::wrap(cast::transmute(script))) |node_contents| {
|
||||||
|
match *node_contents.kind {
|
||||||
|
Element(ref element) if element.tag_name == ~"script" => {
|
||||||
|
match element.get_attr(~"src") {
|
||||||
|
Some(move src) => {
|
||||||
|
debug!("found script: %s", src);
|
||||||
|
let new_url = make_url(move src, Some(copy *url));
|
||||||
|
js_chan.send(JSTaskNewFile(move new_url));
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
complete_script(scope, script, url, &js_chan);
|
||||||
|
debug!("complete script");
|
||||||
}
|
}
|
||||||
Done(*) => {
|
});
|
||||||
break;
|
debug!("set tree handler");
|
||||||
|
|
||||||
|
let input_port = Port();
|
||||||
|
resource_task.send(Load(copy *url, input_port.chan()));
|
||||||
|
debug!("loaded page");
|
||||||
|
loop {
|
||||||
|
match input_port.recv() {
|
||||||
|
Payload(data) => {
|
||||||
|
debug!("received data");
|
||||||
|
parser.parse_chunk(data);
|
||||||
|
}
|
||||||
|
Done(*) => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
css_chan.send(CSSTaskExit);
|
||||||
|
js_chan.send(JSTaskExit);
|
||||||
|
|
||||||
|
return HtmlParserResult { root: root, style_port: css_port, js_port: js_port };
|
||||||
}
|
}
|
||||||
|
|
||||||
css_chan.send(CSSTaskExit);
|
|
||||||
js_chan.send(JSTaskExit);
|
|
||||||
|
|
||||||
return HtmlParserResult { root: root, style_port: css_port, js_port: js_port };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,7 +323,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: @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>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue