mirror of
https://github.com/servo/servo.git
synced 2025-06-25 01:24:37 +01:00
auto merge of #546 : brson/servo/master, r=metajack
This commit is contained in:
commit
bc520e0143
109 changed files with 1182 additions and 988 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit 1b883365bc0813f5775c8207e414b7973e947a76
|
Subproject commit f348465283d6cd85b69bcdc1711d14985d154c39
|
|
@ -19,11 +19,11 @@ use geometry::Au;
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use text::SendableTextRun;
|
use text::SendableTextRun;
|
||||||
|
|
||||||
use core::cast::transmute_region;
|
use std::cast::transmute_region;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use servo_net::image::base::Image;
|
use servo_net::image::base::Image;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use std::arc::ARC;
|
use extra::arc::ARC;
|
||||||
|
|
||||||
/// A list of rendering operations to be performed.
|
/// A list of rendering operations to be performed.
|
||||||
pub struct DisplayList<E> {
|
pub struct DisplayList<E> {
|
||||||
|
|
|
@ -9,6 +9,11 @@ use platform::font_context::FontContextHandle;
|
||||||
use platform::font::{FontHandle, FontTable};
|
use platform::font::{FontHandle, FontTable};
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
use std::cast;
|
||||||
|
use std::result;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
use std::vec;
|
||||||
use text::glyph::{GlyphStore, GlyphIndex};
|
use text::glyph::{GlyphStore, GlyphIndex};
|
||||||
use text::shaping::ShaperMethods;
|
use text::shaping::ShaperMethods;
|
||||||
use text::{Shaper, TextRun};
|
use text::{Shaper, TextRun};
|
||||||
|
@ -94,7 +99,7 @@ pub enum CSSFontWeight {
|
||||||
FontWeight900,
|
FontWeight900,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl CSSFontWeight {
|
impl CSSFontWeight {
|
||||||
pub fn is_bold(self) -> bool {
|
pub fn is_bold(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
FontWeight900 | FontWeight800 | FontWeight700 | FontWeight600 => true,
|
FontWeight900 | FontWeight800 | FontWeight700 | FontWeight600 => true,
|
||||||
|
@ -140,8 +145,8 @@ pub struct FontDescriptor {
|
||||||
selector: FontSelector,
|
selector: FontSelector,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontDescriptor {
|
impl FontDescriptor {
|
||||||
fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor {
|
pub fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor {
|
||||||
FontDescriptor {
|
FontDescriptor {
|
||||||
style: style,
|
style: style,
|
||||||
selector: selector,
|
selector: selector,
|
||||||
|
@ -170,8 +175,8 @@ pub struct FontGroup {
|
||||||
fonts: ~[@mut Font],
|
fonts: ~[@mut Font],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontGroup {
|
impl FontGroup {
|
||||||
fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup {
|
pub fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup {
|
||||||
FontGroup {
|
FontGroup {
|
||||||
families: families,
|
families: families,
|
||||||
style: copy *style,
|
style: copy *style,
|
||||||
|
@ -179,11 +184,11 @@ pub impl FontGroup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.fonts = ~[];
|
self.fonts = ~[];
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_textrun(&self, text: ~str, underline: bool) -> TextRun {
|
pub fn create_textrun(&self, text: ~str, underline: bool) -> TextRun {
|
||||||
assert!(self.fonts.len() > 0);
|
assert!(self.fonts.len() > 0);
|
||||||
|
|
||||||
// TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable.
|
// TODO(Issue #177): Actually fall back through the FontGroup when a font is unsuitable.
|
||||||
|
@ -215,8 +220,8 @@ pub struct Font {
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Font {
|
impl Font {
|
||||||
fn new_from_buffer(ctx: &FontContext,
|
pub fn new_from_buffer(ctx: &FontContext,
|
||||||
buffer: ~[u8],
|
buffer: ~[u8],
|
||||||
style: &SpecifiedFontStyle,
|
style: &SpecifiedFontStyle,
|
||||||
backend: BackendType,
|
backend: BackendType,
|
||||||
|
@ -243,7 +248,7 @@ pub impl Font {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle,
|
pub fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle,
|
||||||
style: &SpecifiedFontStyle, backend: BackendType,
|
style: &SpecifiedFontStyle, backend: BackendType,
|
||||||
profiler_chan: ProfilerChan) -> @mut Font {
|
profiler_chan: ProfilerChan) -> @mut Font {
|
||||||
let metrics = handle.get_metrics();
|
let metrics = handle.get_metrics();
|
||||||
|
@ -259,7 +264,7 @@ pub impl Font {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle,
|
pub fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle,
|
||||||
style: &SpecifiedFontStyle, backend: BackendType,
|
style: &SpecifiedFontStyle, backend: BackendType,
|
||||||
profiler_chan: ProfilerChan) -> Result<@mut Font,()> {
|
profiler_chan: ProfilerChan) -> Result<@mut Font,()> {
|
||||||
|
|
||||||
|
@ -284,7 +289,7 @@ pub impl Font {
|
||||||
shaper
|
shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
|
pub fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
|
||||||
let result = self.handle.get_table_for_tag(tag);
|
let result = self.handle.get_table_for_tag(tag);
|
||||||
let status = if result.is_some() { "Found" } else { "Didn't find" };
|
let status = if result.is_some() { "Found" } else { "Didn't find" };
|
||||||
|
|
||||||
|
@ -295,7 +300,7 @@ pub impl Font {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.shaper = None;
|
self.shaper = None;
|
||||||
self.azure_font = None;
|
self.azure_font = None;
|
||||||
}
|
}
|
||||||
|
@ -332,19 +337,19 @@ pub impl Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub impl Font {
|
impl Font {
|
||||||
fn draw_text_into_context(&mut self,
|
pub fn draw_text_into_context(&mut self,
|
||||||
rctx: &RenderContext,
|
rctx: &RenderContext,
|
||||||
run: &TextRun,
|
run: &TextRun,
|
||||||
range: &Range,
|
range: &Range,
|
||||||
baseline_origin: Point2D<Au>,
|
baseline_origin: Point2D<Au>,
|
||||||
color: Color) {
|
color: Color) {
|
||||||
use core::libc::types::common::c99::{uint16_t, uint32_t};
|
use std::libc::types::common::c99::{uint16_t, uint32_t};
|
||||||
use azure::{struct__AzDrawOptions,
|
use azure::{struct__AzDrawOptions,
|
||||||
struct__AzGlyph,
|
struct__AzGlyph,
|
||||||
struct__AzGlyphBuffer,
|
struct__AzGlyphBuffer,
|
||||||
struct__AzPoint};
|
struct__AzPoint};
|
||||||
use azure::azure::bindgen::{AzDrawTargetFillGlyphs};
|
use azure::azure::{AzDrawTargetFillGlyphs};
|
||||||
|
|
||||||
let target = rctx.get_draw_target();
|
let target = rctx.get_draw_target();
|
||||||
let azfontref = self.get_azure_font();
|
let azfontref = self.get_azure_font();
|
||||||
|
@ -362,7 +367,7 @@ pub impl Font {
|
||||||
vec::reserve(&mut azglyphs, range.length());
|
vec::reserve(&mut azglyphs, range.length());
|
||||||
|
|
||||||
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
|
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
|
||||||
let glyph_advance = glyph.advance();
|
let glyph_advance = glyph.advance_();
|
||||||
let glyph_offset = glyph.offset().get_or_default(Au::zero_point());
|
let glyph_offset = glyph.offset().get_or_default(Au::zero_point());
|
||||||
|
|
||||||
let azglyph = struct__AzGlyph {
|
let azglyph = struct__AzGlyph {
|
||||||
|
@ -379,28 +384,28 @@ pub impl Font {
|
||||||
let azglyph_buf_len = azglyphs.len();
|
let azglyph_buf_len = azglyphs.len();
|
||||||
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 glyphbuf = unsafe {
|
let glyphbuf = struct__AzGlyphBuffer {
|
||||||
struct__AzGlyphBuffer {
|
mGlyphs: vec::raw::to_ptr(azglyphs),
|
||||||
mGlyphs: vec::raw::to_ptr(azglyphs),
|
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
|
unsafe {
|
||||||
AzDrawTargetFillGlyphs(target.azure_draw_target,
|
// TODO(Issue #64): this call needs to move into azure_hl.rs
|
||||||
azfontref,
|
AzDrawTargetFillGlyphs(target.azure_draw_target,
|
||||||
ptr::to_unsafe_ptr(&glyphbuf),
|
azfontref,
|
||||||
azure_pattern,
|
ptr::to_unsafe_ptr(&glyphbuf),
|
||||||
ptr::to_unsafe_ptr(&options),
|
azure_pattern,
|
||||||
ptr::null());
|
ptr::to_unsafe_ptr(&options),
|
||||||
|
ptr::null());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure_text(&self, run: &TextRun, range: &Range) -> RunMetrics {
|
pub fn measure_text(&self, run: &TextRun, range: &Range) -> RunMetrics {
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
|
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
|
||||||
advance += glyph.advance();
|
advance += glyph.advance_();
|
||||||
}
|
}
|
||||||
let bounds = Rect(Point2D(Au(0), -self.metrics.ascent),
|
let bounds = Rect(Point2D(Au(0), -self.metrics.ascent),
|
||||||
Size2D(advance, self.metrics.ascent + self.metrics.descent));
|
Size2D(advance, self.metrics.ascent + self.metrics.descent));
|
||||||
|
@ -417,22 +422,22 @@ pub impl Font {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shape_text(@mut self, text: &str, store: &mut GlyphStore) {
|
pub fn shape_text(@mut self, text: &str, store: &mut GlyphStore) {
|
||||||
// TODO(Issue #229): use a more efficient strategy for repetitive shaping.
|
// TODO(Issue #229): use a more efficient strategy for repetitive shaping.
|
||||||
// For example, Gecko uses a per-"word" hashtable of shaper results.
|
// For example, Gecko uses a per-"word" hashtable of shaper results.
|
||||||
let shaper = self.get_shaper();
|
let shaper = self.get_shaper();
|
||||||
shaper.shape_text(text, store);
|
shaper.shape_text(text, store);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_descriptor(&self) -> FontDescriptor {
|
pub fn get_descriptor(&self) -> FontDescriptor {
|
||||||
FontDescriptor::new(copy self.style, SelectorPlatformIdentifier(self.handle.face_identifier()))
|
FontDescriptor::new(copy self.style, SelectorPlatformIdentifier(self.handle.face_identifier()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
|
pub fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
|
||||||
self.handle.glyph_index(codepoint)
|
self.handle.glyph_index(codepoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glyph_h_advance(&self, glyph: GlyphIndex) -> FractionalPixel {
|
pub fn glyph_h_advance(&self, glyph: GlyphIndex) -> FractionalPixel {
|
||||||
match self.handle.glyph_h_advance(glyph) {
|
match self.handle.glyph_h_advance(glyph) {
|
||||||
Some(adv) => adv,
|
Some(adv) => adv,
|
||||||
None => /* FIXME: Need fallback strategy */ 10f as FractionalPixel
|
None => /* FIXME: Need fallback strategy */ 10f as FractionalPixel
|
||||||
|
|
|
@ -14,7 +14,9 @@ use platform::font::FontHandle;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
|
||||||
use azure::azure_hl::BackendType;
|
use azure::azure_hl::BackendType;
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
use std::str;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
// TODO(Rust #3934): creating lots of new dummy styles is a workaround
|
// TODO(Rust #3934): creating lots of new dummy styles is a workaround
|
||||||
// for not being able to store symbolic enums in top-level constants.
|
// for not being able to store symbolic enums in top-level constants.
|
||||||
|
@ -46,8 +48,8 @@ pub struct FontContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub impl<'self> FontContext {
|
impl<'self> FontContext {
|
||||||
fn new(backend: BackendType,
|
pub fn new(backend: BackendType,
|
||||||
needs_font_list: bool,
|
needs_font_list: bool,
|
||||||
profiler_chan: ProfilerChan)
|
profiler_chan: ProfilerChan)
|
||||||
-> FontContext {
|
-> FontContext {
|
||||||
|
@ -79,7 +81,7 @@ pub impl<'self> FontContext {
|
||||||
self.font_list.get_ref()
|
self.font_list.get_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) -> @FontGroup {
|
pub fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) -> @FontGroup {
|
||||||
match self.group_cache.find(style) {
|
match self.group_cache.find(style) {
|
||||||
Some(fg) => {
|
Some(fg) => {
|
||||||
debug!("font group cache hit");
|
debug!("font group cache hit");
|
||||||
|
@ -94,7 +96,7 @@ pub impl<'self> FontContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
|
pub fn get_font_by_descriptor(&mut self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
|
||||||
match self.instance_cache.find(desc) {
|
match self.instance_cache.find(desc) {
|
||||||
Some(f) => {
|
Some(f) => {
|
||||||
debug!("font cache hit");
|
debug!("font cache hit");
|
||||||
|
@ -129,8 +131,8 @@ pub impl<'self> FontContext {
|
||||||
debug!("(create font group) --- starting ---");
|
debug!("(create font group) --- starting ---");
|
||||||
|
|
||||||
// TODO(Issue #193): make iteration over 'font-family' more robust.
|
// TODO(Issue #193): make iteration over 'font-family' more robust.
|
||||||
for str::each_split_char(style.families, ',') |family| {
|
for style.families.split_iter(',').advance |family| {
|
||||||
let family_name = str::trim(family);
|
let family_name = family.trim();
|
||||||
let transformed_family_name = self.transform_family(family_name);
|
let transformed_family_name = self.transform_family(family_name);
|
||||||
debug!("(create font group) transformed family is `%s`", transformed_family_name);
|
debug!("(create font group) transformed family is `%s`", transformed_family_name);
|
||||||
|
|
||||||
|
@ -142,7 +144,7 @@ pub impl<'self> FontContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for result.each |font_entry| {
|
for result.iter().advance |font_entry| {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
let font_id =
|
let font_id =
|
||||||
|
@ -161,7 +163,7 @@ pub impl<'self> FontContext {
|
||||||
|
|
||||||
let last_resort = FontList::get_last_resort_font_families();
|
let last_resort = FontList::get_last_resort_font_families();
|
||||||
|
|
||||||
for last_resort.each |family| {
|
for last_resort.iter().advance |family| {
|
||||||
let result = match self.font_list {
|
let result = match self.font_list {
|
||||||
Some(ref fl) => {
|
Some(ref fl) => {
|
||||||
fl.find_font_in_family(*family, style)
|
fl.find_font_in_family(*family, style)
|
||||||
|
@ -169,7 +171,7 @@ pub impl<'self> FontContext {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for result.each |font_entry| {
|
for result.iter().advance |font_entry| {
|
||||||
let font_id =
|
let font_id =
|
||||||
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
||||||
let font_desc = FontDescriptor::new(copy *style, font_id);
|
let font_desc = FontDescriptor::new(copy *style, font_id);
|
||||||
|
|
|
@ -8,11 +8,10 @@ use platform::font::FontHandle;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
use platform::font_list::FontListHandle;
|
use platform::font_list::FontListHandle;
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
use servo_util::time::time;
|
|
||||||
use servo_util::time::profile;
|
use servo_util::time::profile;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
|
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
|
||||||
pub type FontFamilyMap = HashMap<~str, @mut FontFamily>;
|
pub type FontFamilyMap = HashMap<~str, @mut FontFamily>;
|
||||||
|
|
||||||
|
@ -29,8 +28,8 @@ pub struct FontList {
|
||||||
prof_chan: ProfilerChan,
|
prof_chan: ProfilerChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontList {
|
impl FontList {
|
||||||
fn new(fctx: &FontContextHandle,
|
pub fn new(fctx: &FontContextHandle,
|
||||||
prof_chan: ProfilerChan)
|
prof_chan: ProfilerChan)
|
||||||
-> FontList {
|
-> FontList {
|
||||||
let handle = FontListHandle::new(fctx);
|
let handle = FontListHandle::new(fctx);
|
||||||
|
@ -53,7 +52,7 @@ pub impl FontList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_font_in_family(&self,
|
pub fn find_font_in_family(&self,
|
||||||
family_name: &str,
|
family_name: &str,
|
||||||
style: &SpecifiedFontStyle) -> Option<@FontEntry> {
|
style: &SpecifiedFontStyle) -> Option<@FontEntry> {
|
||||||
let family = self.find_family(family_name);
|
let family = self.find_family(family_name);
|
||||||
|
@ -62,7 +61,7 @@ pub impl FontList {
|
||||||
|
|
||||||
// if such family exists, try to match style to a font
|
// if such family exists, try to match style to a font
|
||||||
let mut result: Option<@FontEntry> = None;
|
let mut result: Option<@FontEntry> = None;
|
||||||
for family.each |fam| {
|
for family.iter().advance |fam| {
|
||||||
result = fam.find_font_for_style(&self.handle, style);
|
result = fam.find_font_for_style(&self.handle, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@ use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
use core::num::{NumCast, One, Zero};
|
use std::num::{NumCast, One, Zero};
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct Au(i32);
|
pub struct Au(i32);
|
||||||
|
|
||||||
impl Add<Au,Au> for Au {
|
impl Add<Au,Au> for Au {
|
||||||
|
@ -34,14 +35,14 @@ impl Neg<Au> for Au {
|
||||||
fn neg(&self) -> Au { Au(-**self) }
|
fn neg(&self) -> Au { Au(-**self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cmp::Ord for Au {
|
impl Ord for Au {
|
||||||
fn lt(&self, other: &Au) -> bool { **self < **other }
|
fn lt(&self, other: &Au) -> bool { **self < **other }
|
||||||
fn le(&self, other: &Au) -> bool { **self <= **other }
|
fn le(&self, other: &Au) -> bool { **self <= **other }
|
||||||
fn ge(&self, other: &Au) -> bool { **self >= **other }
|
fn ge(&self, other: &Au) -> bool { **self >= **other }
|
||||||
fn gt(&self, other: &Au) -> bool { **self > **other }
|
fn gt(&self, other: &Au) -> bool { **self > **other }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl cmp::Eq for Au {
|
impl Eq for Au {
|
||||||
fn eq(&self, other: &Au) -> bool { **self == **other }
|
fn eq(&self, other: &Au) -> bool { **self == **other }
|
||||||
fn ne(&self, other: &Au) -> bool { **self != **other }
|
fn ne(&self, other: &Au) -> bool { **self != **other }
|
||||||
}
|
}
|
||||||
|
@ -80,11 +81,11 @@ impl NumCast for Au {
|
||||||
fn to_float(&self) -> float { (**self).to_float() }
|
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> {
|
pub fn box<T:Clone + 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Au {
|
impl Au {
|
||||||
pub fn scale_by(self, factor: float) -> Au {
|
pub fn scale_by(self, factor: float) -> Au {
|
||||||
Au(((*self as float) * factor) as i32)
|
Au(((*self as float) * factor) as i32)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ extern mod azure;
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod http_client;
|
extern mod http_client;
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod std;
|
extern mod extra;
|
||||||
extern mod servo_net (name = "net");
|
extern mod servo_net (name = "net");
|
||||||
extern mod servo_util (name = "util");
|
extern mod servo_util (name = "util");
|
||||||
extern mod servo_msg (name = "msg");
|
extern mod servo_msg (name = "msg");
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
|
use azure::azure_hl::{BackendType, CairoBackend, CoreGraphicsBackend};
|
||||||
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
|
use azure::azure_hl::{CoreGraphicsAcceleratedBackend, Direct2DBackend, SkiaBackend};
|
||||||
|
|
||||||
|
use std::f64;
|
||||||
|
use std::result;
|
||||||
|
use std::uint;
|
||||||
|
|
||||||
pub struct Opts {
|
pub struct Opts {
|
||||||
urls: ~[~str],
|
urls: ~[~str],
|
||||||
render_backend: BackendType,
|
render_backend: BackendType,
|
||||||
|
@ -22,17 +26,17 @@ pub struct Opts {
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
use std::getopts;
|
use extra::getopts;
|
||||||
|
|
||||||
let args = args.tail();
|
let args = args.tail();
|
||||||
|
|
||||||
let opts = ~[
|
let opts = ~[
|
||||||
getopts::optopt(~"o"), // output file
|
getopts::optopt("o"), // output file
|
||||||
getopts::optopt(~"r"), // rendering backend
|
getopts::optopt("r"), // rendering backend
|
||||||
getopts::optopt(~"s"), // size of tiles
|
getopts::optopt("s"), // size of tiles
|
||||||
getopts::optopt(~"t"), // threads to render with
|
getopts::optopt("t"), // threads to render with
|
||||||
getopts::optflagopt(~"p"), // profiler flag and output interval
|
getopts::optflagopt("p"), // profiler flag and output interval
|
||||||
getopts::optopt(~"z"), // zoom level
|
getopts::optopt("z"), // zoom level
|
||||||
];
|
];
|
||||||
|
|
||||||
let opt_match = match getopts::getopts(args, opts) {
|
let opt_match = match getopts::getopts(args, opts) {
|
||||||
|
@ -45,11 +49,11 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
copy opt_match.free
|
copy opt_match.free
|
||||||
};
|
};
|
||||||
|
|
||||||
if getopts::opt_present(&opt_match, ~"o") {
|
if getopts::opt_present(&opt_match, "o") {
|
||||||
fail!(~"servo cannot treat 'o' option now.")
|
fail!(~"servo cannot treat 'o' option now.")
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_backend = match getopts::opt_maybe_str(&opt_match, ~"r") {
|
let render_backend = match getopts::opt_maybe_str(&opt_match, "r") {
|
||||||
Some(backend_str) => {
|
Some(backend_str) => {
|
||||||
if backend_str == ~"direct2d" {
|
if backend_str == ~"direct2d" {
|
||||||
Direct2DBackend
|
Direct2DBackend
|
||||||
|
@ -68,24 +72,24 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
None => SkiaBackend
|
None => SkiaBackend
|
||||||
};
|
};
|
||||||
|
|
||||||
let tile_size: uint = match getopts::opt_maybe_str(&opt_match, ~"s") {
|
let tile_size: uint = match getopts::opt_maybe_str(&opt_match, "s") {
|
||||||
Some(tile_size_str) => uint::from_str(tile_size_str).get(),
|
Some(tile_size_str) => uint::from_str(tile_size_str).get(),
|
||||||
None => 512,
|
None => 512,
|
||||||
};
|
};
|
||||||
|
|
||||||
let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, ~"t") {
|
let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, "t") {
|
||||||
Some(n_render_threads_str) => uint::from_str(n_render_threads_str).get(),
|
Some(n_render_threads_str) => uint::from_str(n_render_threads_str).get(),
|
||||||
None => 1, // FIXME: Number of cores.
|
None => 1, // FIXME: Number of cores.
|
||||||
};
|
};
|
||||||
|
|
||||||
let profiler_period: Option<f64> =
|
let profiler_period: Option<f64> =
|
||||||
// if only flag is present, default to 5 second period
|
// if only flag is present, default to 5 second period
|
||||||
match getopts::opt_default(&opt_match, ~"p", ~"5") {
|
match getopts::opt_default(&opt_match, "p", "5") {
|
||||||
Some(period) => Some(f64::from_str(period).get()),
|
Some(period) => Some(f64::from_str(period).get()),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let zoom: uint = match getopts::opt_maybe_str(&opt_match, ~"z") {
|
let zoom: uint = match getopts::opt_maybe_str(&opt_match, "z") {
|
||||||
Some(zoom_str) => uint::from_str(zoom_str).get(),
|
Some(zoom_str) => uint::from_str(zoom_str).get(),
|
||||||
None => 1,
|
None => 1,
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,10 +14,10 @@ use platform::font_context::FontContextHandle;
|
||||||
use text::glyph::GlyphIndex;
|
use text::glyph::GlyphIndex;
|
||||||
use text::util::{float_to_fixed, fixed_to_float};
|
use text::util::{float_to_fixed, fixed_to_float};
|
||||||
|
|
||||||
use freetype::freetype::bindgen::{FT_Get_Char_Index, FT_Get_Postscript_Name};
|
use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name};
|
||||||
use freetype::freetype::bindgen::{FT_Load_Glyph, FT_Set_Char_Size};
|
use freetype::freetype::{FT_Load_Glyph, FT_Set_Char_Size};
|
||||||
use freetype::freetype::bindgen::{FT_New_Face, FT_Get_Sfnt_Table};
|
use freetype::freetype::{FT_New_Face, FT_Get_Sfnt_Table};
|
||||||
use freetype::freetype::bindgen::{FT_New_Memory_Face, FT_Done_Face};
|
use freetype::freetype::{FT_New_Memory_Face, FT_Done_Face};
|
||||||
use freetype::freetype::{FTErrorMethods, FT_F26Dot6, FT_Face, FT_FaceRec};
|
use freetype::freetype::{FTErrorMethods, FT_F26Dot6, FT_Face, FT_FaceRec};
|
||||||
use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong};
|
use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong};
|
||||||
use freetype::freetype::{FT_STYLE_FLAG_ITALIC, FT_STYLE_FLAG_BOLD};
|
use freetype::freetype::{FT_STYLE_FLAG_ITALIC, FT_STYLE_FLAG_BOLD};
|
||||||
|
@ -25,6 +25,11 @@ use freetype::freetype::{FT_SizeRec, FT_UInt, FT_Size_Metrics};
|
||||||
use freetype::freetype::{ft_sfnt_os2};
|
use freetype::freetype::{ft_sfnt_os2};
|
||||||
use freetype::tt_os2::TT_OS2;
|
use freetype::tt_os2::TT_OS2;
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
fn float_to_fixed_ft(f: float) -> i32 {
|
fn float_to_fixed_ft(f: float) -> i32 {
|
||||||
float_to_fixed(6, f)
|
float_to_fixed(6, f)
|
||||||
}
|
}
|
||||||
|
@ -60,8 +65,10 @@ pub struct FontHandle {
|
||||||
impl Drop for FontHandle {
|
impl Drop for FontHandle {
|
||||||
fn finalize(&self) {
|
fn finalize(&self) {
|
||||||
assert!(self.face.is_not_null());
|
assert!(self.face.is_not_null());
|
||||||
if !FT_Done_Face(self.face).succeeded() {
|
unsafe {
|
||||||
fail!(~"FT_Done_Face failed");
|
if !FT_Done_Face(self.face).succeeded() {
|
||||||
|
fail!(~"FT_Done_Face failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,19 +103,21 @@ impl FontHandleMethods for FontHandle {
|
||||||
fn create_face_from_buffer(lib: FT_Library,
|
fn create_face_from_buffer(lib: FT_Library,
|
||||||
cbuf: *u8, cbuflen: uint, pt_size: float)
|
cbuf: *u8, cbuflen: uint, pt_size: float)
|
||||||
-> Result<FT_Face, ()> {
|
-> Result<FT_Face, ()> {
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
unsafe {
|
||||||
let face_index = 0 as FT_Long;
|
let mut face: FT_Face = ptr::null();
|
||||||
let result = FT_New_Memory_Face(lib, cbuf, cbuflen as FT_Long,
|
let face_index = 0 as FT_Long;
|
||||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
let result = FT_New_Memory_Face(lib, cbuf, cbuflen as FT_Long,
|
||||||
|
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||||
if !result.succeeded() || face.is_null() {
|
|
||||||
return Err(());
|
if !result.succeeded() || face.is_null() {
|
||||||
}
|
return Err(());
|
||||||
if FontHandle::set_char_size(face, pt_size).is_ok() {
|
}
|
||||||
Ok(face)
|
if FontHandle::set_char_size(face, pt_size).is_ok() {
|
||||||
} else {
|
Ok(face)
|
||||||
Err(())
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,24 +142,26 @@ impl FontHandleMethods for FontHandle {
|
||||||
if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } {
|
if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } {
|
||||||
default_weight
|
default_weight
|
||||||
} else {
|
} else {
|
||||||
let os2 = FT_Get_Sfnt_Table(self.face, ft_sfnt_os2) as *TT_OS2;
|
unsafe {
|
||||||
let valid = os2.is_not_null() && unsafe { (*os2).version != 0xffff };
|
let os2 = FT_Get_Sfnt_Table(self.face, ft_sfnt_os2) as *TT_OS2;
|
||||||
if valid {
|
let valid = os2.is_not_null() && (*os2).version != 0xffff;
|
||||||
let weight = unsafe { (*os2).usWeightClass };
|
if valid {
|
||||||
match weight {
|
let weight =(*os2).usWeightClass;
|
||||||
1 | 100..199 => FontWeight100,
|
match weight {
|
||||||
2 | 200..299 => FontWeight200,
|
1 | 100..199 => FontWeight100,
|
||||||
3 | 300..399 => FontWeight300,
|
2 | 200..299 => FontWeight200,
|
||||||
4 | 400..499 => FontWeight400,
|
3 | 300..399 => FontWeight300,
|
||||||
5 | 500..599 => FontWeight500,
|
4 | 400..499 => FontWeight400,
|
||||||
6 | 600..699 => FontWeight600,
|
5 | 500..599 => FontWeight500,
|
||||||
7 | 700..799 => FontWeight700,
|
6 | 600..699 => FontWeight600,
|
||||||
8 | 800..899 => FontWeight800,
|
7 | 700..799 => FontWeight700,
|
||||||
9 | 900..999 => FontWeight900,
|
8 | 800..899 => FontWeight800,
|
||||||
_ => default_weight
|
9 | 900..999 => FontWeight900,
|
||||||
|
_ => default_weight
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
default_weight
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
default_weight
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,8 +173,8 @@ impl FontHandleMethods for FontHandle {
|
||||||
FontSourceMem(ref buf) => {
|
FontSourceMem(ref buf) => {
|
||||||
FontHandleMethods::new_from_buffer(fctx, buf.clone(), style)
|
FontHandleMethods::new_from_buffer(fctx, buf.clone(), style)
|
||||||
}
|
}
|
||||||
FontSourceFile(copy file) => {
|
FontSourceFile(ref file) => {
|
||||||
FontHandle::new_from_file(fctx, file, style)
|
FontHandle::new_from_file(fctx, copy *file, style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,21 +182,23 @@ impl FontHandleMethods for FontHandle {
|
||||||
pub fn glyph_index(&self,
|
pub fn glyph_index(&self,
|
||||||
codepoint: char) -> Option<GlyphIndex> {
|
codepoint: char) -> Option<GlyphIndex> {
|
||||||
assert!(self.face.is_not_null());
|
assert!(self.face.is_not_null());
|
||||||
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
|
unsafe {
|
||||||
return if idx != 0 as FT_UInt {
|
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
|
||||||
Some(idx as GlyphIndex)
|
return if idx != 0 as FT_UInt {
|
||||||
} else {
|
Some(idx as GlyphIndex)
|
||||||
debug!("Invalid codepoint: %?", codepoint);
|
} else {
|
||||||
None
|
debug!("Invalid codepoint: %?", codepoint);
|
||||||
};
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_h_advance(&self,
|
pub fn glyph_h_advance(&self,
|
||||||
glyph: GlyphIndex) -> Option<FractionalPixel> {
|
glyph: GlyphIndex) -> Option<FractionalPixel> {
|
||||||
assert!(self.face.is_not_null());
|
assert!(self.face.is_not_null());
|
||||||
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
|
unsafe {
|
||||||
if res.succeeded() {
|
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
|
||||||
unsafe {
|
if res.succeeded() {
|
||||||
let void_glyph = (*self.face).glyph;
|
let void_glyph = (*self.face).glyph;
|
||||||
let slot: FT_GlyphSlot = cast::transmute(void_glyph);
|
let slot: FT_GlyphSlot = cast::transmute(void_glyph);
|
||||||
assert!(slot.is_not_null());
|
assert!(slot.is_not_null());
|
||||||
|
@ -194,10 +207,10 @@ impl FontHandleMethods for FontHandle {
|
||||||
debug!("h_advance for %? is %?", glyph, advance);
|
debug!("h_advance for %? is %?", glyph, advance);
|
||||||
let advance = advance as i32;
|
let advance = advance as i32;
|
||||||
return Some(fixed_to_float_ft(advance) as FractionalPixel);
|
return Some(fixed_to_float_ft(advance) as FractionalPixel);
|
||||||
|
} else {
|
||||||
|
debug!("Unable to load glyph %?. reason: %?", glyph, res);
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
debug!("Unable to load glyph %?. reason: %?", glyph, res);
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,62 +242,68 @@ impl FontHandleMethods for FontHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<'self> FontHandle {
|
impl<'self> FontHandle {
|
||||||
priv fn set_char_size(face: FT_Face, pt_size: float) -> Result<(), ()>{
|
priv fn set_char_size(face: FT_Face, pt_size: float) -> Result<(), ()>{
|
||||||
let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
let char_width = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
||||||
let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
let char_height = float_to_fixed_ft(pt_size) as FT_F26Dot6;
|
||||||
let h_dpi = 72;
|
let h_dpi = 72;
|
||||||
let v_dpi = 72;
|
let v_dpi = 72;
|
||||||
|
|
||||||
let result = FT_Set_Char_Size(face, char_width, char_height, h_dpi, v_dpi);
|
unsafe {
|
||||||
if result.succeeded() { Ok(()) } else { Err(()) }
|
let result = FT_Set_Char_Size(face, char_width, char_height, h_dpi, v_dpi);
|
||||||
|
if result.succeeded() { Ok(()) } else { Err(()) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_file(fctx: &FontContextHandle, file: ~str,
|
pub fn new_from_file(fctx: &FontContextHandle, file: ~str,
|
||||||
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
style: &SpecifiedFontStyle) -> Result<FontHandle, ()> {
|
||||||
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
unsafe {
|
||||||
if ft_ctx.is_null() { return Err(()); }
|
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||||
|
if ft_ctx.is_null() { return Err(()); }
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
let face_index = 0 as FT_Long;
|
let face_index = 0 as FT_Long;
|
||||||
do str::as_c_str(file) |file_str| {
|
do str::as_c_str(file) |file_str| {
|
||||||
FT_New_Face(ft_ctx, file_str,
|
FT_New_Face(ft_ctx, file_str,
|
||||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||||
}
|
}
|
||||||
if face.is_null() {
|
if face.is_null() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
if FontHandle::set_char_size(face, style.pt_size).is_ok() {
|
if FontHandle::set_char_size(face, style.pt_size).is_ok() {
|
||||||
Ok(FontHandle {
|
Ok(FontHandle {
|
||||||
source: FontSourceFile(file),
|
source: FontSourceFile(file),
|
||||||
face: face,
|
face: face,
|
||||||
handle: *fctx
|
handle: *fctx
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
|
pub fn new_from_file_unstyled(fctx: &FontContextHandle, file: ~str)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
unsafe {
|
||||||
if ft_ctx.is_null() { return Err(()); }
|
let ft_ctx: FT_Library = fctx.ctx.ctx;
|
||||||
|
if ft_ctx.is_null() { return Err(()); }
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
let face_index = 0 as FT_Long;
|
let face_index = 0 as FT_Long;
|
||||||
do str::as_c_str(file) |file_str| {
|
do str::as_c_str(file) |file_str| {
|
||||||
FT_New_Face(ft_ctx, file_str,
|
FT_New_Face(ft_ctx, file_str,
|
||||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||||
}
|
}
|
||||||
if face.is_null() {
|
if face.is_null() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(FontHandle {
|
Ok(FontHandle {
|
||||||
source: FontSourceFile(file),
|
source: FontSourceFile(file),
|
||||||
face: face,
|
face: face,
|
||||||
handle: *fctx
|
handle: *fctx
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_face_rec(&'self self) -> &'self FT_FaceRec {
|
priv fn get_face_rec(&'self self) -> &'self FT_FaceRec {
|
||||||
|
|
|
@ -8,8 +8,9 @@ use font_context::FontContextHandleMethods;
|
||||||
use platform::font_list::path_from_identifier;
|
use platform::font_list::path_from_identifier;
|
||||||
|
|
||||||
use freetype::freetype::{FTErrorMethods, FT_Library};
|
use freetype::freetype::{FTErrorMethods, FT_Library};
|
||||||
use freetype::freetype::bindgen::{FT_Done_FreeType, FT_Init_FreeType};
|
use freetype::freetype::{FT_Done_FreeType, FT_Init_FreeType};
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
struct FreeTypeLibraryHandle {
|
struct FreeTypeLibraryHandle {
|
||||||
ctx: FT_Library,
|
ctx: FT_Library,
|
||||||
|
@ -18,7 +19,9 @@ struct FreeTypeLibraryHandle {
|
||||||
impl Drop for FreeTypeLibraryHandle {
|
impl Drop for FreeTypeLibraryHandle {
|
||||||
fn finalize(&self) {
|
fn finalize(&self) {
|
||||||
assert!(self.ctx.is_not_null());
|
assert!(self.ctx.is_not_null());
|
||||||
FT_Done_FreeType(self.ctx);
|
unsafe {
|
||||||
|
FT_Done_FreeType(self.ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,14 +29,16 @@ pub struct FontContextHandle {
|
||||||
ctx: @FreeTypeLibraryHandle,
|
ctx: @FreeTypeLibraryHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontContextHandle {
|
impl FontContextHandle {
|
||||||
pub fn new() -> FontContextHandle {
|
pub fn new() -> FontContextHandle {
|
||||||
let ctx: FT_Library = ptr::null();
|
unsafe {
|
||||||
let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
|
let ctx: FT_Library = ptr::null();
|
||||||
if !result.succeeded() { fail!(); }
|
let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
|
||||||
|
if !result.succeeded() { fail!(); }
|
||||||
|
|
||||||
FontContextHandle {
|
FontContextHandle {
|
||||||
ctx: @FreeTypeLibraryHandle { ctx: ctx },
|
ctx: @FreeTypeLibraryHandle { ctx: ctx },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use fontconfig::fontconfig::{
|
||||||
FcChar8, FcResultMatch, FcSetSystem, FcPattern,
|
FcChar8, FcResultMatch, FcSetSystem, FcPattern,
|
||||||
FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD
|
FcResultNoMatch, FcMatchPattern, FC_SLANT_ITALIC, FC_WEIGHT_BOLD
|
||||||
};
|
};
|
||||||
use fontconfig::fontconfig::bindgen::{
|
use fontconfig::fontconfig::{
|
||||||
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
|
FcConfigGetCurrent, FcConfigGetFonts, FcPatternGetString,
|
||||||
FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
|
FcPatternDestroy, FcFontSetDestroy, FcConfigSubstitute,
|
||||||
FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
|
FcDefaultSubstitute, FcPatternCreate, FcPatternAddString, FcPatternAddInteger,
|
||||||
|
@ -24,20 +24,23 @@ use font_list::{FontEntry, FontFamily, FontFamilyMap};
|
||||||
use platform::font::FontHandle;
|
use platform::font::FontHandle;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use core::libc::c_int;
|
use std::libc;
|
||||||
use core::ptr::Ptr;
|
use std::libc::c_int;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
use std::uint;
|
||||||
|
|
||||||
pub struct FontListHandle {
|
pub struct FontListHandle {
|
||||||
fctx: FontContextHandle,
|
fctx: FontContextHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontListHandle {
|
impl FontListHandle {
|
||||||
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
|
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
|
||||||
FontListHandle { fctx: fctx.clone() }
|
FontListHandle { fctx: fctx.clone() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_available_families(&self) -> FontFamilyMap {
|
pub fn get_available_families(&self) -> FontFamilyMap {
|
||||||
let mut family_map : FontFamilyMap = HashMap::new();
|
let mut family_map : FontFamilyMap = HashMap::new();
|
||||||
unsafe {
|
unsafe {
|
||||||
let config = FcConfigGetCurrent();
|
let config = FcConfigGetCurrent();
|
||||||
|
@ -60,12 +63,12 @@ pub impl FontListHandle {
|
||||||
return family_map;
|
return family_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_variations_for_family(&self, family: @mut FontFamily) {
|
pub fn load_variations_for_family(&self, family: @mut FontFamily) {
|
||||||
debug!("getting variations for %?", family);
|
debug!("getting variations for %?", family);
|
||||||
let config = FcConfigGetCurrent();
|
|
||||||
let font_set = FcConfigGetFonts(config, FcSetSystem);
|
|
||||||
let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let config = FcConfigGetCurrent();
|
||||||
|
let font_set = FcConfigGetFonts(config, FcSetSystem);
|
||||||
|
let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
|
||||||
let pattern = FcPatternCreate();
|
let pattern = FcPatternCreate();
|
||||||
assert!(pattern.is_not_null());
|
assert!(pattern.is_not_null());
|
||||||
do str::as_c_str("family") |FC_FAMILY| {
|
do str::as_c_str("family") |FC_FAMILY| {
|
||||||
|
@ -126,7 +129,7 @@ pub impl FontListHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_last_resort_font_families() -> ~[~str] {
|
pub fn get_last_resort_font_families() -> ~[~str] {
|
||||||
~[~"Arial"]
|
~[~"Arial"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +140,9 @@ struct AutoPattern {
|
||||||
|
|
||||||
impl Drop for AutoPattern {
|
impl Drop for AutoPattern {
|
||||||
fn finalize(&self) {
|
fn finalize(&self) {
|
||||||
FcPatternDestroy(self.pattern);
|
unsafe {
|
||||||
|
FcPatternDestroy(self.pattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,9 @@ use core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors};
|
||||||
use core_text::font_descriptor::{kCTFontDefaultOrientation};
|
use core_text::font_descriptor::{kCTFontDefaultOrientation};
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
pub struct FontTable {
|
pub struct FontTable {
|
||||||
data: CFData,
|
data: CFData,
|
||||||
}
|
}
|
||||||
|
@ -37,8 +40,8 @@ impl Drop for FontTable {
|
||||||
fn finalize(&self) {}
|
fn finalize(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontTable {
|
impl FontTable {
|
||||||
fn wrap(data: CFData) -> FontTable {
|
pub fn wrap(data: CFData) -> FontTable {
|
||||||
FontTable { data: data }
|
FontTable { data: data }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,15 +57,15 @@ pub struct FontHandle {
|
||||||
ctfont: CTFont,
|
ctfont: CTFont,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontHandle {
|
impl FontHandle {
|
||||||
fn new_from_CTFont(_: &FontContextHandle, ctfont: CTFont) -> Result<FontHandle, ()> {
|
pub fn new_from_CTFont(_: &FontContextHandle, ctfont: CTFont) -> Result<FontHandle, ()> {
|
||||||
Ok(FontHandle {
|
Ok(FontHandle {
|
||||||
mut cgfont: None,
|
cgfont: None,
|
||||||
ctfont: ctfont,
|
ctfont: ctfont,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_CGFont(&mut self) -> CGFont {
|
pub fn get_CGFont(&mut self) -> CGFont {
|
||||||
match self.cgfont {
|
match self.cgfont {
|
||||||
Some(ref font) => font.clone(),
|
Some(ref font) => font.clone(),
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -8,11 +8,13 @@ use platform::macos::font::FontHandle;
|
||||||
|
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
|
use std::result;
|
||||||
|
|
||||||
pub struct FontContextHandle {
|
pub struct FontContextHandle {
|
||||||
ctx: ()
|
ctx: ()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontContextHandle {
|
impl FontContextHandle {
|
||||||
// this is a placeholder until NSFontManager or whatever is bound in here.
|
// this is a placeholder until NSFontManager or whatever is bound in here.
|
||||||
pub fn new() -> FontContextHandle {
|
pub fn new() -> FontContextHandle {
|
||||||
FontContextHandle { ctx: () }
|
FontContextHandle { ctx: () }
|
||||||
|
|
|
@ -15,20 +15,21 @@ use core_text::font_collection::CTFontCollectionMethods;
|
||||||
use core_text::font_descriptor::CTFontDescriptorRef;
|
use core_text::font_descriptor::CTFontDescriptorRef;
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
pub struct FontListHandle {
|
pub struct FontListHandle {
|
||||||
fctx: FontContextHandle,
|
fctx: FontContextHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl FontListHandle {
|
impl FontListHandle {
|
||||||
fn new(fctx: &FontContextHandle) -> FontListHandle {
|
pub fn new(fctx: &FontContextHandle) -> FontListHandle {
|
||||||
FontListHandle {
|
FontListHandle {
|
||||||
fctx: fctx.clone()
|
fctx: fctx.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_available_families(&self) -> FontFamilyMap {
|
pub fn get_available_families(&self) -> FontFamilyMap {
|
||||||
let family_names: CFArray<CFStringRef> = core_text::font_collection::get_family_names();
|
let family_names: CFArray<CFStringRef> = core_text::font_collection::get_family_names();
|
||||||
let mut family_map: FontFamilyMap = HashMap::new();
|
let mut family_map: FontFamilyMap = HashMap::new();
|
||||||
for family_names.each |&strref: &CFStringRef| {
|
for family_names.each |&strref: &CFStringRef| {
|
||||||
|
@ -41,7 +42,7 @@ pub impl FontListHandle {
|
||||||
return family_map;
|
return family_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_variations_for_family(&self, family: @mut FontFamily) {
|
pub fn load_variations_for_family(&self, family: @mut FontFamily) {
|
||||||
debug!("Looking for faces of family: %s", family.family_name);
|
debug!("Looking for faces of family: %s", family.family_name);
|
||||||
|
|
||||||
let family_collection = core_text::font_collection::create_for_family(family.family_name);
|
let family_collection = core_text::font_collection::create_for_family(family.family_name);
|
||||||
|
@ -56,7 +57,7 @@ pub impl FontListHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_last_resort_font_families() -> ~[~str] {
|
pub fn get_last_resort_font_families() -> ~[~str] {
|
||||||
~[~"Arial Unicode MS",~"Arial"]
|
~[~"Arial Unicode MS",~"Arial"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,12 @@ use opts::Opts;
|
||||||
use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions};
|
use azure::azure_hl::{B8G8R8A8, Color, ColorPattern, DrawOptions};
|
||||||
use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, Linear, StrokeOptions};
|
use azure::azure_hl::{DrawSurfaceOptions, DrawTarget, Linear, StrokeOptions};
|
||||||
use azure::AzFloat;
|
use azure::AzFloat;
|
||||||
use core::libc::types::common::c99::uint16_t;
|
use std::libc::types::common::c99::uint16_t;
|
||||||
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 servo_net::image::base::Image;
|
use servo_net::image::base::Image;
|
||||||
use std::arc;
|
use extra::arc::ARC;
|
||||||
use std::arc::ARC;
|
|
||||||
|
|
||||||
pub struct RenderContext<'self> {
|
pub struct RenderContext<'self> {
|
||||||
canvas: &'self LayerBuffer,
|
canvas: &'self LayerBuffer,
|
||||||
|
@ -24,7 +23,7 @@ pub struct RenderContext<'self> {
|
||||||
opts: &'self Opts
|
opts: &'self Opts
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<'self> RenderContext<'self> {
|
impl<'self> RenderContext<'self> {
|
||||||
pub fn get_draw_target(&self) -> &'self DrawTarget {
|
pub fn get_draw_target(&self) -> &'self DrawTarget {
|
||||||
&self.canvas.draw_target
|
&self.canvas.draw_target
|
||||||
}
|
}
|
||||||
|
@ -52,7 +51,7 @@ pub impl<'self> RenderContext<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) {
|
pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) {
|
||||||
let image = arc::get(&image);
|
let image = image.get();
|
||||||
let size = Size2D(image.width as i32, image.height as i32);
|
let size = Size2D(image.width as i32, image.height as i32);
|
||||||
let stride = image.width * 4;
|
let stride = image.width * 4;
|
||||||
|
|
||||||
|
@ -72,7 +71,7 @@ pub impl<'self> RenderContext<'self> {
|
||||||
draw_options);
|
draw_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
let pattern = ColorPattern(Color(1.0, 1.0, 1.0, 1.0));
|
let pattern = ColorPattern(Color(1.0, 1.0, 1.0, 1.0));
|
||||||
let rect = Rect(Point2D(self.canvas.rect.origin.x as AzFloat,
|
let rect = Rect(Point2D(self.canvas.rect.origin.x as AzFloat,
|
||||||
self.canvas.rect.origin.y as AzFloat),
|
self.canvas.rect.origin.y as AzFloat),
|
||||||
|
@ -84,12 +83,12 @@ pub impl<'self> RenderContext<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
trait to_float {
|
trait to_float {
|
||||||
fn to_float(self) -> float;
|
fn to_float(&self) -> float;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl to_float for u8 {
|
impl to_float for u8 {
|
||||||
fn to_float(self) -> float {
|
fn to_float(&self) -> float {
|
||||||
(self as float) / 255f
|
(*self as float) / 255f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,9 @@ use geom::rect::Rect;
|
||||||
use opts::Opts;
|
use opts::Opts;
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use std::comm::{Chan, Port, SharedChan};
|
||||||
|
use std::uint;
|
||||||
|
|
||||||
use servo_util::time::{ProfilerChan, profile};
|
use servo_util::time::{ProfilerChan, profile};
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
|
@ -62,9 +63,9 @@ pub fn create_render_task<C: RenderListener + Owned>(port: Port<Msg<C>>,
|
||||||
compositor: C,
|
compositor: C,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
profiler_chan: ProfilerChan) {
|
profiler_chan: ProfilerChan) {
|
||||||
let compositor_cell = Cell(compositor);
|
let compositor_cell = Cell::new(compositor);
|
||||||
let opts_cell = Cell(opts);
|
let opts_cell = Cell::new(opts);
|
||||||
let port = Cell(port);
|
let port = Cell::new(port);
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
let compositor = compositor_cell.take();
|
let compositor = compositor_cell.take();
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::vec;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
|
|
|
@ -2,19 +2,20 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use servo_util::range::Range;
|
|
||||||
use servo_util::vec::*;
|
use servo_util::vec::*;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use geometry;
|
use geometry;
|
||||||
|
|
||||||
use core::cmp::{Ord, Eq};
|
use std::cmp::{Ord, Eq};
|
||||||
use core::num::NumCast;
|
use std::num::NumCast;
|
||||||
use core::u16;
|
use std::u16;
|
||||||
use core;
|
use std::vec;
|
||||||
|
use std::uint;
|
||||||
|
use std::util;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use std::sort;
|
use extra::sort;
|
||||||
|
|
||||||
/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
|
/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
|
||||||
///
|
///
|
||||||
|
@ -403,11 +404,11 @@ impl<'self> 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);
|
util::swap(&mut self.detail_lookup, &mut unsorted_records);
|
||||||
let mut mut_records : ~[DetailedGlyphRecord] = unsorted_records;
|
let mut mut_records : ~[DetailedGlyphRecord] = unsorted_records;
|
||||||
sort::quick_sort3(mut_records);
|
sort::quick_sort3(mut_records);
|
||||||
let mut sorted_records = mut_records;
|
let mut sorted_records = mut_records;
|
||||||
core::util::swap(&mut self.detail_lookup, &mut sorted_records);
|
util::swap(&mut self.detail_lookup, &mut sorted_records);
|
||||||
|
|
||||||
self.lookup_is_sorted = true;
|
self.lookup_is_sorted = true;
|
||||||
}
|
}
|
||||||
|
@ -468,7 +469,8 @@ impl<'self> GlyphInfo<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn advance(self) -> Au {
|
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
|
||||||
|
fn advance_(self) -> Au {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].advance(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].advance(),
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
|
@ -507,10 +509,10 @@ pub struct GlyphStore {
|
||||||
detail_store: DetailedGlyphStore,
|
detail_store: DetailedGlyphStore,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<'self> GlyphStore {
|
impl<'self> GlyphStore {
|
||||||
// Initializes the glyph store, but doesn't actually shape anything.
|
// Initializes the glyph store, but doesn't actually shape anything.
|
||||||
// Use the set_glyph, set_glyphs() methods to store glyph data.
|
// Use the set_glyph, set_glyphs() methods to store glyph data.
|
||||||
fn new(length: uint) -> GlyphStore {
|
pub fn new(length: uint) -> GlyphStore {
|
||||||
assert!(length > 0);
|
assert!(length > 0);
|
||||||
|
|
||||||
GlyphStore {
|
GlyphStore {
|
||||||
|
@ -519,11 +521,11 @@ pub impl<'self> GlyphStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_changes(&mut self) {
|
pub fn finalize_changes(&mut self) {
|
||||||
self.detail_store.ensure_sorted();
|
self.detail_store.ensure_sorted();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_glyph_for_char_index(&mut self, i: uint, data: &GlyphData) {
|
pub fn add_glyph_for_char_index(&mut self, i: uint, data: &GlyphData) {
|
||||||
fn glyph_is_compressible(data: &GlyphData) -> bool {
|
fn glyph_is_compressible(data: &GlyphData) -> bool {
|
||||||
is_simple_glyph_id(data.index)
|
is_simple_glyph_id(data.index)
|
||||||
&& is_simple_advance(data.advance)
|
&& is_simple_advance(data.advance)
|
||||||
|
@ -547,7 +549,7 @@ pub impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry;
|
self.entry_buffer[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_glyphs_for_char_index(&mut self, i: uint, data_for_glyphs: &[GlyphData]) {
|
pub fn add_glyphs_for_char_index(&mut self, i: uint, data_for_glyphs: &[GlyphData]) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
assert!(data_for_glyphs.len() > 0);
|
assert!(data_for_glyphs.len() > 0);
|
||||||
|
|
||||||
|
@ -576,7 +578,7 @@ pub impl<'self> GlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used when a character index has no associated glyph---for example, a ligature continuation.
|
// used when a character index has no associated glyph---for example, a ligature continuation.
|
||||||
fn add_nonglyph_for_char_index(&mut self, i: uint, cluster_start: bool, ligature_start: bool) {
|
pub fn add_nonglyph_for_char_index(&mut self, i: uint, cluster_start: bool, ligature_start: bool) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
|
|
||||||
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
|
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
|
||||||
|
@ -585,7 +587,7 @@ pub impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry;
|
self.entry_buffer[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_glyphs_for_char_index(&'self self,
|
pub fn iter_glyphs_for_char_index(&'self self,
|
||||||
i: uint,
|
i: uint,
|
||||||
cb: &fn(uint, &GlyphInfo<'self>) -> bool)
|
cb: &fn(uint, &GlyphInfo<'self>) -> bool)
|
||||||
-> bool {
|
-> bool {
|
||||||
|
@ -609,7 +611,7 @@ pub impl<'self> GlyphStore {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_glyphs_for_char_range(&'self self,
|
pub fn iter_glyphs_for_char_range(&'self self,
|
||||||
range: &Range,
|
range: &Range,
|
||||||
callback: &fn(uint, &GlyphInfo<'self>) -> bool)
|
callback: &fn(uint, &GlyphInfo<'self>) -> bool)
|
||||||
-> bool {
|
-> bool {
|
||||||
|
@ -631,7 +633,7 @@ pub impl<'self> GlyphStore {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_all_glyphs(&'self self, cb: &fn(uint, &GlyphInfo<'self>) -> bool) -> bool {
|
pub fn iter_all_glyphs(&'self self, cb: &fn(uint, &GlyphInfo<'self>) -> bool) -> bool {
|
||||||
for uint::range(0, self.entry_buffer.len()) |i| {
|
for uint::range(0, self.entry_buffer.len()) |i| {
|
||||||
if !self.iter_glyphs_for_char_index(i, cb) {
|
if !self.iter_glyphs_for_char_index(i, cb) {
|
||||||
break;
|
break;
|
||||||
|
@ -642,56 +644,56 @@ pub impl<'self> GlyphStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getter methods
|
// getter methods
|
||||||
fn char_is_space(&self, i: uint) -> bool {
|
pub fn char_is_space(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].char_is_space()
|
self.entry_buffer[i].char_is_space()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_is_tab(&self, i: uint) -> bool {
|
pub fn char_is_tab(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].char_is_tab()
|
self.entry_buffer[i].char_is_tab()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_is_newline(&self, i: uint) -> bool {
|
pub fn char_is_newline(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].char_is_newline()
|
self.entry_buffer[i].char_is_newline()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ligature_start(&self, i: uint) -> bool {
|
pub fn is_ligature_start(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].is_ligature_start()
|
self.entry_buffer[i].is_ligature_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cluster_start(&self, i: uint) -> bool {
|
pub fn is_cluster_start(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].is_cluster_start()
|
self.entry_buffer[i].is_cluster_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_break_before(&self, i: uint) -> BreakType {
|
pub fn can_break_before(&self, i: uint) -> BreakType {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
self.entry_buffer[i].can_break_before()
|
self.entry_buffer[i].can_break_before()
|
||||||
}
|
}
|
||||||
|
|
||||||
// setter methods
|
// setter methods
|
||||||
fn set_char_is_space(&mut self, i: uint) {
|
pub fn set_char_is_space(&mut self, i: uint) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
let entry = self.entry_buffer[i];
|
let entry = self.entry_buffer[i];
|
||||||
self.entry_buffer[i] = entry.set_char_is_space();
|
self.entry_buffer[i] = entry.set_char_is_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_char_is_tab(&mut self, i: uint) {
|
pub fn set_char_is_tab(&mut self, i: uint) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
let entry = self.entry_buffer[i];
|
let entry = self.entry_buffer[i];
|
||||||
self.entry_buffer[i] = entry.set_char_is_tab();
|
self.entry_buffer[i] = entry.set_char_is_tab();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_char_is_newline(&mut self, i: uint) {
|
pub fn set_char_is_newline(&mut self, i: uint) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
let entry = self.entry_buffer[i];
|
let entry = self.entry_buffer[i];
|
||||||
self.entry_buffer[i] = entry.set_char_is_newline();
|
self.entry_buffer[i] = entry.set_char_is_newline();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_can_break_before(&mut self, i: uint, t: BreakType) {
|
pub fn set_can_break_before(&mut self, i: uint, t: BreakType) {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
let entry = self.entry_buffer[i];
|
let entry = self.entry_buffer[i];
|
||||||
self.entry_buffer[i] = entry.set_can_break_before(t);
|
self.entry_buffer[i] = entry.set_can_break_before(t);
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
extern mod harfbuzz;
|
extern mod harfbuzz;
|
||||||
|
|
||||||
use geom::Point2D;
|
|
||||||
|
|
||||||
use font::{Font, FontHandleMethods, FontTableMethods, FontTableTag};
|
use font::{Font, FontHandleMethods, FontTableMethods, FontTableTag};
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use platform::font::FontTable;
|
use platform::font::FontTable;
|
||||||
|
@ -14,45 +12,37 @@ use text::shaping::ShaperMethods;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use text::util::{float_to_fixed, fixed_to_float, fixed_to_rounded_int};
|
use text::util::{float_to_fixed, fixed_to_float, fixed_to_rounded_int};
|
||||||
|
|
||||||
use core::cast::transmute;
|
use std::cast::transmute;
|
||||||
use core::libc::{c_uint, c_int, c_void, c_char};
|
use std::libc::{c_uint, c_int, c_void, c_char};
|
||||||
use core::ptr::null;
|
use std::ptr;
|
||||||
use core::util::ignore;
|
use std::ptr::null;
|
||||||
|
use std::str;
|
||||||
|
use std::uint;
|
||||||
|
use std::util::ignore;
|
||||||
|
use std::vec;
|
||||||
use geom::Point2D;
|
use geom::Point2D;
|
||||||
use harfbuzz::bindgen::{hb_blob_create, hb_face_create_for_tables};
|
use harfbuzz::{hb_blob_create, hb_face_create_for_tables};
|
||||||
use harfbuzz::bindgen::{hb_buffer_add_utf8, hb_shape};
|
use harfbuzz::{hb_buffer_add_utf8};
|
||||||
use harfbuzz::bindgen::{hb_buffer_create};
|
use harfbuzz::{hb_buffer_get_glyph_positions};
|
||||||
use harfbuzz::bindgen::{hb_buffer_destroy, hb_buffer_add_utf8};
|
use harfbuzz::{hb_buffer_set_direction};
|
||||||
use harfbuzz::bindgen::{hb_buffer_get_glyph_infos};
|
use harfbuzz::{hb_buffer_destroy};
|
||||||
use harfbuzz::bindgen::{hb_buffer_get_glyph_positions};
|
use harfbuzz::{hb_face_destroy};
|
||||||
use harfbuzz::bindgen::{hb_buffer_get_glyph_positions};
|
use harfbuzz::{hb_font_create};
|
||||||
use harfbuzz::bindgen::{hb_buffer_set_direction};
|
use harfbuzz::{hb_font_destroy, hb_buffer_create};
|
||||||
use harfbuzz::bindgen::{hb_buffer_set_direction};
|
use harfbuzz::{hb_font_funcs_create};
|
||||||
use harfbuzz::bindgen::{hb_face_destroy, hb_font_create};
|
use harfbuzz::{hb_font_funcs_destroy};
|
||||||
use harfbuzz::bindgen::{hb_face_destroy};
|
use harfbuzz::{hb_font_funcs_set_glyph_func};
|
||||||
use harfbuzz::bindgen::{hb_font_create, hb_font_destroy};
|
use harfbuzz::{hb_font_funcs_set_glyph_h_advance_func};
|
||||||
use harfbuzz::bindgen::{hb_font_destroy, hb_buffer_create};
|
use harfbuzz::{hb_font_set_funcs};
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_create, hb_font_funcs_destroy};
|
use harfbuzz::{hb_font_set_ppem};
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_create};
|
use harfbuzz::{hb_font_set_scale};
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_destroy};
|
use harfbuzz::{hb_shape, hb_buffer_get_glyph_infos};
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_set_glyph_func};
|
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_set_glyph_func};
|
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_set_glyph_h_advance_func};
|
|
||||||
use harfbuzz::bindgen::{hb_font_funcs_set_glyph_h_advance_func};
|
|
||||||
use harfbuzz::bindgen::{hb_font_set_funcs};
|
|
||||||
use harfbuzz::bindgen::{hb_font_set_funcs};
|
|
||||||
use harfbuzz::bindgen::{hb_font_set_ppem, hb_font_set_scale};
|
|
||||||
use harfbuzz::bindgen::{hb_font_set_ppem};
|
|
||||||
use harfbuzz::bindgen::{hb_font_set_scale};
|
|
||||||
use harfbuzz::bindgen::{hb_shape, hb_buffer_get_glyph_infos};
|
|
||||||
use harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR, hb_blob_t};
|
|
||||||
use harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR};
|
use harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR};
|
||||||
use harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t};
|
use harfbuzz::{hb_blob_t};
|
||||||
use harfbuzz::{hb_buffer_t, hb_codepoint_t, hb_bool_t};
|
use harfbuzz::{hb_bool_t};
|
||||||
use harfbuzz::{hb_face_t, hb_font_t};
|
use harfbuzz::{hb_face_t, hb_font_t};
|
||||||
use harfbuzz::{hb_font_funcs_t, hb_buffer_t, hb_codepoint_t};
|
use harfbuzz::{hb_font_funcs_t, hb_buffer_t, hb_codepoint_t};
|
||||||
use harfbuzz::{hb_glyph_info_t, hb_position_t};
|
use harfbuzz::{hb_glyph_info_t};
|
||||||
use harfbuzz::{hb_glyph_position_t, hb_glyph_info_t};
|
|
||||||
use harfbuzz::{hb_glyph_position_t};
|
use harfbuzz::{hb_glyph_position_t};
|
||||||
use harfbuzz::{hb_position_t, hb_tag_t};
|
use harfbuzz::{hb_position_t, hb_tag_t};
|
||||||
|
|
||||||
|
@ -74,19 +64,21 @@ pub struct ShapedGlyphEntry {
|
||||||
|
|
||||||
impl ShapedGlyphData {
|
impl ShapedGlyphData {
|
||||||
pub fn new(buffer: *hb_buffer_t) -> ShapedGlyphData {
|
pub fn new(buffer: *hb_buffer_t) -> ShapedGlyphData {
|
||||||
let glyph_count = 0;
|
unsafe {
|
||||||
let glyph_infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
|
let glyph_count = 0;
|
||||||
let glyph_count = glyph_count as uint;
|
let glyph_infos = hb_buffer_get_glyph_infos(buffer, &glyph_count);
|
||||||
assert!(glyph_infos.is_not_null());
|
let glyph_count = glyph_count as uint;
|
||||||
let pos_count = 0;
|
assert!(glyph_infos.is_not_null());
|
||||||
let pos_infos = hb_buffer_get_glyph_positions(buffer, &pos_count);
|
let pos_count = 0;
|
||||||
assert!(pos_infos.is_not_null());
|
let pos_infos = hb_buffer_get_glyph_positions(buffer, &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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,50 +144,54 @@ pub struct Shaper {
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl Drop for Shaper {
|
impl Drop for Shaper {
|
||||||
fn finalize(&self) {
|
fn finalize(&self) {
|
||||||
assert!(self.hb_face.is_not_null());
|
unsafe {
|
||||||
hb_face_destroy(self.hb_face);
|
assert!(self.hb_face.is_not_null());
|
||||||
|
hb_face_destroy(self.hb_face);
|
||||||
|
|
||||||
assert!(self.hb_font.is_not_null());
|
assert!(self.hb_font.is_not_null());
|
||||||
hb_font_destroy(self.hb_font);
|
hb_font_destroy(self.hb_font);
|
||||||
|
|
||||||
assert!(self.hb_funcs.is_not_null());
|
assert!(self.hb_funcs.is_not_null());
|
||||||
hb_font_funcs_destroy(self.hb_funcs);
|
hb_font_funcs_destroy(self.hb_funcs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shaper {
|
impl Shaper {
|
||||||
pub fn new(font: @mut Font) -> Shaper {
|
pub fn new(font: @mut Font) -> Shaper {
|
||||||
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
|
unsafe {
|
||||||
let font_ptr = {
|
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
|
||||||
let borrowed_font= &mut *font;
|
let font_ptr = {
|
||||||
borrowed_font as *mut Font
|
let borrowed_font= &mut *font;
|
||||||
};
|
borrowed_font as *mut Font
|
||||||
let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func,
|
};
|
||||||
font_ptr as *c_void,
|
let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func,
|
||||||
null());
|
font_ptr as *c_void,
|
||||||
let hb_font: *hb_font_t = hb_font_create(hb_face);
|
null());
|
||||||
|
let hb_font: *hb_font_t = hb_font_create(hb_face);
|
||||||
|
|
||||||
// Set points-per-em. if zero, performs no hinting in that direction.
|
// Set points-per-em. if zero, performs no hinting in that direction.
|
||||||
let pt_size = font.style.pt_size;
|
let pt_size = font.style.pt_size;
|
||||||
hb_font_set_ppem(hb_font, pt_size as c_uint, pt_size as c_uint);
|
hb_font_set_ppem(hb_font, pt_size as c_uint, pt_size as c_uint);
|
||||||
|
|
||||||
// Set scaling. Note that this takes 16.16 fixed point.
|
// Set scaling. Note that this takes 16.16 fixed point.
|
||||||
hb_font_set_scale(hb_font,
|
hb_font_set_scale(hb_font,
|
||||||
Shaper::float_to_fixed(pt_size) as c_int,
|
Shaper::float_to_fixed(pt_size) as c_int,
|
||||||
Shaper::float_to_fixed(pt_size) as c_int);
|
Shaper::float_to_fixed(pt_size) as c_int);
|
||||||
|
|
||||||
// configure static function callbacks.
|
// configure static function callbacks.
|
||||||
// NB. This funcs structure could be reused globally, as it never changes.
|
// NB. This funcs structure could be reused globally, as it never changes.
|
||||||
let hb_funcs: *hb_font_funcs_t = hb_font_funcs_create();
|
let hb_funcs: *hb_font_funcs_t = hb_font_funcs_create();
|
||||||
hb_font_funcs_set_glyph_func(hb_funcs, glyph_func, null(), null());
|
hb_font_funcs_set_glyph_func(hb_funcs, glyph_func, null(), null());
|
||||||
hb_font_funcs_set_glyph_h_advance_func(hb_funcs, glyph_h_advance_func, null(), null());
|
hb_font_funcs_set_glyph_h_advance_func(hb_funcs, glyph_h_advance_func, null(), null());
|
||||||
hb_font_set_funcs(hb_font, hb_funcs, font_ptr as *c_void, null());
|
hb_font_set_funcs(hb_font, hb_funcs, font_ptr as *c_void, null());
|
||||||
|
|
||||||
Shaper {
|
Shaper {
|
||||||
font: font,
|
font: font,
|
||||||
hb_face: hb_face,
|
hb_face: hb_face,
|
||||||
hb_font: hb_font,
|
hb_font: hb_font,
|
||||||
hb_funcs: hb_funcs,
|
hb_funcs: hb_funcs,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,21 +212,23 @@ impl ShaperMethods for Shaper {
|
||||||
/// Calculate the layout metrics associated with the given text when rendered in a specific
|
/// Calculate the layout metrics associated with the given text when rendered in a specific
|
||||||
/// font.
|
/// font.
|
||||||
fn shape_text(&self, text: &str, glyphs: &mut GlyphStore) {
|
fn shape_text(&self, text: &str, glyphs: &mut GlyphStore) {
|
||||||
let hb_buffer: *hb_buffer_t = hb_buffer_create();
|
unsafe {
|
||||||
hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);
|
let hb_buffer: *hb_buffer_t = hb_buffer_create();
|
||||||
|
hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);
|
||||||
|
|
||||||
// Using as_buf because it never does a copy - we don't need the trailing null
|
// Using as_buf because it never does a copy - we don't need the trailing null
|
||||||
do str::as_buf(text) |ctext: *u8, _: uint| {
|
do str::as_buf(text) |ctext: *u8, _: uint| {
|
||||||
hb_buffer_add_utf8(hb_buffer,
|
hb_buffer_add_utf8(hb_buffer,
|
||||||
ctext as *c_char,
|
ctext as *c_char,
|
||||||
text.len() as c_int,
|
text.len() as c_int,
|
||||||
0,
|
0,
|
||||||
text.len() as c_int);
|
text.len() as c_int);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_shape(self.hb_font, hb_buffer, null(), 0);
|
||||||
|
self.save_glyph_results(text, glyphs, hb_buffer);
|
||||||
|
hb_buffer_destroy(hb_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_shape(self.hb_font, hb_buffer, null(), 0);
|
|
||||||
self.save_glyph_results(text, glyphs, hb_buffer);
|
|
||||||
hb_buffer_destroy(hb_buffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +237,7 @@ impl Shaper {
|
||||||
let glyph_data = ShapedGlyphData::new(buffer);
|
let glyph_data = ShapedGlyphData::new(buffer);
|
||||||
let glyph_count = glyph_data.len();
|
let glyph_count = glyph_data.len();
|
||||||
let byte_max = text.len();
|
let byte_max = text.len();
|
||||||
let char_max = str::char_len(text);
|
let char_max = text.char_len();
|
||||||
|
|
||||||
// GlyphStore records are indexed by character, not byte offset.
|
// GlyphStore records are indexed by character, not byte offset.
|
||||||
// so, we must be careful to increment this when saving glyph entries.
|
// so, we must be careful to increment this when saving glyph entries.
|
||||||
|
@ -267,7 +265,7 @@ impl Shaper {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < byte_max {
|
while i < byte_max {
|
||||||
byteToGlyph[i] = NO_GLYPH;
|
byteToGlyph[i] = NO_GLYPH;
|
||||||
let range = str::char_range_at(text, i);
|
let range = text.char_range_at(i);
|
||||||
ignore(range.ch);
|
ignore(range.ch);
|
||||||
i = range.next;
|
i = range.next;
|
||||||
}
|
}
|
||||||
|
@ -292,7 +290,7 @@ impl Shaper {
|
||||||
debug!("(char idx): char->(glyph index):");
|
debug!("(char idx): char->(glyph index):");
|
||||||
let mut i = 0u;
|
let mut i = 0u;
|
||||||
while i < byte_max {
|
while i < byte_max {
|
||||||
let range = str::char_range_at(text, i);
|
let range = text.char_range_at(i);
|
||||||
debug!("%u: %? --> %d", i, range.ch, byteToGlyph[i] as int);
|
debug!("%u: %? --> %d", i, range.ch, byteToGlyph[i] as int);
|
||||||
i = range.next;
|
i = range.next;
|
||||||
}
|
}
|
||||||
|
@ -318,7 +316,7 @@ impl Shaper {
|
||||||
// find a range of chars corresponding to this glyph, plus
|
// find a range of chars corresponding to this glyph, plus
|
||||||
// any trailing chars that do not have associated glyphs.
|
// any trailing chars that do not have associated glyphs.
|
||||||
while char_byte_span.end() < byte_max {
|
while char_byte_span.end() < byte_max {
|
||||||
let range = str::char_range_at(text, char_byte_span.end());
|
let range = text.char_range_at(char_byte_span.end());
|
||||||
ignore(range.ch);
|
ignore(range.ch);
|
||||||
char_byte_span.extend_to(range.next);
|
char_byte_span.extend_to(range.next);
|
||||||
|
|
||||||
|
@ -329,7 +327,7 @@ impl Shaper {
|
||||||
byteToGlyph[char_byte_span.end()] == NO_GLYPH {
|
byteToGlyph[char_byte_span.end()] == NO_GLYPH {
|
||||||
debug!("Extending char byte span to include byte offset=%u with no associated \
|
debug!("Extending char byte span to include byte offset=%u with no associated \
|
||||||
glyph", char_byte_span.end());
|
glyph", char_byte_span.end());
|
||||||
let range = str::char_range_at(text, char_byte_span.end());
|
let range = text.char_range_at(char_byte_span.end());
|
||||||
ignore(range.ch);
|
ignore(range.ch);
|
||||||
char_byte_span.extend_to(range.next);
|
char_byte_span.extend_to(range.next);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +402,7 @@ impl Shaper {
|
||||||
// extend, clipping at end of text range.
|
// extend, clipping at end of text range.
|
||||||
while covered_byte_span.end() < byte_max
|
while covered_byte_span.end() < byte_max
|
||||||
&& byteToGlyph[covered_byte_span.end()] == NO_GLYPH {
|
&& byteToGlyph[covered_byte_span.end()] == NO_GLYPH {
|
||||||
let range = str::char_range_at(text, covered_byte_span.end());
|
let range = text.char_range_at(covered_byte_span.end());
|
||||||
ignore(range.ch);
|
ignore(range.ch);
|
||||||
covered_byte_span.extend_to(range.next);
|
covered_byte_span.extend_to(range.next);
|
||||||
}
|
}
|
||||||
|
@ -457,7 +455,7 @@ impl Shaper {
|
||||||
// set the other chars, who have no glyphs
|
// set the other chars, who have no glyphs
|
||||||
let mut i = covered_byte_span.begin();
|
let mut i = covered_byte_span.begin();
|
||||||
loop {
|
loop {
|
||||||
let range = str::char_range_at(text, i);
|
let range = text.char_range_at(i);
|
||||||
ignore(range.ch);
|
ignore(range.ch);
|
||||||
i = range.next;
|
i = range.next;
|
||||||
if i >= covered_byte_span.end() { break; }
|
if i >= covered_byte_span.end() { break; }
|
||||||
|
|
|
@ -42,9 +42,9 @@ impl SendableTextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<'self> TextRun {
|
impl<'self> TextRun {
|
||||||
fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
||||||
let mut glyph_store = GlyphStore::new(str::char_len(text));
|
let mut glyph_store = GlyphStore::new(text.char_len());
|
||||||
TextRun::compute_potential_breaks(text, &mut glyph_store);
|
TextRun::compute_potential_breaks(text, &mut glyph_store);
|
||||||
do profile(time::LayoutShapingCategory, font.profiler_chan.clone()) {
|
do profile(time::LayoutShapingCategory, font.profiler_chan.clone()) {
|
||||||
font.shape_text(text, &mut glyph_store);
|
font.shape_text(text, &mut glyph_store);
|
||||||
|
@ -59,18 +59,18 @@ pub impl<'self> TextRun {
|
||||||
return run;
|
return run;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(&self) {
|
pub fn teardown(&self) {
|
||||||
self.font.teardown();
|
self.font.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) {
|
pub fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) {
|
||||||
// TODO(Issue #230): do a better job. See Gecko's LineBreaker.
|
// TODO(Issue #230): do a better job. See Gecko's LineBreaker.
|
||||||
|
|
||||||
let mut byte_i = 0u;
|
let mut byte_i = 0u;
|
||||||
let mut char_j = 0u;
|
let mut char_j = 0u;
|
||||||
let mut prev_is_whitespace = false;
|
let mut prev_is_whitespace = false;
|
||||||
while byte_i < text.len() {
|
while byte_i < text.len() {
|
||||||
let range = str::char_range_at(text, byte_i);
|
let range = text.char_range_at(byte_i);
|
||||||
let ch = range.ch;
|
let ch = range.ch;
|
||||||
let next = range.next;
|
let next = range.next;
|
||||||
// set char properties.
|
// set char properties.
|
||||||
|
@ -114,10 +114,10 @@ pub impl<'self> TextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char_len(&self) -> uint { self.glyphs.entry_buffer.len() }
|
pub fn char_len(&self) -> uint { self.glyphs.entry_buffer.len() }
|
||||||
fn glyphs(&'self self) -> &'self GlyphStore { &self.glyphs }
|
pub fn glyphs(&'self self) -> &'self GlyphStore { &self.glyphs }
|
||||||
|
|
||||||
fn range_is_trimmable_whitespace(&self, range: &Range) -> bool {
|
pub fn range_is_trimmable_whitespace(&self, range: &Range) -> bool {
|
||||||
for range.eachi |i| {
|
for range.eachi |i| {
|
||||||
if !self.glyphs.char_is_space(i) &&
|
if !self.glyphs.char_is_space(i) &&
|
||||||
!self.glyphs.char_is_tab(i) &&
|
!self.glyphs.char_is_tab(i) &&
|
||||||
|
@ -126,11 +126,11 @@ pub impl<'self> TextRun {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metrics_for_range(&self, range: &Range) -> RunMetrics {
|
pub fn metrics_for_range(&self, range: &Range) -> RunMetrics {
|
||||||
self.font.measure_text(self, range)
|
self.font.measure_text(self, range)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn min_width_for_range(&self, range: &Range) -> Au {
|
pub fn min_width_for_range(&self, range: &Range) -> Au {
|
||||||
let mut max_piece_width = Au(0);
|
let mut max_piece_width = Au(0);
|
||||||
debug!("iterating outer range %?", range);
|
debug!("iterating outer range %?", range);
|
||||||
for self.iter_indivisible_pieces_for_range(range) |piece_range| {
|
for self.iter_indivisible_pieces_for_range(range) |piece_range| {
|
||||||
|
@ -141,7 +141,7 @@ pub impl<'self> TextRun {
|
||||||
return max_piece_width;
|
return max_piece_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
pub fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
||||||
let mut clump = Range::new(range.begin(), 0);
|
let mut clump = Range::new(range.begin(), 0);
|
||||||
let mut in_clump = false;
|
let mut in_clump = false;
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ pub impl<'self> TextRun {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter_indivisible_pieces_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
pub fn iter_indivisible_pieces_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
||||||
let mut clump = Range::new(range.begin(), 0);
|
let mut clump = Range::new(range.begin(), 0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
let mut out_str: ~str = ~"";
|
let mut out_str: ~str = ~"";
|
||||||
let out_whitespace = match mode {
|
let out_whitespace = match mode {
|
||||||
CompressNone | DiscardNewline => {
|
CompressNone | DiscardNewline => {
|
||||||
for str::each_char(text) |ch: char| {
|
for text.iter().advance |ch: char| {
|
||||||
if is_discardable_char(ch, mode) {
|
if is_discardable_char(ch, mode) {
|
||||||
// TODO: record skipped char
|
// TODO: record skipped char
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,7 +46,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
if ch == '\t' {
|
if ch == '\t' {
|
||||||
// TODO: set "has tab" flag
|
// TODO: set "has tab" flag
|
||||||
}
|
}
|
||||||
str::push_char(&mut out_str, ch);
|
out_str.push_char(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
|
text.len() > 0 && is_in_whitespace(text.char_at_reverse(0), mode)
|
||||||
|
@ -54,7 +54,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
|
|
||||||
CompressWhitespace | CompressWhitespaceNewline => {
|
CompressWhitespace | CompressWhitespaceNewline => {
|
||||||
let mut in_whitespace: bool = incoming_whitespace;
|
let mut in_whitespace: bool = incoming_whitespace;
|
||||||
for str::each_char(text) |ch: char| {
|
for text.iter().advance |ch: char| {
|
||||||
// TODO: discard newlines between CJK chars
|
// TODO: discard newlines between CJK chars
|
||||||
let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);
|
let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);
|
||||||
|
|
||||||
|
@ -65,14 +65,14 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
// TODO: record skipped char
|
// TODO: record skipped char
|
||||||
} else {
|
} else {
|
||||||
// TODO: record kept char
|
// TODO: record kept char
|
||||||
str::push_char(&mut out_str, ch);
|
out_str.push_char(ch);
|
||||||
}
|
}
|
||||||
} else { /* next_in_whitespace; possibly add a space char */
|
} else { /* next_in_whitespace; possibly add a space char */
|
||||||
if in_whitespace {
|
if in_whitespace {
|
||||||
// TODO: record skipped char
|
// TODO: record skipped char
|
||||||
} else {
|
} else {
|
||||||
// TODO: record kept char
|
// TODO: record kept char
|
||||||
str::push_char(&mut out_str, ' ');
|
out_str.push_char(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// save whitespace context for next char
|
// save whitespace context for next char
|
||||||
|
|
|
@ -14,10 +14,12 @@ use gfx::render_task::{RenderChan, ReRenderMsg};
|
||||||
|
|
||||||
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
|
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
|
||||||
use azure::azure::AzGLContext;
|
use azure::azure::AzGLContext;
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Chan, SharedChan, Port};
|
use std::comm;
|
||||||
use core::num::Orderable;
|
use std::comm::{Chan, SharedChan, Port};
|
||||||
use core::util;
|
use std::num::Orderable;
|
||||||
|
use std::task;
|
||||||
|
use std::util;
|
||||||
use geom::matrix::identity;
|
use geom::matrix::identity;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
@ -137,8 +139,8 @@ impl CompositorTask {
|
||||||
pub fn create(port: Port<Msg>,
|
pub fn create(port: Port<Msg>,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
shutdown_chan: Chan<()>) {
|
shutdown_chan: Chan<()>) {
|
||||||
let port = Cell(port);
|
let port = Cell::new(port);
|
||||||
let shutdown_chan = Cell(shutdown_chan);
|
let shutdown_chan = Cell::new(shutdown_chan);
|
||||||
do on_osmain {
|
do on_osmain {
|
||||||
let compositor_task = CompositorTask::new(port.take(),
|
let compositor_task = CompositorTask::new(port.take(),
|
||||||
profiler_chan.clone(),
|
profiler_chan.clone(),
|
||||||
|
@ -158,7 +160,7 @@ impl CompositorTask {
|
||||||
// list. This is only here because we don't have that logic in the renderer yet.
|
// list. This is only here because we don't have that logic in the renderer yet.
|
||||||
let context = rendergl::init_render_context();
|
let context = rendergl::init_render_context();
|
||||||
let root_layer = @mut ContainerLayer();
|
let root_layer = @mut ContainerLayer();
|
||||||
let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0, 600.0), identity());
|
let scene = @mut Scene(ContainerLayerKind(root_layer), Size2D(800.0f32, 600.0), identity());
|
||||||
let done = @mut false;
|
let done = @mut false;
|
||||||
|
|
||||||
// FIXME: This should not be a separate offset applied after the fact but rather should be
|
// FIXME: This should not be a separate offset applied after the fact but rather should be
|
||||||
|
@ -181,7 +183,7 @@ impl CompositorTask {
|
||||||
// Hook the windowing system's resize callback up to the resize rate limiter.
|
// Hook the windowing system's resize callback up to the resize rate limiter.
|
||||||
do window.set_resize_callback |width, height| {
|
do window.set_resize_callback |width, height| {
|
||||||
debug!("osmain: window resized to %ux%u", width, height);
|
debug!("osmain: window resized to %ux%u", width, height);
|
||||||
*window_size = Size2D(width, height);
|
*window_size = Size2D(width as int, height as int);
|
||||||
layout_chan_clone.chan.send(RouteScriptMsg(SendEventMsg(ResizeEvent(width, height))));
|
layout_chan_clone.chan.send(RouteScriptMsg(SendEventMsg(ResizeEvent(width, height))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use layout::aux::LayoutAuxMethods;
|
use layout::aux::LayoutAuxMethods;
|
||||||
|
|
||||||
use core::cast::transmute;
|
use std::cast::transmute;
|
||||||
use newcss::complete::CompleteSelectResults;
|
use newcss::complete::CompleteSelectResults;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
use url_from_str = std::net::url::from_str;
|
use url_from_str = extra::net::url::from_str;
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::result;
|
||||||
|
use std::str;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::select::SelectCtx;
|
use newcss::select::SelectCtx;
|
||||||
use newcss::types::OriginUA;
|
use newcss::types::OriginUA;
|
||||||
|
@ -32,7 +34,7 @@ fn default_url(name: &str) -> Url {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_stream(style: &str) -> DataStream {
|
fn style_stream(style: &str) -> DataStream {
|
||||||
let style = Cell(str::to_bytes(style));
|
let style = Cell::new(style.as_bytes().to_owned());
|
||||||
let d: DataStream = || if !style.is_empty() {
|
let d: DataStream = || if !style.is_empty() {
|
||||||
Some(style.take())
|
Some(style.take())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
/// Implementation of the callbacks that the CSS selector engine uses to query the DOM.
|
/// Implementation of the callbacks that the CSS selector engine uses to query the DOM.
|
||||||
///
|
///
|
||||||
|
|
||||||
use core::str::eq_slice;
|
use std::str;
|
||||||
|
use std::str::eq_slice;
|
||||||
use newcss::select::SelectHandler;
|
use newcss::select::SelectHandler;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
|
|
||||||
|
@ -104,7 +105,7 @@ impl SelectHandler<AbstractNode<LayoutView>> for NodeSelectHandler {
|
||||||
None => false,
|
None => false,
|
||||||
Some(existing_classes) => {
|
Some(existing_classes) => {
|
||||||
let mut ret = false;
|
let mut ret = false;
|
||||||
for str::each_split_char(existing_classes, ' ') |s| {
|
for existing_classes.split_iter(' ').advance |s| {
|
||||||
if s == class {
|
if s == class {
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
use compositing::{CompositorChan, SetLayoutChan, SetRenderChan};
|
use compositing::{CompositorChan, SetLayoutChan, SetRenderChan};
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::Port;
|
use std::comm;
|
||||||
|
use std::comm::Port;
|
||||||
|
use std::task;
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use gfx::render_task::RenderChan;
|
use gfx::render_task::RenderChan;
|
||||||
use gfx::render_task;
|
use gfx::render_task;
|
||||||
|
@ -43,7 +45,7 @@ impl Engine {
|
||||||
($Msg:ty, $Chan:ident) => (
|
($Msg:ty, $Chan:ident) => (
|
||||||
{
|
{
|
||||||
let (port, chan) = comm::stream::<$Msg>();
|
let (port, chan) = comm::stream::<$Msg>();
|
||||||
(Cell(port), $Chan::new(chan))
|
(Cell::new(port), $Chan::new(chan))
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
)
|
)
|
||||||
|
@ -58,15 +60,15 @@ impl Engine {
|
||||||
let (layout_port, layout_chan) = closure_stream!(layout_interface::Msg, LayoutChan);
|
let (layout_port, layout_chan) = closure_stream!(layout_interface::Msg, LayoutChan);
|
||||||
|
|
||||||
let (render_port, render_chan) = comm::stream::<render_task::Msg<CompositorChan>>();
|
let (render_port, render_chan) = comm::stream::<render_task::Msg<CompositorChan>>();
|
||||||
let (render_port, render_chan) = (Cell(render_port), RenderChan::new(render_chan));
|
let (render_port, render_chan) = (Cell::new(render_port), RenderChan::new(render_chan));
|
||||||
|
|
||||||
|
|
||||||
compositor_chan.send(SetLayoutChan(layout_chan.clone()));
|
compositor_chan.send(SetLayoutChan(layout_chan.clone()));
|
||||||
compositor_chan.send(SetRenderChan(render_chan.clone()));
|
compositor_chan.send(SetRenderChan(render_chan.clone()));
|
||||||
|
|
||||||
let compositor_chan = Cell(compositor_chan);
|
let compositor_chan = Cell::new(compositor_chan);
|
||||||
|
|
||||||
let opts = Cell(copy *opts);
|
let opts = Cell::new(copy *opts);
|
||||||
|
|
||||||
{
|
{
|
||||||
let engine_chan = engine_chan.clone();
|
let engine_chan = engine_chan.clone();
|
||||||
|
|
|
@ -40,21 +40,20 @@ pub trait LayoutAuxMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
||||||
// FIXME (Rust #3080): These unsafe blocks are *not* unused!
|
|
||||||
pub fn layout_data(self) -> @mut LayoutData {
|
pub fn layout_data(self) -> @mut LayoutData {
|
||||||
/*unsafe {*/
|
unsafe {
|
||||||
self.unsafe_layout_data()
|
self.unsafe_layout_data()
|
||||||
/*}*/
|
}
|
||||||
}
|
}
|
||||||
pub fn has_layout_data(self) -> bool {
|
pub fn has_layout_data(self) -> bool {
|
||||||
/*unsafe {*/
|
unsafe {
|
||||||
self.unsafe_has_layout_data()
|
self.unsafe_has_layout_data()
|
||||||
/*}*/
|
}
|
||||||
}
|
}
|
||||||
pub fn set_layout_data(self, data: @mut LayoutData) {
|
pub fn set_layout_data(self, data: @mut LayoutData) {
|
||||||
/*unsafe {*/
|
unsafe {
|
||||||
self.unsafe_set_layout_data(data)
|
self.unsafe_set_layout_data(data)
|
||||||
/*}*/
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If none exists, creates empty layout data for the node (the reader-auxiliary
|
/// If none exists, creates empty layout data for the node (the reader-auxiliary
|
||||||
|
|
|
@ -13,7 +13,7 @@ use layout::inline::InlineLayout;
|
||||||
use layout::model::{MaybeAuto, Specified, Auto};
|
use layout::model::{MaybeAuto, Specified, Auto};
|
||||||
use layout::float_context::FloatContext;
|
use layout::float_context::FloatContext;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
|
@ -51,7 +51,7 @@ impl BlockFlowData {
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.common.teardown();
|
self.common.teardown();
|
||||||
for self.box.each |box| {
|
for self.box.iter().advance |box| {
|
||||||
box.teardown();
|
box.teardown();
|
||||||
}
|
}
|
||||||
self.box = None;
|
self.box = None;
|
||||||
|
@ -192,7 +192,7 @@ impl BlockFlowData {
|
||||||
let mut remaining_width = self.common.position.size.width;
|
let mut remaining_width = self.common.position.size.width;
|
||||||
let mut x_offset = Au(0);
|
let mut x_offset = Au(0);
|
||||||
|
|
||||||
for self.box.each |&box| {
|
for self.box.iter().advance |&box| {
|
||||||
let style = box.style();
|
let style = box.style();
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
|
@ -251,7 +251,7 @@ impl BlockFlowData {
|
||||||
let mut top_offset = Au(0);
|
let mut top_offset = Au(0);
|
||||||
let mut left_offset = Au(0);
|
let mut left_offset = Au(0);
|
||||||
|
|
||||||
for self.box.each |&box| {
|
for self.box.iter().advance |&box| {
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
top_offset = model.margin.top + model.border.top + model.padding.top;
|
top_offset = model.margin.top + model.border.top + model.padding.top;
|
||||||
cur_y += top_offset;
|
cur_y += top_offset;
|
||||||
|
|
|
@ -11,10 +11,11 @@ use layout::flow::FlowContext;
|
||||||
use layout::model::{BoxModel, MaybeAuto};
|
use layout::model::{BoxModel, MaybeAuto};
|
||||||
use layout::text;
|
use layout::text;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::cmp::ApproxEq;
|
use std::cmp::ApproxEq;
|
||||||
use core::managed;
|
use std::managed;
|
||||||
use core::num::Zero;
|
use std::num::Zero;
|
||||||
|
use std::uint;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
||||||
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
||||||
|
@ -35,7 +36,7 @@ use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_net::image::holder::ImageHolder;
|
use servo_net::image::holder::ImageHolder;
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::range::*;
|
use servo_util::range::*;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
/// Render boxes (`struct RenderBox`) are the leaves of the layout tree. They cannot position
|
/// Render boxes (`struct RenderBox`) are the leaves of the layout tree. They cannot position
|
||||||
/// themselves. In general, render boxes do not have a simple correspondence with CSS boxes as in
|
/// themselves. In general, render boxes do not have a simple correspondence with CSS boxes as in
|
||||||
|
@ -178,10 +179,10 @@ impl RenderBoxBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl RenderBox {
|
impl RenderBox {
|
||||||
/// Borrows this render box immutably in order to work with its common data.
|
/// Borrows this render box immutably in order to work with its common data.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn with_base<R>(&self, callback: &fn(&RenderBoxBase) -> R) -> R {
|
pub fn with_base<R>(&self, callback: &fn(&RenderBoxBase) -> R) -> R {
|
||||||
match *self {
|
match *self {
|
||||||
GenericRenderBoxClass(generic_box) => callback(generic_box),
|
GenericRenderBoxClass(generic_box) => callback(generic_box),
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
|
@ -198,7 +199,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Borrows this render box mutably in order to work with its common data.
|
/// Borrows this render box mutably in order to work with its common data.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn with_mut_base<R>(&self, callback: &fn(&mut RenderBoxBase) -> R) -> R {
|
pub fn with_mut_base<R>(&self, callback: &fn(&mut RenderBoxBase) -> R) -> R {
|
||||||
match *self {
|
match *self {
|
||||||
GenericRenderBoxClass(generic_box) => callback(generic_box),
|
GenericRenderBoxClass(generic_box) => callback(generic_box),
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
|
@ -214,14 +215,14 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to return the position of this box.
|
/// A convenience function to return the position of this box.
|
||||||
fn position(&self) -> Rect<Au> {
|
pub fn position(&self) -> Rect<Au> {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
base.position
|
base.position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to return the debugging ID of this box.
|
/// A convenience function to return the debugging ID of this box.
|
||||||
fn id(&self) -> int {
|
pub fn id(&self) -> int {
|
||||||
do self.with_mut_base |base| {
|
do self.with_mut_base |base| {
|
||||||
base.id
|
base.id
|
||||||
}
|
}
|
||||||
|
@ -229,7 +230,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Returns true if this element is replaced content. This is true for images, form elements,
|
/// Returns true if this element is replaced content. This is true for images, form elements,
|
||||||
/// and so on.
|
/// and so on.
|
||||||
fn is_replaced(&self) -> bool {
|
pub fn is_replaced(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
ImageRenderBoxClass(*) => true,
|
ImageRenderBoxClass(*) => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -237,7 +238,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this element can be split. This is true for text boxes.
|
/// Returns true if this element can be split. This is true for text boxes.
|
||||||
fn can_split(&self) -> bool {
|
pub fn can_split(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
TextRenderBoxClass(*) => true,
|
TextRenderBoxClass(*) => true,
|
||||||
_ => false
|
_ => false
|
||||||
|
@ -245,7 +246,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this element is an unscanned text box that consists entirely of whitespace.
|
/// Returns true if this element is an unscanned text box that consists entirely of whitespace.
|
||||||
fn is_whitespace_only(&self) -> bool {
|
pub fn is_whitespace_only(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
UnscannedTextRenderBoxClass(unscanned_text_box) => {
|
UnscannedTextRenderBoxClass(unscanned_text_box) => {
|
||||||
unscanned_text_box.text.is_whitespace()
|
unscanned_text_box.text.is_whitespace()
|
||||||
|
@ -255,7 +256,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether this box can merge with another render box.
|
/// Determines whether this box can merge with another render box.
|
||||||
fn can_merge_with_box(&self, other: RenderBox) -> bool {
|
pub fn can_merge_with_box(&self, other: RenderBox) -> bool {
|
||||||
match (self, &other) {
|
match (self, &other) {
|
||||||
(&UnscannedTextRenderBoxClass(*), &UnscannedTextRenderBoxClass(*)) => {
|
(&UnscannedTextRenderBoxClass(*), &UnscannedTextRenderBoxClass(*)) => {
|
||||||
self.font_style() == other.font_style() && self.text_decoration() == other.text_decoration()
|
self.font_style() == other.font_style() && self.text_decoration() == other.text_decoration()
|
||||||
|
@ -269,7 +270,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Attempts to split this box so that its width is no more than `max_width`. Fails if this box
|
/// Attempts to split this box so that its width is no more than `max_width`. Fails if this box
|
||||||
/// is an unscanned text box.
|
/// is an unscanned text box.
|
||||||
fn split_to_width(&self, _: &LayoutContext, max_width: Au, starts_line: bool)
|
pub fn split_to_width(&self, _: &LayoutContext, max_width: Au, starts_line: bool)
|
||||||
-> SplitBoxResult {
|
-> SplitBoxResult {
|
||||||
match *self {
|
match *self {
|
||||||
GenericRenderBoxClass(*) | ImageRenderBoxClass(*) => CannotSplit(*self),
|
GenericRenderBoxClass(*) | ImageRenderBoxClass(*) => CannotSplit(*self),
|
||||||
|
@ -400,7 +401,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the *minimum width* of this render box as defined by the CSS specification.
|
/// Returns the *minimum width* of this render box as defined by the CSS specification.
|
||||||
fn get_min_width(&self, _: &LayoutContext) -> Au {
|
pub fn get_min_width(&self, _: &LayoutContext) -> Au {
|
||||||
// FIXME(pcwalton): I think we only need to calculate this if the damage says that CSS
|
// FIXME(pcwalton): I think we only need to calculate this if the damage says that CSS
|
||||||
// needs to be restyled.
|
// needs to be restyled.
|
||||||
|
|
||||||
|
@ -426,7 +427,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the *preferred width* of this render box as defined by the CSS specification.
|
/// Returns the *preferred width* of this render box as defined by the CSS specification.
|
||||||
fn get_pref_width(&self, _: &LayoutContext) -> Au {
|
pub fn get_pref_width(&self, _: &LayoutContext) -> Au {
|
||||||
self.guess_width() + match *self {
|
self.guess_width() + match *self {
|
||||||
// TODO: This should account for the preferred width of the box element in isolation.
|
// TODO: This should account for the preferred width of the box element in isolation.
|
||||||
// That includes borders, margins, and padding, but not child widths. The block
|
// That includes borders, margins, and padding, but not child widths. The block
|
||||||
|
@ -451,7 +452,7 @@ pub impl RenderBox {
|
||||||
let mut line_width: Au = Au(0);
|
let mut line_width: Au = Au(0);
|
||||||
for text_box.run.glyphs.iter_glyphs_for_char_range(line_range)
|
for text_box.run.glyphs.iter_glyphs_for_char_range(line_range)
|
||||||
|_, glyph| {
|
|_, glyph| {
|
||||||
line_width += glyph.advance()
|
line_width += glyph.advance_()
|
||||||
}
|
}
|
||||||
|
|
||||||
max_line_width = Au::max(max_line_width, line_width);
|
max_line_width = Au::max(max_line_width, line_width);
|
||||||
|
@ -466,32 +467,32 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Returns the amount of left and right "fringe" used by this box. This is based on margins,
|
/// Returns the amount of left and right "fringe" used by this box. This is based on margins,
|
||||||
/// borders, padding, and width.
|
/// borders, padding, and width.
|
||||||
fn get_used_width(&self) -> (Au, Au) {
|
pub fn get_used_width(&self) -> (Au, Au) {
|
||||||
// TODO: This should actually do some computation! See CSS 2.1, Sections 10.3 and 10.4.
|
// TODO: This should actually do some computation! See CSS 2.1, Sections 10.3 and 10.4.
|
||||||
(Au(0), Au(0))
|
(Au(0), Au(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the amount of left and right "fringe" used by this box. This should be based on
|
/// Returns the amount of left and right "fringe" used by this box. This should be based on
|
||||||
/// margins, borders, padding, and width.
|
/// margins, borders, padding, and width.
|
||||||
fn get_used_height(&self) -> (Au, Au) {
|
pub fn get_used_height(&self) -> (Au, Au) {
|
||||||
// TODO: This should actually do some computation! See CSS 2.1, Sections 10.5 and 10.6.
|
// TODO: This should actually do some computation! See CSS 2.1, Sections 10.5 and 10.6.
|
||||||
(Au(0), Au(0))
|
(Au(0), Au(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_padding(&self, cb_width: Au) {
|
pub fn compute_padding(&self, cb_width: Au) {
|
||||||
do self.with_mut_base |base| {
|
do self.with_mut_base |base| {
|
||||||
base.model.compute_padding(base.node.style(), cb_width);
|
base.model.compute_padding(base.node.style(), cb_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_noncontent_width(&self) -> Au {
|
pub fn get_noncontent_width(&self) -> Au {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
base.model.border.left + base.model.padding.left +
|
base.model.border.left + base.model.padding.left +
|
||||||
base.model.border.right + base.model.padding.right
|
base.model.border.right + base.model.padding.right
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_model<R>(&self, callback: &fn(&mut BoxModel) -> R) -> R {
|
pub fn with_model<R>(&self, callback: &fn(&mut BoxModel) -> R) -> R {
|
||||||
do self.with_mut_base |base| {
|
do self.with_mut_base |base| {
|
||||||
callback(&mut base.model)
|
callback(&mut base.model)
|
||||||
}
|
}
|
||||||
|
@ -499,7 +500,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// The box formed by the content edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
/// The box formed by the content edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
||||||
/// the owning flow.
|
/// the owning flow.
|
||||||
fn content_box(&self) -> Rect<Au> {
|
pub fn content_box(&self) -> Rect<Au> {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
let origin = Point2D(base.position.origin.x +
|
let origin = Point2D(base.position.origin.x +
|
||||||
base.model.border.left +
|
base.model.border.left +
|
||||||
|
@ -513,26 +514,26 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// The box formed by the border edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
/// The box formed by the border edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
||||||
/// the owning flow.
|
/// the owning flow.
|
||||||
fn border_box(&self) -> Rect<Au> {
|
pub fn border_box(&self) -> Rect<Au> {
|
||||||
// TODO: Actually compute the content box, padding, and border.
|
// TODO: Actually compute the content box, padding, and border.
|
||||||
self.content_box()
|
self.content_box()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The box formed by the margin edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
/// The box formed by the margin edge as defined in CSS 2.1 § 8.1. Coordinates are relative to
|
||||||
/// the owning flow.
|
/// the owning flow.
|
||||||
fn margin_box(&self) -> Rect<Au> {
|
pub fn margin_box(&self) -> Rect<Au> {
|
||||||
// TODO: Actually compute the content_box, padding, border, and margin.
|
// TODO: Actually compute the content_box, padding, border, and margin.
|
||||||
self.content_box()
|
self.content_box()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to access the computed style of the DOM node that this render box
|
/// A convenience function to access the computed style of the DOM node that this render box
|
||||||
/// represents.
|
/// represents.
|
||||||
fn style(&self) -> CompleteStyle {
|
pub fn style(&self) -> CompleteStyle {
|
||||||
self.with_base(|base| base.node.style())
|
self.with_base(|base| base.node.style())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to access the DOM node that this render box represents.
|
/// A convenience function to access the DOM node that this render box represents.
|
||||||
fn node(&self) -> AbstractNode<LayoutView> {
|
pub fn node(&self) -> AbstractNode<LayoutView> {
|
||||||
self.with_base(|base| base.node)
|
self.with_base(|base| base.node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +541,7 @@ pub impl RenderBox {
|
||||||
/// represents.
|
/// represents.
|
||||||
///
|
///
|
||||||
/// If there is no ancestor-or-self `Element` node, fails.
|
/// If there is no ancestor-or-self `Element` node, fails.
|
||||||
fn nearest_ancestor_element(&self) -> AbstractNode<LayoutView> {
|
pub fn nearest_ancestor_element(&self) -> AbstractNode<LayoutView> {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
let mut node = base.node;
|
let mut node = base.node;
|
||||||
while !node.is_element() {
|
while !node.is_element() {
|
||||||
|
@ -571,7 +572,7 @@ pub impl RenderBox {
|
||||||
/// representing the box's stacking context. When asked to construct its constituent display
|
/// representing the box's stacking context. When asked to construct its constituent display
|
||||||
/// items, each box puts its display items into the correct stack layer according to CSS 2.1
|
/// items, each box puts its display items into the correct stack layer according to CSS 2.1
|
||||||
/// Appendix E. Finally, the builder flattens the list.
|
/// Appendix E. Finally, the builder flattens the list.
|
||||||
fn build_display_list<E:ExtraDisplayListData>(&self,
|
pub fn build_display_list<E:ExtraDisplayListData>(&self,
|
||||||
_: &DisplayListBuilder,
|
_: &DisplayListBuilder,
|
||||||
dirty: &Rect<Au>,
|
dirty: &Rect<Au>,
|
||||||
offset: &Point2D<Au>,
|
offset: &Point2D<Au>,
|
||||||
|
@ -715,7 +716,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background of this render box to the display
|
/// Adds the display items necessary to paint the background of this render box to the display
|
||||||
/// list if necessary.
|
/// list if necessary.
|
||||||
fn paint_background_if_applicable<E:ExtraDisplayListData>(&self,
|
pub fn paint_background_if_applicable<E:ExtraDisplayListData>(&self,
|
||||||
list: &Cell<DisplayList<E>>,
|
list: &Cell<DisplayList<E>>,
|
||||||
absolute_bounds: &Rect<Au>) {
|
absolute_bounds: &Rect<Au>) {
|
||||||
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
|
@ -741,7 +742,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts this node's computed style to a font style used for rendering.
|
/// Converts this node's computed style to a font style used for rendering.
|
||||||
fn font_style(&self) -> FontStyle {
|
pub fn font_style(&self) -> FontStyle {
|
||||||
let my_style = self.nearest_ancestor_element().style();
|
let my_style = self.nearest_ancestor_element().style();
|
||||||
|
|
||||||
debug!("(font style) start: %?", self.nearest_ancestor_element().type_id());
|
debug!("(font style) start: %?", self.nearest_ancestor_element().type_id());
|
||||||
|
@ -757,7 +758,7 @@ pub impl RenderBox {
|
||||||
CSSFontFamilyGenericFamily(Monospace) => ~"monospace",
|
CSSFontFamilyGenericFamily(Monospace) => ~"monospace",
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let font_families = str::connect(font_families, ~", ");
|
let font_families = font_families.connect(", ");
|
||||||
debug!("(font style) font families: `%s`", font_families);
|
debug!("(font style) font families: `%s`", font_families);
|
||||||
|
|
||||||
let font_size = match my_style.font_size() {
|
let font_size = match my_style.font_size() {
|
||||||
|
@ -786,7 +787,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
|
/// Returns the text alignment of the computed style of the nearest ancestor-or-self `Element`
|
||||||
/// node.
|
/// node.
|
||||||
fn text_align(&self) -> CSSTextAlign {
|
pub fn text_align(&self) -> CSSTextAlign {
|
||||||
self.nearest_ancestor_element().style().text_align()
|
self.nearest_ancestor_element().style().text_align()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -795,7 +796,7 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the text decoration of the computed style of the nearest `Element` node
|
/// Returns the text decoration of the computed style of the nearest `Element` node
|
||||||
fn text_decoration(&self) -> CSSTextDecoration {
|
pub fn text_decoration(&self) -> CSSTextDecoration {
|
||||||
/// Computes the propagated value of text-decoration, as specified in CSS 2.1 § 16.3.1
|
/// Computes the propagated value of text-decoration, as specified in CSS 2.1 § 16.3.1
|
||||||
/// TODO: make sure this works with anonymous box generation.
|
/// TODO: make sure this works with anonymous box generation.
|
||||||
fn get_propagated_text_decoration(element: AbstractNode<LayoutView>) -> CSSTextDecoration {
|
fn get_propagated_text_decoration(element: AbstractNode<LayoutView>) -> CSSTextDecoration {
|
||||||
|
@ -856,9 +857,10 @@ pub impl RenderBox {
|
||||||
GenericRenderBoxClass(*) => ~"GenericRenderBox",
|
GenericRenderBoxClass(*) => ~"GenericRenderBox",
|
||||||
ImageRenderBoxClass(*) => ~"ImageRenderBox",
|
ImageRenderBoxClass(*) => ~"ImageRenderBox",
|
||||||
TextRenderBoxClass(text_box) => {
|
TextRenderBoxClass(text_box) => {
|
||||||
fmt!("TextRenderBox(text=%s)", str::substr(text_box.run.text,
|
fmt!("TextRenderBox(text=%s)",
|
||||||
text_box.range.begin(),
|
text_box.run.text.slice(
|
||||||
text_box.range.length()))
|
text_box.range.begin(),
|
||||||
|
text_box.range.begin() + text_box.range.length()))
|
||||||
}
|
}
|
||||||
UnscannedTextRenderBoxClass(text_box) => {
|
UnscannedTextRenderBoxClass(text_box) => {
|
||||||
fmt!("UnscannedTextRenderBox(%s)", text_box.text)
|
fmt!("UnscannedTextRenderBox(%s)", text_box.text)
|
||||||
|
|
|
@ -36,8 +36,8 @@ pub struct LayoutTreeBuilder {
|
||||||
next_bid: int,
|
next_bid: int,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl LayoutTreeBuilder {
|
impl LayoutTreeBuilder {
|
||||||
fn new() -> LayoutTreeBuilder {
|
pub fn new() -> LayoutTreeBuilder {
|
||||||
LayoutTreeBuilder {
|
LayoutTreeBuilder {
|
||||||
root_flow: None,
|
root_flow: None,
|
||||||
next_cid: -1,
|
next_cid: -1,
|
||||||
|
@ -142,7 +142,8 @@ impl BoxGenerator {
|
||||||
inline.boxes.push(new_box);
|
inline.boxes.push(new_box);
|
||||||
} else if self.inline_spacers_needed_for_node(node) {
|
} else if self.inline_spacers_needed_for_node(node) {
|
||||||
// else, maybe make a spacer for "left" margin, border, padding
|
// else, maybe make a spacer for "left" margin, border, padding
|
||||||
for self.make_inline_spacer_for_node_side(ctx, node, LogicalBefore).each
|
let inline_spacer = self.make_inline_spacer_for_node_side(ctx, node, LogicalBefore);
|
||||||
|
for inline_spacer.iter().advance
|
||||||
|spacer: &RenderBox| {
|
|spacer: &RenderBox| {
|
||||||
inline.boxes.push(*spacer);
|
inline.boxes.push(*spacer);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +191,7 @@ impl BoxGenerator {
|
||||||
// If this non-leaf box generates extra horizontal spacing, add a SpacerBox for
|
// If this non-leaf box generates extra horizontal spacing, add a SpacerBox for
|
||||||
// it.
|
// it.
|
||||||
let result = self.make_inline_spacer_for_node_side(ctx, node, LogicalAfter);
|
let result = self.make_inline_spacer_for_node_side(ctx, node, LogicalAfter);
|
||||||
for result.each |spacer| {
|
for result.iter().advance |spacer| {
|
||||||
let boxes = &mut self.flow.inline().boxes;
|
let boxes = &mut self.flow.inline().boxes;
|
||||||
boxes.push(*spacer);
|
boxes.push(*spacer);
|
||||||
}
|
}
|
||||||
|
@ -269,14 +270,14 @@ impl BoxGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub impl LayoutTreeBuilder {
|
impl LayoutTreeBuilder {
|
||||||
/* Debug-only ids */
|
/* Debug-only ids */
|
||||||
fn next_flow_id(&mut self) -> int { self.next_cid += 1; self.next_cid }
|
pub fn next_flow_id(&mut self) -> int { self.next_cid += 1; self.next_cid }
|
||||||
fn next_box_id(&mut self) -> int { self.next_bid += 1; self.next_bid }
|
pub fn next_box_id(&mut self) -> int { self.next_bid += 1; self.next_bid }
|
||||||
|
|
||||||
/// Creates necessary box(es) and flow context(s) for the current DOM node,
|
/// Creates necessary box(es) and flow context(s) for the current DOM node,
|
||||||
/// and recurses on its children.
|
/// and recurses on its children.
|
||||||
fn construct_recursively(&mut self,
|
pub fn construct_recursively(&mut self,
|
||||||
layout_ctx: &LayoutContext,
|
layout_ctx: &LayoutContext,
|
||||||
cur_node: AbstractNode<LayoutView>,
|
cur_node: AbstractNode<LayoutView>,
|
||||||
parent_generator: @mut BoxGenerator,
|
parent_generator: @mut BoxGenerator,
|
||||||
|
@ -319,7 +320,7 @@ pub impl LayoutTreeBuilder {
|
||||||
Some(this_generator)
|
Some(this_generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn box_generator_for_node(&mut self,
|
pub fn box_generator_for_node(&mut self,
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
parent_generator: @mut BoxGenerator,
|
parent_generator: @mut BoxGenerator,
|
||||||
sibling_generator: Option<@mut BoxGenerator>)
|
sibling_generator: Option<@mut BoxGenerator>)
|
||||||
|
@ -433,7 +434,7 @@ pub impl LayoutTreeBuilder {
|
||||||
Some(new_generator)
|
Some(new_generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_child_generator(&mut self,
|
pub fn create_child_generator(&mut self,
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
parent_generator: @mut BoxGenerator,
|
parent_generator: @mut BoxGenerator,
|
||||||
ty: FlowContextType)
|
ty: FlowContextType)
|
||||||
|
@ -445,7 +446,7 @@ pub impl LayoutTreeBuilder {
|
||||||
@mut BoxGenerator::new(new_flow)
|
@mut BoxGenerator::new(new_flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_child_generator_if_needed(&mut self,
|
pub fn create_child_generator_if_needed(&mut self,
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
parent_generator: @mut BoxGenerator,
|
parent_generator: @mut BoxGenerator,
|
||||||
maybe_generator: Option<@mut BoxGenerator>,
|
maybe_generator: Option<@mut BoxGenerator>,
|
||||||
|
@ -466,7 +467,7 @@ pub impl LayoutTreeBuilder {
|
||||||
///
|
///
|
||||||
/// The latter can only be done immediately adjacent to, or at the beginning or end of a block
|
/// The latter can only be done immediately adjacent to, or at the beginning or end of a block
|
||||||
/// flow. Otherwise, the whitespace might affect whitespace collapsing with adjacent text.
|
/// flow. Otherwise, the whitespace might affect whitespace collapsing with adjacent text.
|
||||||
fn simplify_children_of_flow(&self, _: &LayoutContext, parent_flow: &mut FlowContext) {
|
pub fn simplify_children_of_flow(&self, _: &LayoutContext, parent_flow: &mut FlowContext) {
|
||||||
match *parent_flow {
|
match *parent_flow {
|
||||||
InlineFlow(*) => {
|
InlineFlow(*) => {
|
||||||
let mut found_child_inline = false;
|
let mut found_child_inline = false;
|
||||||
|
@ -493,7 +494,7 @@ pub impl LayoutTreeBuilder {
|
||||||
let first_child = do parent_flow.with_base |parent_node| {
|
let first_child = do parent_flow.with_base |parent_node| {
|
||||||
parent_node.first_child
|
parent_node.first_child
|
||||||
};
|
};
|
||||||
for first_child.each |&first_flow| {
|
for first_child.iter().advance |&first_flow| {
|
||||||
if first_flow.starts_inline_flow() {
|
if first_flow.starts_inline_flow() {
|
||||||
// FIXME: workaround for rust#6393
|
// FIXME: workaround for rust#6393
|
||||||
let mut do_remove = false;
|
let mut do_remove = false;
|
||||||
|
@ -516,7 +517,7 @@ pub impl LayoutTreeBuilder {
|
||||||
let last_child = do parent_flow.with_base |parent_node| {
|
let last_child = do parent_flow.with_base |parent_node| {
|
||||||
parent_node.last_child
|
parent_node.last_child
|
||||||
};
|
};
|
||||||
for last_child.each |&last_flow| {
|
for last_child.iter().advance |&last_flow| {
|
||||||
if last_flow.starts_inline_flow() {
|
if last_flow.starts_inline_flow() {
|
||||||
// FIXME: workaround for rust#6393
|
// FIXME: workaround for rust#6393
|
||||||
let mut do_remove = false;
|
let mut do_remove = false;
|
||||||
|
@ -540,13 +541,13 @@ pub impl LayoutTreeBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fixup_split_inline(&self, _: FlowContext) {
|
pub fn fixup_split_inline(&self, _: 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 called on the root DOM element.
|
/// Entry point for box creation. Should only be called on the root DOM element.
|
||||||
fn construct_trees(&mut self, layout_ctx: &LayoutContext, root: AbstractNode<LayoutView>)
|
pub fn construct_trees(&mut self, layout_ctx: &LayoutContext, root: AbstractNode<LayoutView>)
|
||||||
-> Result<FlowContext, ()> {
|
-> Result<FlowContext, ()> {
|
||||||
let new_flow = self.make_flow(Flow_Root, root);
|
let new_flow = self.make_flow(Flow_Root, root);
|
||||||
let new_generator = @mut BoxGenerator::new(new_flow);
|
let new_generator = @mut BoxGenerator::new(new_flow);
|
||||||
|
@ -557,7 +558,7 @@ pub impl LayoutTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a flow of the given type for the supplied node.
|
/// Creates a flow of the given type for the supplied node.
|
||||||
fn make_flow(&mut self, ty: FlowContextType, node: AbstractNode<LayoutView>) -> FlowContext {
|
pub fn make_flow(&mut self, ty: FlowContextType, node: AbstractNode<LayoutView>) -> FlowContext {
|
||||||
let info = FlowData::new(self.next_flow_id(), node);
|
let info = FlowData::new(self.next_flow_id(), node);
|
||||||
let result = match ty {
|
let result = match ty {
|
||||||
Flow_Absolute => AbsoluteFlow(@mut info),
|
Flow_Absolute => AbsoluteFlow(@mut info),
|
||||||
|
|
|
@ -8,7 +8,7 @@ use layout::box::RenderBox;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
|
|
|
@ -10,7 +10,7 @@ use layout::flow::{FloatFlow, FlowData};
|
||||||
use layout::model::{MaybeAuto};
|
use layout::model::{MaybeAuto};
|
||||||
use layout::float_context::{FloatContext, PlacementInfo, FloatLeft};
|
use layout::float_context::{FloatContext, PlacementInfo, FloatLeft};
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
|
@ -48,7 +48,7 @@ impl FloatFlowData {
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.common.teardown();
|
self.common.teardown();
|
||||||
for self.box.each |box| {
|
for self.box.iter().advance |box| {
|
||||||
box.teardown();
|
box.teardown();
|
||||||
}
|
}
|
||||||
self.box = None;
|
self.box = None;
|
||||||
|
@ -95,7 +95,7 @@ impl FloatFlowData {
|
||||||
self.containing_width = remaining_width;
|
self.containing_width = remaining_width;
|
||||||
let mut x_offset = Au(0);
|
let mut x_offset = Au(0);
|
||||||
|
|
||||||
for self.box.each |&box| {
|
for self.box.iter().advance |&box| {
|
||||||
let style = box.style();
|
let style = box.style();
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
|
@ -161,7 +161,7 @@ impl FloatFlowData {
|
||||||
let mut cur_y = Au(0);
|
let mut cur_y = Au(0);
|
||||||
let mut top_offset = Au(0);
|
let mut top_offset = Au(0);
|
||||||
|
|
||||||
for self.box.each |&box| {
|
for self.box.iter().advance |&box| {
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
top_offset = model.margin.top + model.border.top + model.padding.top;
|
top_offset = model.margin.top + model.border.top + model.padding.top;
|
||||||
cur_y += top_offset;
|
cur_y += top_offset;
|
||||||
|
@ -193,7 +193,7 @@ impl FloatFlowData {
|
||||||
|
|
||||||
|
|
||||||
//TODO(eatkinson): compute heights properly using the 'height' property.
|
//TODO(eatkinson): compute heights properly using the 'height' property.
|
||||||
for self.box.each |&box| {
|
for self.box.iter().advance |&box| {
|
||||||
|
|
||||||
let height_prop =
|
let height_prop =
|
||||||
MaybeAuto::from_height(box.style().height(), Au(0)).spec_or_default(Au(0));
|
MaybeAuto::from_height(box.style().height(), Au(0)).spec_or_default(Au(0));
|
||||||
|
|
|
@ -6,7 +6,8 @@ use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::geometry::{Au, max, min};
|
use gfx::geometry::{Au, max, min};
|
||||||
use core::util::replace;
|
use std::util::replace;
|
||||||
|
use std::vec;
|
||||||
|
|
||||||
pub enum FloatType{
|
pub enum FloatType{
|
||||||
FloatLeft,
|
FloatLeft,
|
||||||
|
|
|
@ -33,7 +33,8 @@ use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
use layout::inline::{InlineFlowData};
|
use layout::inline::{InlineFlowData};
|
||||||
use layout::float_context::{FloatContext, Invalid};
|
use layout::float_context::{FloatContext, Invalid};
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use std::uint;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
|
@ -89,14 +90,14 @@ impl FlowData {
|
||||||
// or we risk dynamic borrow failures.
|
// or we risk dynamic borrow failures.
|
||||||
self.parent = None;
|
self.parent = None;
|
||||||
|
|
||||||
for self.first_child.each |flow| {
|
for self.first_child.iter().advance |flow| {
|
||||||
flow.teardown();
|
flow.teardown();
|
||||||
}
|
}
|
||||||
self.first_child = None;
|
self.first_child = None;
|
||||||
|
|
||||||
self.last_child = None;
|
self.last_child = None;
|
||||||
|
|
||||||
for self.next_sibling.each |flow| {
|
for self.next_sibling.iter().advance |flow| {
|
||||||
flow.teardown();
|
flow.teardown();
|
||||||
}
|
}
|
||||||
self.next_sibling = None;
|
self.next_sibling = None;
|
||||||
|
@ -317,14 +318,14 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(block) => {
|
BlockFlow(block) => {
|
||||||
let block = &mut *block;
|
let block = &mut *block;
|
||||||
do block.box.map_default(seed) |box| {
|
do block.box.map_default(copy seed) |box| {
|
||||||
cb(seed, *box)
|
cb(copy seed, *box)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineFlow(inline) => {
|
InlineFlow(inline) => {
|
||||||
let inline = &mut *inline;
|
let inline = &mut *inline;
|
||||||
do inline.boxes.foldl(seed) |acc, box| {
|
do inline.boxes.foldl(seed) |acc, box| {
|
||||||
cb(*acc, *box)
|
cb(copy *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)),
|
||||||
|
@ -349,7 +350,7 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(block) => {
|
BlockFlow(block) => {
|
||||||
let block = &mut *block;
|
let block = &mut *block;
|
||||||
for block.box.each |box| {
|
for block.box.iter().advance |box| {
|
||||||
if !cb(*box) {
|
if !cb(*box) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -357,7 +358,7 @@ impl<'self> FlowContext {
|
||||||
}
|
}
|
||||||
InlineFlow(inline) => {
|
InlineFlow(inline) => {
|
||||||
let inline = &mut *inline;
|
let inline = &mut *inline;
|
||||||
for inline.boxes.each |box| {
|
for inline.boxes.iter().advance |box| {
|
||||||
if !cb(*box) {
|
if !cb(*box) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core;
|
use std;
|
||||||
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
|
use layout::box::{CannotSplit, GenericRenderBoxClass, ImageRenderBoxClass, RenderBox};
|
||||||
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
use layout::box::{SplitDidFit, SplitDidNotFit, TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
@ -12,7 +12,10 @@ use layout::flow::{FlowContext, FlowData, InlineFlow};
|
||||||
use layout::text::{UnscannedMethods, adapt_textbox_with_range};
|
use layout::text::{UnscannedMethods, adapt_textbox_with_range};
|
||||||
use layout::float_context::FloatContext;
|
use layout::float_context::FloatContext;
|
||||||
|
|
||||||
use core::util;
|
use std::u16;
|
||||||
|
use std::uint;
|
||||||
|
use std::util;
|
||||||
|
use std::vec;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
|
@ -25,8 +28,8 @@ use newcss::units::{Em, Px, Pt};
|
||||||
use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage};
|
use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage};
|
||||||
|
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use std::deque::Deque;
|
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
use extra::deque::Deque;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Lineboxes are represented as offsets into the child list, rather than
|
Lineboxes are represented as offsets into the child list, rather than
|
||||||
|
@ -55,8 +58,8 @@ pub struct NodeRange {
|
||||||
range: Range,
|
range: Range,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl NodeRange {
|
impl NodeRange {
|
||||||
fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
pub fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
||||||
NodeRange { node: node, range: copy *range }
|
NodeRange { node: node, range: copy *range }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,9 +329,9 @@ impl TextRunScanner {
|
||||||
let mut new_ranges: ~[Range] = ~[];
|
let mut new_ranges: ~[Range] = ~[];
|
||||||
let mut char_total = 0;
|
let mut char_total = 0;
|
||||||
for uint::range(0, transformed_strs.len()) |i| {
|
for uint::range(0, transformed_strs.len()) |i| {
|
||||||
let added_chars = str::char_len(transformed_strs[i]);
|
let added_chars = transformed_strs[i].char_len();
|
||||||
new_ranges.push(Range::new(char_total, added_chars));
|
new_ranges.push(Range::new(char_total, added_chars));
|
||||||
str::push_str(&mut run_str, transformed_strs[i]);
|
run_str.push_str(transformed_strs[i]);
|
||||||
char_total += added_chars;
|
char_total += added_chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +418,7 @@ impl LineboxScanner {
|
||||||
flow: inline,
|
flow: inline,
|
||||||
new_boxes: ~[],
|
new_boxes: ~[],
|
||||||
work_list: @mut Deque::new(),
|
work_list: @mut Deque::new(),
|
||||||
pending_line: PendingLine {mut range: Range::empty(), mut bounds: Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0)))},
|
pending_line: PendingLine {range: Range::empty(), bounds: Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0)))},
|
||||||
line_spans: ~[],
|
line_spans: ~[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -637,7 +640,7 @@ impl LineboxScanner {
|
||||||
debug!("LineboxScanner: Pushing box b%d to line %u", box.id(), self.line_spans.len());
|
debug!("LineboxScanner: Pushing box b%d to line %u", box.id(), self.line_spans.len());
|
||||||
|
|
||||||
if self.pending_line.range.length() == 0 {
|
if self.pending_line.range.length() == 0 {
|
||||||
assert!(self.new_boxes.len() <= (core::u16::max_value as uint));
|
assert!(self.new_boxes.len() <= (u16::max_value as uint));
|
||||||
self.pending_line.range.reset(self.new_boxes.len(), 0);
|
self.pending_line.range.reset(self.new_boxes.len(), 0);
|
||||||
}
|
}
|
||||||
self.pending_line.range.extend_by(1);
|
self.pending_line.range.extend_by(1);
|
||||||
|
|
|
@ -15,9 +15,9 @@ use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
|
|
||||||
use core::cast::transmute;
|
use std::cast::transmute;
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Chan, Port};
|
use std::comm::{Chan, Port};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
@ -43,7 +43,7 @@ use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
use servo_util::time::{ProfilerChan, profile, time};
|
use servo_util::time::{ProfilerChan, profile, time};
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
pub fn create_layout_task(port: Port<Msg>,
|
pub fn create_layout_task(port: Port<Msg>,
|
||||||
script_chan: ScriptChan,
|
script_chan: ScriptChan,
|
||||||
|
@ -51,7 +51,7 @@ pub fn create_layout_task(port: Port<Msg>,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
profiler_chan: ProfilerChan) {
|
profiler_chan: ProfilerChan) {
|
||||||
let port = Cell(port);
|
let port = Cell::new(port);
|
||||||
do spawn {
|
do spawn {
|
||||||
let mut layout = Layout::new(port.take(),
|
let mut layout = Layout::new(port.take(),
|
||||||
script_chan.clone(),
|
script_chan.clone(),
|
||||||
|
@ -129,14 +129,14 @@ impl Layout {
|
||||||
match self.port.recv() {
|
match self.port.recv() {
|
||||||
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
|
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
|
||||||
ReflowMsg(data) => {
|
ReflowMsg(data) => {
|
||||||
let data = Cell(data);
|
let data = Cell::new(data);
|
||||||
|
|
||||||
do profile(time::LayoutPerformCategory, self.profiler_chan.clone()) {
|
do profile(time::LayoutPerformCategory, self.profiler_chan.clone()) {
|
||||||
self.handle_reflow(data.take());
|
self.handle_reflow(data.take());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QueryMsg(query, chan) => {
|
QueryMsg(query, chan) => {
|
||||||
let chan = Cell(chan);
|
let chan = Cell::new(chan);
|
||||||
do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) {
|
do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) {
|
||||||
self.handle_query(query, chan.take());
|
self.handle_query(query, chan.take());
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_add_stylesheet(&self, sheet: Stylesheet) {
|
fn handle_add_stylesheet(&self, sheet: Stylesheet) {
|
||||||
let sheet = Cell(sheet);
|
let sheet = Cell::new(sheet);
|
||||||
self.css_select_ctx.append_sheet(sheet.take(), OriginAuthor);
|
self.css_select_ctx.append_sheet(sheet.take(), OriginAuthor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ impl Layout {
|
||||||
ctx: &layout_ctx,
|
ctx: &layout_ctx,
|
||||||
};
|
};
|
||||||
|
|
||||||
let display_list = @Cell(DisplayList::new());
|
let display_list = @Cell::new(DisplayList::new());
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -346,7 +346,7 @@ impl Layout {
|
||||||
ctx: &layout_ctx,
|
ctx: &layout_ctx,
|
||||||
};
|
};
|
||||||
let display_list: @Cell<DisplayList<RenderBox>> =
|
let display_list: @Cell<DisplayList<RenderBox>> =
|
||||||
@Cell(DisplayList::new());
|
@Cell::new(DisplayList::new());
|
||||||
flow.build_display_list(&builder,
|
flow.build_display_list(&builder,
|
||||||
&flow.position(),
|
&flow.position(),
|
||||||
display_list);
|
display_list);
|
||||||
|
@ -355,7 +355,7 @@ impl Layout {
|
||||||
let mut resp = Err(());
|
let mut resp = Err(());
|
||||||
let display_list = &display_list.take().list;
|
let display_list = &display_list.take().list;
|
||||||
// iterate in reverse to ensure we have the most recently painted render box
|
// iterate in reverse to ensure we have the most recently painted render box
|
||||||
for display_list.each_reverse |display_item| {
|
for display_list.rev_iter().advance |display_item| {
|
||||||
let bounds = display_item.bounds();
|
let bounds = display_item.bounds();
|
||||||
// TODO this check should really be performed by a method of DisplayItem
|
// TODO this check should really be performed by a method of DisplayItem
|
||||||
if x <= bounds.origin.x + bounds.size.width &&
|
if x <= bounds.origin.x + bounds.size.width &&
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
use layout::display_list_builder::{ExtraDisplayListData, ToGfxColor};
|
use layout::display_list_builder::{ExtraDisplayListData, ToGfxColor};
|
||||||
use layout::box::RenderBox;
|
use layout::box::RenderBox;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::num::Zero;
|
use std::num::Zero;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
@ -172,7 +172,8 @@ impl RenderBox {
|
||||||
// Are all the widths equal?
|
// Are all the widths equal?
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Obviously this is wrong.
|
// FIXME(pcwalton): Obviously this is wrong.
|
||||||
if [ border.top, border.right, border.bottom ].all(|a| *a == border.left) {
|
let borders = [ border.top, border.right, border.bottom ];
|
||||||
|
if borders.iter().all(|a| *a == border.left) {
|
||||||
let border_width = border.top;
|
let border_width = border.top;
|
||||||
let bounds = Rect {
|
let bounds = Rect {
|
||||||
origin: Point2D {
|
origin: Point2D {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use windowing::{ResizeCallback, ScrollCallback, WindowMethods, WindowMouseEvent,
|
||||||
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback};
|
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback};
|
||||||
|
|
||||||
use alert::{Alert, AlertMethods};
|
use alert::{Alert, AlertMethods};
|
||||||
use core::libc::c_int;
|
use std::libc::c_int;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use servo_msg::compositor::{IdleRenderState, RenderState, RenderingRenderState};
|
use servo_msg::compositor::{IdleRenderState, RenderState, RenderingRenderState};
|
||||||
|
@ -59,8 +59,7 @@ impl WindowMethods<Application> for Window {
|
||||||
/// Creates a new window.
|
/// Creates a new window.
|
||||||
pub fn new(_: &Application) -> @mut Window {
|
pub fn new(_: &Application) -> @mut Window {
|
||||||
// Create the GLUT window.
|
// Create the GLUT window.
|
||||||
// FIXME (Rust #3080): These unsafe blocks are *not* unused!
|
unsafe { glut::glutInitWindowSize(800, 600); }
|
||||||
/*unsafe { */glut::bindgen::glutInitWindowSize(800, 600);/* }*/
|
|
||||||
let glut_window = glut::create_window(~"Servo");
|
let glut_window = glut::create_window(~"Servo");
|
||||||
|
|
||||||
// Create our window object.
|
// Create our window object.
|
||||||
|
@ -74,10 +73,10 @@ impl WindowMethods<Application> for Window {
|
||||||
scroll_callback: None,
|
scroll_callback: None,
|
||||||
zoom_callback: None,
|
zoom_callback: None,
|
||||||
|
|
||||||
drag_origin: Point2D(0, 0),
|
drag_origin: Point2D(0 as c_int, 0),
|
||||||
|
|
||||||
mouse_down_button: @mut 0,
|
mouse_down_button: @mut 0,
|
||||||
mouse_down_point: @mut Point2D(0, 0),
|
mouse_down_point: @mut Point2D(0 as c_int, 0),
|
||||||
|
|
||||||
ready_state: FinishedLoading,
|
ready_state: FinishedLoading,
|
||||||
render_state: IdleRenderState,
|
render_state: IdleRenderState,
|
||||||
|
@ -231,12 +230,12 @@ impl Window {
|
||||||
match key {
|
match key {
|
||||||
12 => self.load_url(), // Ctrl+L
|
12 => self.load_url(), // Ctrl+L
|
||||||
k if k == ('=' as u8) && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl++
|
k if k == ('=' as u8) && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl++
|
||||||
for self.zoom_callback.each |&callback| {
|
for self.zoom_callback.iter().advance |&callback| {
|
||||||
callback(0.1);
|
callback(0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k if k == 31 && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl+-
|
k if k == 31 && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => { // Ctrl+-
|
||||||
for self.zoom_callback.each |&callback| {
|
for self.zoom_callback.iter().advance |&callback| {
|
||||||
callback(-0.1);
|
callback(-0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern mod servo_msg (name = "msg");
|
||||||
extern mod servo_util (name = "util");
|
extern mod servo_util (name = "util");
|
||||||
extern mod sharegl;
|
extern mod sharegl;
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod std;
|
extern mod extra;
|
||||||
|
|
||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
extern mod core_graphics;
|
extern mod core_graphics;
|
||||||
|
@ -42,11 +42,13 @@ use gfx::opts;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::time::{Profiler, ProfilerChan, PrintMsg};
|
use servo_util::time::{Profiler, ProfilerChan, PrintMsg};
|
||||||
use std::uv_global_loop;
|
use extra::uv_global_loop;
|
||||||
|
|
||||||
pub use gfx::opts::Opts;
|
pub use gfx::opts::Opts;
|
||||||
pub use gfx::text;
|
pub use gfx::text;
|
||||||
pub use servo_util::url::make_url;
|
pub use servo_util::url::make_url;
|
||||||
|
use std::comm;
|
||||||
|
use std::os;
|
||||||
|
|
||||||
#[path="compositing/mod.rs"]
|
#[path="compositing/mod.rs"]
|
||||||
pub mod compositing;
|
pub mod compositing;
|
||||||
|
@ -102,7 +104,7 @@ fn run(opts: &Opts) {
|
||||||
let period = *period;
|
let period = *period;
|
||||||
do spawn {
|
do spawn {
|
||||||
loop {
|
loop {
|
||||||
std::timer::sleep(&uv_global_loop::get(),
|
extra::timer::sleep(&uv_global_loop::get(),
|
||||||
(period * 1000f64) as uint);
|
(period * 1000f64) as uint);
|
||||||
profiler_chan.send(PrintMsg);
|
profiler_chan.send(PrintMsg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Chan, Port};
|
use std::comm;
|
||||||
use core::task;
|
use std::comm::{Chan, Port};
|
||||||
|
use std::task;
|
||||||
|
|
||||||
pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
|
pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
|
||||||
let (setup_po, setup_ch) = comm::stream();
|
let (setup_po, setup_ch) = comm::stream();
|
||||||
|
@ -18,7 +19,7 @@ pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
|
||||||
|
|
||||||
pub fn spawn_conversation<A: Owned, B: Owned>(f: ~fn(Port<A>, Chan<B>)) -> (Port<B>, Chan<A>) {
|
pub fn spawn_conversation<A: Owned, B: Owned>(f: ~fn(Port<A>, Chan<B>)) -> (Port<B>, Chan<A>) {
|
||||||
let (from_child, to_parent) = comm::stream();
|
let (from_child, to_parent) = comm::stream();
|
||||||
let to_parent = Cell(to_parent);
|
let to_parent = Cell::new(to_parent);
|
||||||
let to_child = do spawn_listener |from_parent| {
|
let to_child = do spawn_listener |from_parent| {
|
||||||
f(from_parent, to_parent.take())
|
f(from_parent, to_parent.take())
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
//! The high-level interface from script to engine. Using this abstract interface helps reduce
|
//! The high-level interface from script to engine. Using this abstract interface helps reduce
|
||||||
/// coupling between these two components
|
/// coupling between these two components
|
||||||
|
|
||||||
use core::comm::{Chan, SharedChan};
|
use std::comm::{Chan, SharedChan};
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct EngineChan {
|
pub struct EngineChan {
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
|
|
||||||
extern mod azure;
|
extern mod azure;
|
||||||
extern mod core;
|
|
||||||
extern mod geom;
|
|
||||||
extern mod std;
|
extern mod std;
|
||||||
|
extern mod geom;
|
||||||
|
extern mod extra;
|
||||||
|
|
||||||
pub mod compositor;
|
pub mod compositor;
|
||||||
pub mod engine;
|
pub mod engine;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
use resource_task::{Done, LoaderTask, Payload};
|
use resource_task::{Done, LoaderTask, Payload};
|
||||||
|
|
||||||
use core::io::{ReaderUtil, file_reader};
|
use std::io::{ReaderUtil, file_reader};
|
||||||
use core::task;
|
use std::task;
|
||||||
|
|
||||||
static READ_SIZE: uint = 1024;
|
static READ_SIZE: uint = 1024;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
use resource_task::{Payload, Done, LoaderTask};
|
use resource_task::{Payload, Done, LoaderTask};
|
||||||
|
|
||||||
use core::comm::SharedChan;
|
use std::comm::SharedChan;
|
||||||
use core::task;
|
use std::task;
|
||||||
use http_client::uv_http_request;
|
use http_client::uv_http_request;
|
||||||
use http_client;
|
use http_client;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::vec;
|
||||||
use stb_image = stb_image::image;
|
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
|
||||||
|
|
|
@ -6,10 +6,10 @@ use image::base::Image;
|
||||||
use image_cache_task::{ImageReady, ImageNotReady, ImageFailed};
|
use image_cache_task::{ImageReady, ImageNotReady, ImageFailed};
|
||||||
use local_image_cache::LocalImageCache;
|
use local_image_cache::LocalImageCache;
|
||||||
|
|
||||||
use core::util::replace;
|
use std::util::replace;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
use std::arc::{ARC, clone, get};
|
use extra::arc::ARC;
|
||||||
|
|
||||||
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
||||||
// the network stack. This should probably be factored out into an interface and use dependency
|
// the network stack. This should probably be factored out into an interface and use dependency
|
||||||
|
@ -24,7 +24,7 @@ pub struct ImageHolder {
|
||||||
local_image_cache: @mut LocalImageCache,
|
local_image_cache: @mut LocalImageCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl ImageHolder {
|
impl ImageHolder {
|
||||||
pub fn new(url: Url, local_image_cache: @mut LocalImageCache) -> ImageHolder {
|
pub fn new(url: Url, local_image_cache: @mut LocalImageCache) -> ImageHolder {
|
||||||
debug!("ImageHolder::new() %?", url.to_str());
|
debug!("ImageHolder::new() %?", url.to_str());
|
||||||
let holder = ImageHolder {
|
let holder = ImageHolder {
|
||||||
|
@ -50,16 +50,16 @@ pub impl ImageHolder {
|
||||||
///
|
///
|
||||||
/// The intent is that the impure version is used during layout when dimensions are used for
|
/// The intent is that the impure version is used during layout when dimensions are used for
|
||||||
/// computing layout.
|
/// computing layout.
|
||||||
fn size(&self) -> Size2D<int> {
|
pub fn size(&self) -> Size2D<int> {
|
||||||
self.cached_size
|
self.cached_size
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Query and update the current image size.
|
/// Query and update the current image size.
|
||||||
fn get_size(&mut self) -> Option<Size2D<int>> {
|
pub fn get_size(&mut self) -> Option<Size2D<int>> {
|
||||||
debug!("get_size() %?", self.url);
|
debug!("get_size() %?", self.url);
|
||||||
match self.get_image() {
|
match self.get_image() {
|
||||||
Some(img) => {
|
Some(img) => {
|
||||||
let img_ref = get(&img);
|
let img_ref = img.get();
|
||||||
self.cached_size = Size2D(img_ref.width as int,
|
self.cached_size = Size2D(img_ref.width as int,
|
||||||
img_ref.height as int);
|
img_ref.height as int);
|
||||||
Some(copy self.cached_size)
|
Some(copy self.cached_size)
|
||||||
|
@ -68,7 +68,7 @@ pub impl ImageHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_image(&mut self) -> Option<ARC<~Image>> {
|
pub fn get_image(&mut self) -> Option<ARC<~Image>> {
|
||||||
debug!("get_image() %?", self.url);
|
debug!("get_image() %?", self.url);
|
||||||
|
|
||||||
// If this is the first time we've called this function, load
|
// If this is the first time we've called this function, load
|
||||||
|
@ -91,7 +91,7 @@ pub impl ImageHolder {
|
||||||
let image = replace(&mut self.image, None);
|
let image = replace(&mut self.image, None);
|
||||||
|
|
||||||
let result = match image {
|
let result = match image {
|
||||||
Some(ref image) => Some(clone(image)),
|
Some(ref image) => Some(image.clone()),
|
||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,14 @@ use resource_task;
|
||||||
use resource_task::ResourceTask;
|
use resource_task::ResourceTask;
|
||||||
use servo_util::url::{UrlMap, url_map};
|
use servo_util::url::{UrlMap, url_map};
|
||||||
|
|
||||||
use clone_arc = std::arc::clone;
|
use std::cell::Cell;
|
||||||
use core::cell::Cell;
|
use std::comm::{Chan, Port, SharedChan, stream};
|
||||||
use core::comm::{Chan, Port, SharedChan, stream};
|
use std::task::spawn;
|
||||||
use core::task::spawn;
|
use std::to_str::ToStr;
|
||||||
use core::to_str::ToStr;
|
use std::util::replace;
|
||||||
use core::util::replace;
|
use std::result;
|
||||||
use std::arc::ARC;
|
use extra::arc::ARC;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
/// Tell the cache that we may need a particular image soon. Must be posted
|
/// Tell the cache that we may need a particular image soon. Must be posted
|
||||||
|
@ -54,7 +54,7 @@ pub enum ImageResponseMsg {
|
||||||
impl ImageResponseMsg {
|
impl ImageResponseMsg {
|
||||||
fn clone(&self) -> ImageResponseMsg {
|
fn clone(&self) -> ImageResponseMsg {
|
||||||
match *self {
|
match *self {
|
||||||
ImageReady(ref img) => ImageReady(clone_arc(img)),
|
ImageReady(ref img) => ImageReady(img.clone()),
|
||||||
ImageNotReady => ImageNotReady,
|
ImageNotReady => ImageNotReady,
|
||||||
ImageFailed => ImageFailed,
|
ImageFailed => ImageFailed,
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,12 @@ pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFact
|
||||||
// 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
|
||||||
let decoder_factory_cell = Cell(decoder_factory);
|
let decoder_factory_cell = Cell::new(decoder_factory);
|
||||||
|
|
||||||
let (port, chan) = stream();
|
let (port, chan) = stream();
|
||||||
let chan = SharedChan::new(chan);
|
let chan = SharedChan::new(chan);
|
||||||
let port_cell = Cell(port);
|
let port_cell = Cell::new(port);
|
||||||
let chan_cell = Cell(chan.clone());
|
let chan_cell = Cell::new(chan.clone());
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
let mut cache = ImageCache {
|
let mut cache = ImageCache {
|
||||||
|
@ -116,7 +116,7 @@ pub fn ImageCacheTask_(resource_task: ResourceTask, decoder_factory: DecoderFact
|
||||||
|
|
||||||
fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
|
fn SyncImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
|
||||||
let (port, chan) = stream();
|
let (port, chan) = stream();
|
||||||
let port_cell = Cell(port);
|
let port_cell = Cell::new(port);
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
let port = port_cell.take();
|
let port = port_cell.take();
|
||||||
|
@ -247,7 +247,7 @@ impl ImageCache {
|
||||||
Init => {
|
Init => {
|
||||||
let to_cache = self.chan.clone();
|
let to_cache = self.chan.clone();
|
||||||
let resource_task = self.resource_task.clone();
|
let resource_task = self.resource_task.clone();
|
||||||
let url_cell = Cell(copy url);
|
let url_cell = Cell::new(copy url);
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
let url = url_cell.take();
|
let url = url_cell.take();
|
||||||
|
@ -256,7 +256,7 @@ impl ImageCache {
|
||||||
let image = load_image_data(copy url, resource_task.clone());
|
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(image)))
|
Ok(Cell::new(result::unwrap(image)))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
};
|
};
|
||||||
|
@ -279,7 +279,7 @@ impl ImageCache {
|
||||||
match data {
|
match data {
|
||||||
Ok(data_cell) => {
|
Ok(data_cell) => {
|
||||||
let data = data_cell.take();
|
let data = data_cell.take();
|
||||||
self.set_state(copy url, Prefetched(@Cell(data)));
|
self.set_state(copy url, Prefetched(@Cell::new(data)));
|
||||||
match next_step {
|
match next_step {
|
||||||
DoDecode => self.decode(url),
|
DoDecode => self.decode(url),
|
||||||
_ => ()
|
_ => ()
|
||||||
|
@ -320,7 +320,7 @@ impl ImageCache {
|
||||||
|
|
||||||
let data = data_cell.take();
|
let data = data_cell.take();
|
||||||
let to_cache = self.chan.clone();
|
let to_cache = self.chan.clone();
|
||||||
let url_cell = Cell(copy url);
|
let url_cell = Cell::new(copy url);
|
||||||
let decode = (self.decoder_factory)();
|
let decode = (self.decoder_factory)();
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
|
@ -351,8 +351,8 @@ impl ImageCache {
|
||||||
Decoding => {
|
Decoding => {
|
||||||
match image {
|
match image {
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
self.set_state(copy url, Decoded(@clone_arc(&image)));
|
self.set_state(copy url, Decoded(@image.clone()));
|
||||||
self.purge_waiters(url, || ImageReady(clone_arc(&image)) );
|
self.purge_waiters(url, || ImageReady(image.clone()) );
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.set_state(copy url, Failed);
|
self.set_state(copy url, Failed);
|
||||||
|
@ -389,7 +389,7 @@ impl ImageCache {
|
||||||
Prefetching(DoDecode) => response.send(ImageNotReady),
|
Prefetching(DoDecode) => response.send(ImageNotReady),
|
||||||
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
||||||
Decoding => response.send(ImageNotReady),
|
Decoding => response.send(ImageNotReady),
|
||||||
Decoded(image) => response.send(ImageReady(clone_arc(image))),
|
Decoded(image) => response.send(ImageReady((*image).clone())),
|
||||||
Failed => response.send(ImageFailed),
|
Failed => response.send(ImageFailed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -411,7 +411,7 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoded(image) => {
|
Decoded(image) => {
|
||||||
response.send(ImageReady(clone_arc(image)));
|
response.send(ImageReady((*image).clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Failed => {
|
Failed => {
|
||||||
|
|
|
@ -11,16 +11,17 @@ multiple times and thus triggering reflows multiple times.
|
||||||
use image_cache_task::{Decode, GetImage, ImageCacheTask, ImageFailed, ImageNotReady, ImageReady};
|
use image_cache_task::{Decode, GetImage, ImageCacheTask, ImageFailed, ImageNotReady, ImageReady};
|
||||||
use image_cache_task::{ImageResponseMsg, Prefetch, WaitForImage};
|
use image_cache_task::{ImageResponseMsg, Prefetch, WaitForImage};
|
||||||
|
|
||||||
use clone_arc = std::arc::clone;
|
use std::comm;
|
||||||
use core::comm::Port;
|
use std::comm::Port;
|
||||||
|
use std::task;
|
||||||
use servo_util::url::{UrlMap, url_map};
|
use servo_util::url::{UrlMap, url_map};
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
||||||
LocalImageCache {
|
LocalImageCache {
|
||||||
image_cache_task: image_cache_task,
|
image_cache_task: image_cache_task,
|
||||||
round_number: 1,
|
round_number: 1,
|
||||||
mut on_image_available: None,
|
on_image_available: None,
|
||||||
state_map: url_map()
|
state_map: url_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +41,7 @@ priv struct ImageState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)] // Using maps of Urls
|
#[allow(non_implicitly_copyable_typarams)] // Using maps of Urls
|
||||||
pub impl LocalImageCache {
|
impl LocalImageCache {
|
||||||
/// The local cache will only do a single remote request for a given
|
/// The local cache will only do a single remote request for a given
|
||||||
/// URL in each 'round'. Layout should call this each time it begins
|
/// URL in each 'round'. Layout should call this each time it begins
|
||||||
pub fn next_round(&mut self, on_image_available: @fn() -> ~fn(ImageResponseMsg)) {
|
pub fn next_round(&mut self, on_image_available: @fn() -> ~fn(ImageResponseMsg)) {
|
||||||
|
@ -76,7 +77,7 @@ pub impl LocalImageCache {
|
||||||
match state.last_response {
|
match state.last_response {
|
||||||
ImageReady(ref image) => {
|
ImageReady(ref image) => {
|
||||||
let (port, chan) = comm::stream();
|
let (port, chan) = comm::stream();
|
||||||
chan.send(ImageReady(clone_arc(image)));
|
chan.send(ImageReady(image.clone()));
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
ImageNotReady => {
|
ImageNotReady => {
|
||||||
|
@ -122,7 +123,7 @@ pub impl LocalImageCache {
|
||||||
|
|
||||||
// Put a copy of the response in the cache
|
// Put a copy of the response in the cache
|
||||||
let response_copy = match response {
|
let response_copy = match response {
|
||||||
ImageReady(ref image) => ImageReady(clone_arc(image)),
|
ImageReady(ref image) => ImageReady(image.clone()),
|
||||||
ImageNotReady => ImageNotReady,
|
ImageNotReady => ImageNotReady,
|
||||||
ImageFailed => ImageFailed
|
ImageFailed => ImageFailed
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ extern mod geom;
|
||||||
extern mod http_client;
|
extern mod http_client;
|
||||||
extern mod servo_util (name = "util");
|
extern mod servo_util (name = "util");
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod std;
|
extern mod extra;
|
||||||
|
|
||||||
/// Image handling.
|
/// Image handling.
|
||||||
///
|
///
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
use file_loader;
|
use file_loader;
|
||||||
use http_loader;
|
use http_loader;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use std::comm::{Chan, Port, SharedChan};
|
||||||
use std::net::url::{Url, to_str};
|
use extra::net::url::{Url, to_str};
|
||||||
use util::spawn_listener;
|
use util::spawn_listener;
|
||||||
|
|
||||||
pub enum ControlMsg {
|
pub enum ControlMsg {
|
||||||
|
@ -52,7 +52,7 @@ pub fn ResourceTask() -> ResourceTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask {
|
fn create_resource_task_with_loaders(loaders: ~[(~str, LoaderTaskFactory)]) -> ResourceTask {
|
||||||
let loaders_cell = Cell(loaders);
|
let loaders_cell = Cell::new(loaders);
|
||||||
let chan = do spawn_listener |from_client| {
|
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, loaders_cell.take()).start()
|
ResourceManager(from_client, loaders_cell.take()).start()
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::comm::{Chan, Port};
|
use std::comm;
|
||||||
|
use std::comm::{Chan, Port};
|
||||||
|
use std::task;
|
||||||
|
|
||||||
pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
|
pub fn spawn_listener<A: Owned>(f: ~fn(Port<A>)) -> Chan<A> {
|
||||||
let (setup_port, setup_chan) = comm::stream();
|
let (setup_port, setup_chan) = comm::stream();
|
||||||
|
|
|
@ -8,9 +8,11 @@ use dom::clientrect::ClientRect;
|
||||||
use script_task::{task_from_context, global_script_context};
|
use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext, JSVal};
|
use js::jsapi::{JSObject, JSContext, JSVal};
|
||||||
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
|
|
||||||
pub impl ClientRect {
|
use std::cast;
|
||||||
|
|
||||||
|
impl ClientRect {
|
||||||
pub fn init_wrapper(@mut self) {
|
pub fn init_wrapper(@mut self) {
|
||||||
let script_context = global_script_context();
|
let script_context = global_script_context();
|
||||||
let cx = script_context.js_compartment.cx.ptr;
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
|
|
|
@ -9,8 +9,10 @@ use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
pub impl ClientRectList {
|
use std::cast;
|
||||||
fn init_wrapper(@mut self) {
|
|
||||||
|
impl ClientRectList {
|
||||||
|
pub fn init_wrapper(@mut self) {
|
||||||
let script_context = global_script_context();
|
let script_context = global_script_context();
|
||||||
let cx = script_context.js_compartment.cx.ptr;
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
let owner = script_context.root_frame.get_ref().window;
|
let owner = script_context.root_frame.get_ref().window;
|
||||||
|
|
|
@ -2853,7 +2853,7 @@ class CGCallGenerator(CGThing):
|
||||||
"""
|
"""
|
||||||
def __init__(self, errorReport, arguments, argsPre, returnType,
|
def __init__(self, errorReport, arguments, argsPre, returnType,
|
||||||
extendedAttributes, descriptorProvider, nativeMethodName,
|
extendedAttributes, descriptorProvider, nativeMethodName,
|
||||||
static, object="self", declareResult=True):
|
static, object="this", declareResult=True):
|
||||||
CGThing.__init__(self)
|
CGThing.__init__(self)
|
||||||
|
|
||||||
assert errorReport is None or isinstance(errorReport, CGThing)
|
assert errorReport is None or isinstance(errorReport, CGThing)
|
||||||
|
@ -3070,7 +3070,7 @@ class CGAbstractBindingMethod(CGAbstractExternMethod):
|
||||||
unwrapThis = CGIndenter(CGGeneric(
|
unwrapThis = CGIndenter(CGGeneric(
|
||||||
str(CastableObjectUnwrapper(
|
str(CastableObjectUnwrapper(
|
||||||
FakeCastableDescriptor(self.descriptor),
|
FakeCastableDescriptor(self.descriptor),
|
||||||
"obj", "self", self.unwrapFailureCode))))
|
"obj", "this", self.unwrapFailureCode))))
|
||||||
return CGList([ self.getThis(), unwrapThis,
|
return CGList([ self.getThis(), unwrapThis,
|
||||||
self.generate_code() ], "\n").define()
|
self.generate_code() ], "\n").define()
|
||||||
|
|
||||||
|
@ -3081,7 +3081,7 @@ class CGAbstractBindingMethod(CGAbstractExternMethod):
|
||||||
" return false as JSBool;\n"
|
" return false as JSBool;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"let self: *rust_box<%s>;" % self.descriptor.nativeType))
|
"let this: *rust_box<%s>;" % self.descriptor.nativeType))
|
||||||
|
|
||||||
def generate_code(self):
|
def generate_code(self):
|
||||||
assert(False) # Override me
|
assert(False) # Override me
|
||||||
|
@ -3098,7 +3098,7 @@ class CGGenericMethod(CGAbstractBindingMethod):
|
||||||
def generate_code(self):
|
def generate_code(self):
|
||||||
return CGIndenter(CGGeneric(
|
return CGIndenter(CGGeneric(
|
||||||
"let _info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"let _info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"return CallJitMethodOp(_info, cx, obj, ptr::to_unsafe_ptr(&(*self).payload) as *libc::c_void, argc, vp);"))
|
"return CallJitMethodOp(_info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, argc, vp);"))
|
||||||
|
|
||||||
class CGAbstractStaticMethod(CGAbstractMethod):
|
class CGAbstractStaticMethod(CGAbstractMethod):
|
||||||
"""
|
"""
|
||||||
|
@ -3121,7 +3121,7 @@ class CGSpecializedMethod(CGAbstractExternMethod):
|
||||||
self.method = method
|
self.method = method
|
||||||
name = method.identifier.name
|
name = method.identifier.name
|
||||||
args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'),
|
args = [Argument('*JSContext', 'cx'), Argument('JSHandleObject', 'obj'),
|
||||||
Argument('*mut %s' % descriptor.nativeType, 'self'),
|
Argument('*mut %s' % descriptor.nativeType, 'this'),
|
||||||
Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')]
|
Argument('libc::c_uint', 'argc'), Argument('*mut JSVal', 'vp')]
|
||||||
CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args)
|
CGAbstractExternMethod.__init__(self, descriptor, name, 'JSBool', args)
|
||||||
|
|
||||||
|
@ -3154,7 +3154,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
||||||
def generate_code(self):
|
def generate_code(self):
|
||||||
return CGIndenter(CGGeneric(
|
return CGIndenter(CGGeneric(
|
||||||
"let _info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
"let _info: *JSJitInfo = RUST_FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
|
||||||
"return CallJitPropertyOp(_info, cx, obj, ptr::to_unsafe_ptr(&(*self).payload) as *libc::c_void, vp);"))
|
"return CallJitPropertyOp(_info, cx, obj, ptr::to_unsafe_ptr(&(*this).payload) as *libc::c_void, vp);"))
|
||||||
|
|
||||||
class CGSpecializedGetter(CGAbstractExternMethod):
|
class CGSpecializedGetter(CGAbstractExternMethod):
|
||||||
"""
|
"""
|
||||||
|
@ -3166,7 +3166,7 @@ class CGSpecializedGetter(CGAbstractExternMethod):
|
||||||
name = 'get_' + attr.identifier.name
|
name = 'get_' + attr.identifier.name
|
||||||
args = [ Argument('*JSContext', 'cx'),
|
args = [ Argument('*JSContext', 'cx'),
|
||||||
Argument('JSHandleObject', 'obj'),
|
Argument('JSHandleObject', 'obj'),
|
||||||
Argument('*%s' % descriptor.nativeType, 'self'),
|
Argument('*%s' % descriptor.nativeType, 'this'),
|
||||||
Argument('*mut JSVal', 'vp') ]
|
Argument('*mut JSVal', 'vp') ]
|
||||||
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
|
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
|
||||||
|
|
||||||
|
@ -3466,7 +3466,7 @@ if expando.is_not_null() {
|
||||||
getIndexedOrExpando = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
getIndexedOrExpando = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
"if index.is_some() {\n" +
|
"if index.is_some() {\n" +
|
||||||
" let index = index.get();\n" +
|
" let index = index.get();\n" +
|
||||||
" let self = UnwrapProxy(proxy);\n" +
|
" let this = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define())
|
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define())
|
||||||
getIndexedOrExpando += """
|
getIndexedOrExpando += """
|
||||||
// Even if we don't have this index, we don't forward the
|
// Even if we don't have this index, we don't forward the
|
||||||
|
@ -3488,7 +3488,7 @@ if expando.is_not_null() {
|
||||||
" return false;\n" +
|
" return false;\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" let self = UnwrapProxy(proxy);\n" +
|
" let this = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
|
||||||
"}\n") % (self.descriptor.nativeType)
|
"}\n") % (self.descriptor.nativeType)
|
||||||
else:
|
else:
|
||||||
|
@ -3558,7 +3558,7 @@ class CGAbstractClassHook(CGAbstractExternMethod):
|
||||||
def definition_body_prologue(self):
|
def definition_body_prologue(self):
|
||||||
return "" #XXXjdm we may want to do a proper unwrap here
|
return "" #XXXjdm we may want to do a proper unwrap here
|
||||||
return """
|
return """
|
||||||
let self: *%s = &(unwrap::<*rust_box<%s>>(obj).payload);
|
let this: *%s = &(unwrap::<*rust_box<%s>>(obj).payload);
|
||||||
""" % (self.descriptor.nativeType, self.descriptor.nativeType)
|
""" % (self.descriptor.nativeType, self.descriptor.nativeType)
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
|
@ -3570,8 +3570,8 @@ class CGAbstractClassHook(CGAbstractExternMethod):
|
||||||
|
|
||||||
def finalizeHook(descriptor, hookName, context):
|
def finalizeHook(descriptor, hookName, context):
|
||||||
if descriptor.customFinalize:
|
if descriptor.customFinalize:
|
||||||
return """if (self) {
|
return """if (this) {
|
||||||
self->%s(%s);
|
this->%s(%s);
|
||||||
}""" % (hookName, context)
|
}""" % (hookName, context)
|
||||||
#clearWrapper = "ClearWrapper(self, self);\n" if descriptor.wrapperCache else ""
|
#clearWrapper = "ClearWrapper(self, self);\n" if descriptor.wrapperCache else ""
|
||||||
if descriptor.workers:
|
if descriptor.workers:
|
||||||
|
@ -4132,9 +4132,7 @@ class CGBindingRoot(CGThing):
|
||||||
dictionaries,
|
dictionaries,
|
||||||
['js::*',
|
['js::*',
|
||||||
'js::jsapi::*',
|
'js::jsapi::*',
|
||||||
'js::jsapi::bindgen::*',
|
|
||||||
'js::jsfriendapi::bindgen::*',
|
'js::jsfriendapi::bindgen::*',
|
||||||
'js::glue::bindgen::*',
|
|
||||||
'js::glue::*',
|
'js::glue::*',
|
||||||
'dom::node::AbstractNode', #XXXjdm
|
'dom::node::AbstractNode', #XXXjdm
|
||||||
'dom::document::Document', #XXXjdm
|
'dom::document::Document', #XXXjdm
|
||||||
|
@ -4150,6 +4148,11 @@ class CGBindingRoot(CGThing):
|
||||||
'script_task::task_from_context',
|
'script_task::task_from_context',
|
||||||
'dom::bindings::utils::EnumEntry',
|
'dom::bindings::utils::EnumEntry',
|
||||||
'dom::node::ScriptView',
|
'dom::node::ScriptView',
|
||||||
|
'std::cast',
|
||||||
|
'std::libc',
|
||||||
|
'std::ptr',
|
||||||
|
'std::vec',
|
||||||
|
'std::str'
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
curr)
|
curr)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use js::jsapi::JSVal;
|
use js::jsapi::JSVal;
|
||||||
use js::{JSVAL_FALSE, JSVAL_TRUE};
|
use js::{JSVAL_FALSE, JSVAL_TRUE};
|
||||||
use js::glue::bindgen::{RUST_UINT_TO_JSVAL, RUST_JSVAL_TO_INT};
|
use js::glue::{RUST_UINT_TO_JSVAL, RUST_JSVAL_TO_INT};
|
||||||
|
|
||||||
pub trait JSValConvertible {
|
pub trait JSValConvertible {
|
||||||
fn to_jsval(&self) -> JSVal;
|
fn to_jsval(&self) -> JSVal;
|
||||||
|
@ -13,11 +13,15 @@ pub trait JSValConvertible {
|
||||||
|
|
||||||
impl JSValConvertible for u32 {
|
impl JSValConvertible for u32 {
|
||||||
fn to_jsval(&self) -> JSVal {
|
fn to_jsval(&self) -> JSVal {
|
||||||
RUST_UINT_TO_JSVAL(*self)
|
unsafe {
|
||||||
|
RUST_UINT_TO_JSVAL(*self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_jsval(val: JSVal) -> Option<u32> {
|
fn from_jsval(val: JSVal) -> Option<u32> {
|
||||||
Some(RUST_JSVAL_TO_INT(val) as u32)
|
unsafe {
|
||||||
|
Some(RUST_JSVAL_TO_INT(val) as u32)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,21 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
use std::libc;
|
||||||
|
use std::ptr;
|
||||||
|
use std::result;
|
||||||
|
use std::vec;
|
||||||
use dom::bindings::utils::{DOMString, rust_box, squirrel_away, str};
|
use dom::bindings::utils::{DOMString, rust_box, squirrel_away, str};
|
||||||
use dom::bindings::utils::{WrapperCache, DerivedWrapper};
|
use dom::bindings::utils::{WrapperCache, DerivedWrapper};
|
||||||
use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper};
|
use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper};
|
||||||
use dom::bindings::utils;
|
use dom::bindings::utils;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::htmlcollection::HTMLCollection;
|
use dom::htmlcollection::HTMLCollection;
|
||||||
use js::glue::bindgen::*;
|
use js::glue::*;
|
||||||
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB};
|
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB};
|
||||||
use js::jsapi::bindgen::{JS_DefineProperties};
|
use js::jsapi::{JS_DefineProperties};
|
||||||
use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot, JS_DefineFunctions};
|
use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot, JS_DefineFunctions};
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec, JSPropertyOpWrapper};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec, JSPropertyOpWrapper};
|
||||||
use js::jsapi::{JSStrictPropertyOpWrapper, JSNativeWrapper, JSFunctionSpec};
|
use js::jsapi::{JSStrictPropertyOpWrapper, JSNativeWrapper, JSFunctionSpec};
|
||||||
use js::rust::{Compartment, jsobj};
|
use js::rust::{Compartment, jsobj};
|
||||||
|
@ -19,8 +24,8 @@ use js::{JSPROP_NATIVE_ACCESSORS};
|
||||||
use js::{JS_ARGV, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL};
|
use js::{JS_ARGV, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL};
|
||||||
use script_task::task_from_context;
|
use script_task::task_from_context;
|
||||||
|
|
||||||
use core::libc::c_uint;
|
use std::libc::c_uint;
|
||||||
use core::ptr::null;
|
use std::ptr::null;
|
||||||
|
|
||||||
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -96,9 +101,11 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
|
flags: (JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS) as u8,
|
||||||
getter: JSPropertyOpWrapper {op: null(), info: null()},
|
getter: JSPropertyOpWrapper {op: null(), info: null()},
|
||||||
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
||||||
vec::push(&mut compartment.global_props, attrs);
|
compartment.global_props.push(attrs);
|
||||||
vec::as_imm_buf(*attrs, |specs, _len| {
|
vec::as_imm_buf(*attrs, |specs, _len| {
|
||||||
assert!(JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs) == 1);
|
unsafe {
|
||||||
|
assert!(JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs) == 1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getElementsByTagName"),
|
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getElementsByTagName"),
|
||||||
|
@ -112,7 +119,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
flags: 0,
|
flags: 0,
|
||||||
selfHostedName: null()}];
|
selfHostedName: null()}];
|
||||||
vec::as_imm_buf(*methods, |fns, _len| {
|
vec::as_imm_buf(*methods, |fns, _len| {
|
||||||
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
|
unsafe {
|
||||||
|
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
compartment.register_class(utils::instance_jsclass(~"DocumentInstance",
|
compartment.register_class(utils::instance_jsclass(~"DocumentInstance",
|
||||||
|
@ -129,12 +138,12 @@ pub fn create(compartment: @mut Compartment, doc: @mut Document) -> *JSObject {
|
||||||
unsafe {
|
unsafe {
|
||||||
let raw_ptr: *libc::c_void = cast::transmute(squirrel_away(doc));
|
let raw_ptr: *libc::c_void = cast::transmute(squirrel_away(doc));
|
||||||
JS_SetReservedSlot(instance.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
JS_SetReservedSlot(instance.ptr, 0, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
||||||
}
|
|
||||||
|
|
||||||
compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(instance.ptr),
|
compartment.define_property(~"document", RUST_OBJECT_TO_JSVAL(instance.ptr),
|
||||||
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
||||||
JSPROP_ENUMERATE);
|
JSPROP_ENUMERATE);
|
||||||
|
}
|
||||||
|
|
||||||
instance.ptr
|
instance.ptr
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@ use dom::bindings::utils::{BindingObject, DerivedWrapper};
|
||||||
use dom::domparser::DOMParser;
|
use dom::domparser::DOMParser;
|
||||||
|
|
||||||
use js::jsapi::{JSContext, JSObject, JSVal};
|
use js::jsapi::{JSContext, JSObject, JSVal};
|
||||||
use js::glue::bindgen::{RUST_OBJECT_TO_JSVAL};
|
use js::glue::{RUST_OBJECT_TO_JSVAL};
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
|
||||||
impl CacheableWrapper for DOMParser {
|
impl CacheableWrapper for DOMParser {
|
||||||
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
||||||
|
|
|
@ -12,10 +12,17 @@ use layout_interface::{ContentBoxQuery, ContentBoxResponse};
|
||||||
use script_task::task_from_context;
|
use script_task::task_from_context;
|
||||||
use super::utils;
|
use super::utils;
|
||||||
|
|
||||||
use core::libc::c_uint;
|
use std::cast;
|
||||||
use core::ptr::null;
|
use std::i32;
|
||||||
use js::glue::bindgen::*;
|
use std::libc;
|
||||||
use js::jsapi::bindgen::*;
|
use std::libc::c_uint;
|
||||||
|
use std::ptr;
|
||||||
|
use std::ptr::null;
|
||||||
|
use std::result;
|
||||||
|
use std::str;
|
||||||
|
use std::vec;
|
||||||
|
use js::glue::*;
|
||||||
|
use js::jsapi::*;
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
|
||||||
use js::jsapi::{JSNativeWrapper, JSTracer, JSTRACE_OBJECT};
|
use js::jsapi::{JSNativeWrapper, JSTracer, JSTRACE_OBJECT};
|
||||||
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSFunctionSpec};
|
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSFunctionSpec};
|
||||||
|
@ -78,7 +85,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
||||||
vec::push(&mut compartment.global_props, attrs);
|
vec::push(&mut compartment.global_props, attrs);
|
||||||
vec::as_imm_buf(*attrs, |specs, _len| {
|
vec::as_imm_buf(*attrs, |specs, _len| {
|
||||||
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
unsafe {
|
||||||
|
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getClientRects"),
|
let methods = @~[JSFunctionSpec {name: compartment.add_name(~"getClientRects"),
|
||||||
|
@ -102,7 +111,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
flags: 0,
|
flags: 0,
|
||||||
selfHostedName: null()}];
|
selfHostedName: null()}];
|
||||||
vec::as_imm_buf(*methods, |fns, _len| {
|
vec::as_imm_buf(*methods, |fns, _len| {
|
||||||
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
|
unsafe {
|
||||||
|
JS_DefineFunctions(compartment.cx.ptr, obj.ptr, fns);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
compartment.register_class(utils::instance_jsclass(~"GenericElementInstance",
|
compartment.register_class(utils::instance_jsclass(~"GenericElementInstance",
|
||||||
|
@ -127,7 +138,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
||||||
vec::push(&mut compartment.global_props, attrs);
|
vec::push(&mut compartment.global_props, attrs);
|
||||||
vec::as_imm_buf(*attrs, |specs, _len| {
|
vec::as_imm_buf(*attrs, |specs, _len| {
|
||||||
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
unsafe {
|
||||||
|
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,8 +312,10 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
|
||||||
assert!(cache.get_wrapper().is_null());
|
assert!(cache.get_wrapper().is_null());
|
||||||
cache.set_wrapper(obj.ptr);
|
cache.set_wrapper(obj.ptr);
|
||||||
|
|
||||||
let raw_ptr = node.raw_object() as *libc::c_void;
|
unsafe {
|
||||||
JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
let raw_ptr = node.raw_object() as *libc::c_void;
|
||||||
|
JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
use dom::bindings::codegen::EventBinding;
|
use dom::bindings::codegen::EventBinding;
|
||||||
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
|
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
|
||||||
use dom::event::Event_;
|
use dom::event::Event_;
|
||||||
use script_task::{task_from_context, global_script_context};
|
use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
use js::jsapi::{JSObject, JSContext, JSVal};
|
use js::jsapi::{JSObject, JSContext, JSVal};
|
||||||
|
|
||||||
pub impl Event_ {
|
impl Event_ {
|
||||||
pub fn init_wrapper(@mut self) {
|
pub fn init_wrapper(@mut self) {
|
||||||
let script_context = global_script_context();
|
let script_context = global_script_context();
|
||||||
let cx = script_context.js_compartment.cx.ptr;
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
use dom::bindings::codegen::EventTargetBinding;
|
use dom::bindings::codegen::EventTargetBinding;
|
||||||
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
|
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use script_task::{task_from_context, global_script_context};
|
use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
use js::jsapi::{JSObject, JSContext, JSVal};
|
use js::jsapi::{JSObject, JSContext, JSVal};
|
||||||
|
|
||||||
pub impl EventTarget {
|
impl EventTarget {
|
||||||
pub fn init_wrapper(@mut self) {
|
pub fn init_wrapper(@mut self) {
|
||||||
let script_context = global_script_context();
|
let script_context = global_script_context();
|
||||||
let cx = script_context.js_compartment.cx.ptr;
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
|
|
|
@ -9,8 +9,10 @@ use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
pub impl HTMLCollection {
|
use std::cast;
|
||||||
fn init_wrapper(@mut self) {
|
|
||||||
|
impl HTMLCollection {
|
||||||
|
pub fn init_wrapper(@mut self) {
|
||||||
let script_context = global_script_context();
|
let script_context = global_script_context();
|
||||||
let cx = script_context.js_compartment.cx.ptr;
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
let owner = script_context.root_frame.get_ref().window;
|
let owner = script_context.root_frame.get_ref().window;
|
||||||
|
|
|
@ -9,9 +9,12 @@ use dom::bindings::utils::{CacheableWrapper, WrapperCache, DerivedWrapper};
|
||||||
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
|
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
|
||||||
use dom::node::{DoctypeNodeTypeId, ScriptView};
|
use dom::node::{DoctypeNodeTypeId, ScriptView};
|
||||||
|
|
||||||
use core::libc::c_uint;
|
use std::cast;
|
||||||
use core::ptr::null;
|
use std::libc::c_uint;
|
||||||
use js::jsapi::bindgen::*;
|
use std::ptr;
|
||||||
|
use std::ptr::null;
|
||||||
|
use std::vec;
|
||||||
|
use js::jsapi::*;
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSPropertySpec};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSPropertySpec};
|
||||||
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper};
|
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper};
|
||||||
use js::jsval::{INT_TO_JSVAL};
|
use js::jsval::{INT_TO_JSVAL};
|
||||||
|
@ -53,7 +56,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
setter: JSStrictPropertyOpWrapper {op: null(), info: null()}}];
|
||||||
vec::push(&mut compartment.global_props, attrs);
|
vec::push(&mut compartment.global_props, attrs);
|
||||||
vec::as_imm_buf(*attrs, |specs, _len| {
|
vec::as_imm_buf(*attrs, |specs, _len| {
|
||||||
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
unsafe {
|
||||||
|
JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,15 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
|
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString, jschar};
|
||||||
use js::jsapi::bindgen::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
|
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
|
||||||
use js::glue::bindgen::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra};
|
use js::glue::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra};
|
||||||
use js::glue::bindgen::{GetObjectProto};
|
use js::glue::{GetObjectProto};
|
||||||
|
|
||||||
use core::sys::size_of;
|
use std::cast;
|
||||||
|
use std::libc;
|
||||||
|
use std::ptr;
|
||||||
|
use std::str;
|
||||||
|
use std::sys::size_of;
|
||||||
|
|
||||||
type c_bool = libc::c_int;
|
type c_bool = libc::c_int;
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = ~"[object " + name + ~"]";
|
let result = ~"[object " + name + ~"]";
|
||||||
for result.each_chari |i, c| {
|
for result.iter().enumerate().advance |(i, c)| {
|
||||||
*chars.offset(i) = c as jschar;
|
*chars.offset(i) = c as jschar;
|
||||||
}
|
}
|
||||||
*chars.offset(nchars) = 0;
|
*chars.offset(nchars) = 0;
|
||||||
|
|
|
@ -10,10 +10,14 @@ use dom::node::{AbstractNode, Text, Comment, Doctype, TextNodeTypeId, CommentNod
|
||||||
use dom::node::{DoctypeNodeTypeId, ScriptView};
|
use dom::node::{DoctypeNodeTypeId, ScriptView};
|
||||||
|
|
||||||
use js::jsapi::{JSFreeOp, JSObject, JSContext};
|
use js::jsapi::{JSFreeOp, JSObject, JSContext};
|
||||||
use js::jsapi::bindgen::{JS_SetReservedSlot};
|
use js::jsapi::{JS_SetReservedSlot};
|
||||||
use js::glue::bindgen::{RUST_PRIVATE_TO_JSVAL};
|
use js::glue::{RUST_PRIVATE_TO_JSVAL};
|
||||||
use js::rust::{Compartment, jsobj};
|
use js::rust::{Compartment, jsobj};
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
use std::libc;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("text finalize: %?!", obj as uint);
|
debug!("text finalize: %?!", obj as uint);
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -83,8 +87,10 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
|
||||||
assert!(cache.get_wrapper().is_null());
|
assert!(cache.get_wrapper().is_null());
|
||||||
cache.set_wrapper(obj.ptr);
|
cache.set_wrapper(obj.ptr);
|
||||||
|
|
||||||
let raw_ptr = node.raw_object() as *libc::c_void;
|
unsafe {
|
||||||
JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
let raw_ptr = node.raw_object() as *libc::c_void;
|
||||||
|
JS_SetReservedSlot(obj.ptr, DOM_OBJECT_SLOT as u32, RUST_PRIVATE_TO_JSVAL(raw_ptr));
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,26 @@ use dom::bindings::node;
|
||||||
use dom::node::{AbstractNode, ScriptView};
|
use dom::node::{AbstractNode, ScriptView};
|
||||||
use script_task::task_from_context;
|
use script_task::task_from_context;
|
||||||
|
|
||||||
use core::cast;
|
use std::cast;
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use core::ptr::{null, to_unsafe_ptr};
|
use std::libc;
|
||||||
use js::glue::bindgen::*;
|
use std::ptr;
|
||||||
use js::glue::bindgen::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
use std::ptr::{null, to_unsafe_ptr};
|
||||||
|
use std::result;
|
||||||
|
use std::str;
|
||||||
|
use std::sys;
|
||||||
|
use std::uint;
|
||||||
|
use js::glue::*;
|
||||||
|
use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
||||||
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
|
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB, RESOLVE_STUB};
|
||||||
use js::jsapi::bindgen::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction};
|
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction};
|
||||||
use js::jsapi::bindgen::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
|
use js::jsapi::{JS_DefineProperties, JS_WrapValue, JS_ForwardGetPropertyTo};
|
||||||
use js::jsapi::bindgen::{JS_EncodeString, JS_free, JS_GetStringCharsAndLength};
|
use js::jsapi::{JS_EncodeString, JS_free, JS_GetStringCharsAndLength};
|
||||||
use js::jsapi::bindgen::{JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype};
|
use js::jsapi::{JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype};
|
||||||
use js::jsapi::bindgen::{JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject};
|
use js::jsapi::{JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject};
|
||||||
use js::jsapi::bindgen::{JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject};
|
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject};
|
||||||
use js::jsapi::bindgen::{JS_NewStringCopyN, JS_DefineFunctions, JS_DefineProperty};
|
use js::jsapi::{JS_NewStringCopyN, JS_DefineFunctions, JS_DefineProperty};
|
||||||
use js::jsapi::bindgen::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot};
|
use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot};
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSNative};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSNative};
|
||||||
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
|
use js::jsapi::{JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
|
||||||
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
|
||||||
|
@ -88,8 +94,8 @@ pub enum DOMString {
|
||||||
null_string
|
null_string
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl DOMString {
|
impl DOMString {
|
||||||
fn to_str(&self) -> ~str {
|
pub fn to_str(&self) -> ~str {
|
||||||
match *self {
|
match *self {
|
||||||
str(ref s) => s.clone(),
|
str(ref s) => s.clone(),
|
||||||
null_string => ~""
|
null_string => ~""
|
||||||
|
@ -129,17 +135,17 @@ pub unsafe fn squirrel_away<T>(x: @mut T) -> *rust_box<T> {
|
||||||
|
|
||||||
//XXX very incomplete
|
//XXX very incomplete
|
||||||
pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
|
pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
|
||||||
let jsstr;
|
|
||||||
if RUST_JSVAL_IS_STRING(v) == 1 {
|
|
||||||
jsstr = RUST_JSVAL_TO_STRING(v)
|
|
||||||
} else {
|
|
||||||
jsstr = JS_ValueToString(cx, v);
|
|
||||||
if jsstr.is_null() {
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let jsstr;
|
||||||
|
if RUST_JSVAL_IS_STRING(v) == 1 {
|
||||||
|
jsstr = RUST_JSVAL_TO_STRING(v)
|
||||||
|
} else {
|
||||||
|
jsstr = JS_ValueToString(cx, v);
|
||||||
|
if jsstr.is_null() {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let strbuf = JS_EncodeString(cx, jsstr);
|
let strbuf = JS_EncodeString(cx, jsstr);
|
||||||
let buf = str::raw::from_buf(strbuf as *u8);
|
let buf = str::raw::from_buf(strbuf as *u8);
|
||||||
JS_free(cx, strbuf as *libc::c_void);
|
JS_free(cx, strbuf as *libc::c_void);
|
||||||
|
@ -172,45 +178,49 @@ pub fn get_compartment(cx: *JSContext) -> @mut Compartment {
|
||||||
|
|
||||||
extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSBool) -> JSBool {
|
extern fn has_instance(_cx: *JSContext, obj: **JSObject, v: *JSVal, bp: *mut JSBool) -> JSBool {
|
||||||
//XXXjdm this is totally broken for non-object values
|
//XXXjdm this is totally broken for non-object values
|
||||||
let mut o = RUST_JSVAL_TO_OBJECT(unsafe {*v});
|
unsafe {
|
||||||
let obj = unsafe {*obj};
|
let mut o = RUST_JSVAL_TO_OBJECT(unsafe {*v});
|
||||||
unsafe { *bp = 0; }
|
let obj = unsafe {*obj};
|
||||||
while o.is_not_null() {
|
unsafe { *bp = 0; }
|
||||||
if o == obj {
|
while o.is_not_null() {
|
||||||
unsafe { *bp = 1; }
|
if o == obj {
|
||||||
break;
|
unsafe { *bp = 1; }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
o = JS_GetPrototype(o);
|
||||||
}
|
}
|
||||||
o = JS_GetPrototype(o);
|
return 1;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
|
pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JSClass {
|
||||||
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
|
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
|
||||||
JSClass {
|
unsafe {
|
||||||
name: compartment.add_name(copy name),
|
JSClass {
|
||||||
flags: 0,
|
name: compartment.add_name(copy name),
|
||||||
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
flags: 0,
|
||||||
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
|
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
||||||
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
|
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
|
||||||
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
|
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
|
||||||
finalize: null(),
|
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
|
||||||
checkAccess: null(),
|
finalize: null(),
|
||||||
call: null(),
|
checkAccess: null(),
|
||||||
hasInstance: has_instance,
|
call: null(),
|
||||||
construct: null(),
|
hasInstance: has_instance,
|
||||||
trace: null(),
|
construct: null(),
|
||||||
reserved: (null(), null(), null(), null(), null(), // 05
|
trace: null(),
|
||||||
null(), null(), null(), null(), null(), // 10
|
reserved: (null(), null(), null(), null(), null(), // 05
|
||||||
null(), null(), null(), null(), null(), // 15
|
null(), null(), null(), null(), null(), // 10
|
||||||
null(), null(), null(), null(), null(), // 20
|
null(), null(), null(), null(), null(), // 15
|
||||||
null(), null(), null(), null(), null(), // 25
|
null(), null(), null(), null(), null(), // 20
|
||||||
null(), null(), null(), null(), null(), // 30
|
null(), null(), null(), null(), null(), // 25
|
||||||
null(), null(), null(), null(), null(), // 35
|
null(), null(), null(), null(), null(), // 30
|
||||||
null(), null(), null(), null(), null()) // 40
|
null(), null(), null(), null(), null(), // 35
|
||||||
|
null(), null(), null(), null(), null()) // 40
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return f;
|
return f;
|
||||||
|
@ -219,30 +229,32 @@ pub fn prototype_jsclass(name: ~str) -> @fn(compartment: @mut Compartment) -> JS
|
||||||
pub fn instance_jsclass(name: ~str, finalize: *u8, trace: *u8)
|
pub fn instance_jsclass(name: ~str, finalize: *u8, trace: *u8)
|
||||||
-> @fn(compartment: @mut Compartment) -> JSClass {
|
-> @fn(compartment: @mut Compartment) -> JSClass {
|
||||||
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
|
let f: @fn(@mut Compartment) -> JSClass = |compartment: @mut Compartment| {
|
||||||
JSClass {
|
unsafe {
|
||||||
name: compartment.add_name(copy name),
|
JSClass {
|
||||||
flags: JSCLASS_HAS_RESERVED_SLOTS(1) | js::JSCLASS_IS_DOMJSCLASS,
|
name: compartment.add_name(copy name),
|
||||||
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
flags: JSCLASS_HAS_RESERVED_SLOTS(1) | js::JSCLASS_IS_DOMJSCLASS,
|
||||||
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
addProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
delProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
getProperty: GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
|
setProperty: GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
||||||
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
|
enumerate: GetJSClassHookStubPointer(ENUMERATE_STUB) as *u8,
|
||||||
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
|
resolve: GetJSClassHookStubPointer(RESOLVE_STUB) as *u8,
|
||||||
finalize: finalize,
|
convert: GetJSClassHookStubPointer(CONVERT_STUB) as *u8,
|
||||||
checkAccess: null(),
|
finalize: finalize,
|
||||||
call: null(),
|
checkAccess: null(),
|
||||||
hasInstance: has_instance,
|
call: null(),
|
||||||
construct: null(),
|
hasInstance: has_instance,
|
||||||
trace: trace,
|
construct: null(),
|
||||||
reserved: (null(), null(), null(), null(), null(), // 05
|
trace: trace,
|
||||||
null(), null(), null(), null(), null(), // 10
|
reserved: (null(), null(), null(), null(), null(), // 05
|
||||||
null(), null(), null(), null(), null(), // 15
|
null(), null(), null(), null(), null(), // 10
|
||||||
null(), null(), null(), null(), null(), // 20
|
null(), null(), null(), null(), null(), // 15
|
||||||
null(), null(), null(), null(), null(), // 25
|
null(), null(), null(), null(), null(), // 20
|
||||||
null(), null(), null(), null(), null(), // 30
|
null(), null(), null(), null(), null(), // 25
|
||||||
null(), null(), null(), null(), null(), // 35
|
null(), null(), null(), null(), null(), // 30
|
||||||
null(), null(), null(), null(), null()) // 40
|
null(), null(), null(), null(), null(), // 35
|
||||||
|
null(), null(), null(), null(), null()) // 40
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return f;
|
return f;
|
||||||
|
@ -262,12 +274,14 @@ pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut
|
||||||
None => compartment.new_object(copy name, null(), compartment.global_obj.ptr)
|
None => compartment.new_object(copy name, null(), compartment.global_obj.ptr)
|
||||||
});
|
});
|
||||||
|
|
||||||
compartment.define_property(copy name, RUST_OBJECT_TO_JSVAL(obj.ptr),
|
unsafe {
|
||||||
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
compartment.define_property(copy name, RUST_OBJECT_TO_JSVAL(obj.ptr),
|
||||||
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
GetJSClassHookStubPointer(PROPERTY_STUB) as *u8,
|
||||||
JSPROP_ENUMERATE);
|
GetJSClassHookStubPointer(STRICT_PROPERTY_STUB) as *u8,
|
||||||
compartment.stash_global_proto(name, obj);
|
JSPROP_ENUMERATE);
|
||||||
return obj;
|
compartment.stash_global_proto(name, obj);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use slot 0 for holding the raw object. This is safe for both
|
// We use slot 0 for holding the raw object. This is safe for both
|
||||||
|
@ -390,8 +404,10 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
|
unsafe {
|
||||||
RUST_PRIVATE_TO_JSVAL(domClass as *libc::c_void));
|
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
|
||||||
|
RUST_PRIVATE_TO_JSVAL(domClass as *libc::c_void));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut interface = ptr::null();
|
let mut interface = ptr::null();
|
||||||
|
@ -419,75 +435,77 @@ fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject,
|
||||||
staticMethods: *JSFunctionSpec,
|
staticMethods: *JSFunctionSpec,
|
||||||
constants: *ConstantSpec,
|
constants: *ConstantSpec,
|
||||||
name: *libc::c_char) -> *JSObject {
|
name: *libc::c_char) -> *JSObject {
|
||||||
let constructor = if constructorClass.is_not_null() {
|
unsafe {
|
||||||
let functionProto = JS_GetFunctionPrototype(cx, global);
|
let constructor = if constructorClass.is_not_null() {
|
||||||
if functionProto.is_null() {
|
let functionProto = JS_GetFunctionPrototype(cx, global);
|
||||||
ptr::null()
|
if functionProto.is_null() {
|
||||||
|
ptr::null()
|
||||||
|
} else {
|
||||||
|
JS_NewObject(cx, constructorClass, functionProto, global)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
JS_NewObject(cx, constructorClass, functionProto, global)
|
assert!(constructorNative.is_not_null());
|
||||||
}
|
let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
|
||||||
} else {
|
JSFUN_CONSTRUCTOR, global, name);
|
||||||
assert!(constructorNative.is_not_null());
|
if fun.is_null() {
|
||||||
let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
|
ptr::null()
|
||||||
JSFUN_CONSTRUCTOR, global, name);
|
} else {
|
||||||
if fun.is_null() {
|
JS_GetFunctionObject(fun)
|
||||||
ptr::null()
|
}
|
||||||
} else {
|
|
||||||
JS_GetFunctionObject(fun)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if constructor.is_null() {
|
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
if staticMethods.is_not_null() &&
|
|
||||||
!DefineMethods(cx, constructor, staticMethods) {
|
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
if constructorClass.is_not_null() {
|
|
||||||
let toString = do str::as_c_str("toString") |s| {
|
|
||||||
DefineFunctionWithReserved(cx, constructor, s,
|
|
||||||
InterfaceObjectToString,
|
|
||||||
0, 0)
|
|
||||||
};
|
};
|
||||||
if toString.is_null() {
|
|
||||||
|
if constructor.is_null() {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
let toStringObj = JS_GetFunctionObject(toString);
|
if staticMethods.is_not_null() &&
|
||||||
SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
|
!DefineMethods(cx, constructor, staticMethods) {
|
||||||
&RUST_PRIVATE_TO_JSVAL(constructorClass as *libc::c_void));
|
|
||||||
let s = JS_InternString(cx, name);
|
|
||||||
if s.is_null() {
|
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
|
|
||||||
&RUST_STRING_TO_JSVAL(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
if constants.is_not_null() &&
|
if constructorClass.is_not_null() {
|
||||||
!DefineConstants(cx, constructor, constants) {
|
let toString = do str::as_c_str("toString") |s| {
|
||||||
return ptr::null();
|
DefineFunctionWithReserved(cx, constructor, s,
|
||||||
}
|
InterfaceObjectToString,
|
||||||
|
0, 0)
|
||||||
|
};
|
||||||
|
if toString.is_null() {
|
||||||
|
return ptr::null();
|
||||||
|
}
|
||||||
|
|
||||||
if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
|
let toStringObj = JS_GetFunctionObject(toString);
|
||||||
return ptr::null();
|
SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
|
||||||
}
|
&RUST_PRIVATE_TO_JSVAL(constructorClass as *libc::c_void));
|
||||||
|
let s = JS_InternString(cx, name);
|
||||||
|
if s.is_null() {
|
||||||
|
return ptr::null();
|
||||||
|
}
|
||||||
|
SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
|
||||||
|
&RUST_STRING_TO_JSVAL(s));
|
||||||
|
}
|
||||||
|
|
||||||
let alreadyDefined = 0;
|
if constants.is_not_null() &&
|
||||||
if JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined) == 0 {
|
!DefineConstants(cx, constructor, constants) {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if alreadyDefined == 0 &&
|
if proto.is_not_null() && JS_LinkConstructorAndPrototype(cx, constructor, proto) == 0 {
|
||||||
JS_DefineProperty(cx, receiver, name, RUST_OBJECT_TO_JSVAL(constructor),
|
return ptr::null();
|
||||||
ptr::null(), ptr::null(), 0) == 0 {
|
}
|
||||||
return ptr::null();
|
|
||||||
}
|
|
||||||
|
|
||||||
return constructor;
|
let alreadyDefined = 0;
|
||||||
|
if JS_AlreadyHasOwnProperty(cx, receiver, name, &alreadyDefined) == 0 {
|
||||||
|
return ptr::null();
|
||||||
|
}
|
||||||
|
|
||||||
|
if alreadyDefined == 0 &&
|
||||||
|
JS_DefineProperty(cx, receiver, name, RUST_OBJECT_TO_JSVAL(constructor),
|
||||||
|
ptr::null(), ptr::null(), 0) == 0 {
|
||||||
|
return ptr::null();
|
||||||
|
}
|
||||||
|
|
||||||
|
return constructor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) -> bool {
|
fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) -> bool {
|
||||||
|
@ -520,11 +538,15 @@ fn DefineConstants(cx: *JSContext, obj: *JSObject, constants: *ConstantSpec) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineMethods(cx: *JSContext, obj: *JSObject, methods: *JSFunctionSpec) -> bool {
|
fn DefineMethods(cx: *JSContext, obj: *JSObject, methods: *JSFunctionSpec) -> bool {
|
||||||
JS_DefineFunctions(cx, obj, methods) != 0
|
unsafe {
|
||||||
|
JS_DefineFunctions(cx, obj, methods) != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefineProperties(cx: *JSContext, obj: *JSObject, properties: *JSPropertySpec) -> bool {
|
fn DefineProperties(cx: *JSContext, obj: *JSObject, properties: *JSPropertySpec) -> bool {
|
||||||
JS_DefineProperties(cx, obj, properties) != 0
|
unsafe {
|
||||||
|
JS_DefineProperties(cx, obj, properties) != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
|
fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
|
||||||
|
@ -532,24 +554,26 @@ fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
|
||||||
methods: *JSFunctionSpec,
|
methods: *JSFunctionSpec,
|
||||||
properties: *JSPropertySpec,
|
properties: *JSPropertySpec,
|
||||||
constants: *ConstantSpec) -> *JSObject {
|
constants: *ConstantSpec) -> *JSObject {
|
||||||
let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
|
unsafe {
|
||||||
if ourProto.is_null() {
|
let ourProto = JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global);
|
||||||
return ptr::null();
|
if ourProto.is_null() {
|
||||||
}
|
return ptr::null();
|
||||||
|
}
|
||||||
|
|
||||||
if methods.is_not_null() && !DefineMethods(cx, ourProto, methods) {
|
if methods.is_not_null() && !DefineMethods(cx, ourProto, methods) {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if properties.is_not_null() && !DefineProperties(cx, ourProto, properties) {
|
if properties.is_not_null() && !DefineProperties(cx, ourProto, properties) {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if constants.is_not_null() && !DefineConstants(cx, ourProto, constants) {
|
if constants.is_not_null() && !DefineConstants(cx, ourProto, constants) {
|
||||||
return ptr::null();
|
return ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ourProto;
|
return ourProto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) -> JSBool {
|
pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) -> JSBool {
|
||||||
|
@ -578,20 +602,20 @@ pub struct WrapperCache {
|
||||||
wrapper: *JSObject
|
wrapper: *JSObject
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl WrapperCache {
|
impl WrapperCache {
|
||||||
fn get_wrapper(&self) -> *JSObject {
|
pub fn get_wrapper(&self) -> *JSObject {
|
||||||
unsafe { cast::transmute(self.wrapper) }
|
unsafe { cast::transmute(self.wrapper) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_wrapper(&mut self, wrapper: *JSObject) {
|
pub fn set_wrapper(&mut self, wrapper: *JSObject) {
|
||||||
self.wrapper = wrapper;
|
self.wrapper = wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rootable(&self) -> **JSObject {
|
pub fn get_rootable(&self) -> **JSObject {
|
||||||
return to_unsafe_ptr(&self.wrapper);
|
return to_unsafe_ptr(&self.wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new() -> WrapperCache {
|
pub fn new() -> WrapperCache {
|
||||||
WrapperCache {
|
WrapperCache {
|
||||||
wrapper: ptr::null()
|
wrapper: ptr::null()
|
||||||
}
|
}
|
||||||
|
@ -660,10 +684,12 @@ pub fn GetPropertyOnPrototype(cx: *JSContext, proxy: *JSObject, id: jsid, found:
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetArrayIndexFromId(_cx: *JSContext, id: jsid) -> Option<u32> {
|
pub fn GetArrayIndexFromId(_cx: *JSContext, id: jsid) -> Option<u32> {
|
||||||
if RUST_JSID_IS_INT(id) != 0 {
|
unsafe {
|
||||||
return Some(RUST_JSID_TO_INT(id) as u32);
|
if RUST_JSID_IS_INT(id) != 0 {
|
||||||
|
return Some(RUST_JSID_TO_INT(id) as u32);
|
||||||
|
}
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
return None;
|
|
||||||
// if id is length atom, -1, otherwise
|
// if id is length atom, -1, otherwise
|
||||||
/*return if JSID_IS_ATOM(id) {
|
/*return if JSID_IS_ATOM(id) {
|
||||||
let atom = JSID_TO_ATOM(id);
|
let atom = JSID_TO_ATOM(id);
|
||||||
|
@ -730,11 +756,13 @@ pub fn XrayResolveProperty(cx: *JSContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn InternJSString(cx: *JSContext, chars: *libc::c_char) -> Option<jsid> {
|
fn InternJSString(cx: *JSContext, chars: *libc::c_char) -> Option<jsid> {
|
||||||
let s = JS_InternString(cx, chars);
|
unsafe {
|
||||||
if s.is_not_null() {
|
let s = JS_InternString(cx, chars);
|
||||||
Some(RUST_INTERNED_STRING_TO_JSID(cx, s))
|
if s.is_not_null() {
|
||||||
} else {
|
Some(RUST_INTERNED_STRING_TO_JSID(cx, s))
|
||||||
None
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,19 @@ use dom::bindings::utils::{WrapperCache};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use super::utils;
|
use super::utils;
|
||||||
|
|
||||||
use core::libc::c_uint;
|
use std::cast;
|
||||||
use core::ptr::null;
|
use std::libc;
|
||||||
use core::ptr;
|
use std::libc::c_uint;
|
||||||
|
use std::ptr::null;
|
||||||
|
use std::ptr;
|
||||||
|
use std::result;
|
||||||
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub};
|
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub};
|
||||||
use js::global::jsval_to_rust_str;
|
use js::global::jsval_to_rust_str;
|
||||||
use js::glue::bindgen::*;
|
use js::glue::*;
|
||||||
use js::glue::bindgen::RUST_JSVAL_TO_INT;
|
use js::glue::RUST_JSVAL_TO_INT;
|
||||||
use js::jsapi::bindgen::{JS_DefineFunctions, JS_GC, JS_GetRuntime};
|
use js::jsapi::{JS_DefineFunctions, JS_GC, JS_GetRuntime};
|
||||||
use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot};
|
use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot};
|
||||||
use js::jsapi::bindgen::{JS_ValueToString};
|
use js::jsapi::{JS_ValueToString};
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSFunctionSpec};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSFunctionSpec};
|
||||||
use js::jsapi::{JSNativeWrapper};
|
use js::jsapi::{JSNativeWrapper};
|
||||||
use js::rust::Compartment;
|
use js::rust::Compartment;
|
||||||
|
@ -67,9 +70,11 @@ extern fn close(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn gc(cx: *JSContext, _argc: c_uint, _vp: *JSVal) -> JSBool {
|
extern fn gc(cx: *JSContext, _argc: c_uint, _vp: *JSVal) -> JSBool {
|
||||||
let runtime = JS_GetRuntime(cx);
|
unsafe {
|
||||||
JS_GC(runtime);
|
let runtime = JS_GetRuntime(cx);
|
||||||
return 1;
|
JS_GC(runtime);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
|
unsafe fn unwrap(obj: *JSObject) -> *rust_box<Window> {
|
||||||
|
@ -128,7 +133,9 @@ pub fn init(compartment: @mut Compartment) {
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
JS_DefineFunctions(compartment.cx.ptr, proto.ptr, &methods[0]);
|
unsafe {
|
||||||
|
JS_DefineFunctions(compartment.cx.ptr, proto.ptr, &methods[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(compartment: @mut Compartment, win: @mut Window) {
|
pub fn create(compartment: @mut Compartment, win: @mut Window) {
|
||||||
|
@ -141,13 +148,13 @@ pub fn create(compartment: @mut Compartment, win: @mut Window) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let raw_ptr: *libc::c_void = cast::transmute(squirrel_away(win));
|
let raw_ptr: *libc::c_void = cast::transmute(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));
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: All properties/methods on Window need to be available on the global
|
//TODO: All properties/methods on Window need to be available on the global
|
||||||
// object as well. We probably want a special JSClass with a resolve hook.
|
// object as well. We probably want a special JSClass with a resolve hook.
|
||||||
compartment.define_property(~"window", RUST_OBJECT_TO_JSVAL(obj.ptr),
|
compartment.define_property(~"window", RUST_OBJECT_TO_JSVAL(obj.ptr),
|
||||||
JS_PropertyStub, JS_StrictPropertyStub,
|
JS_PropertyStub, JS_StrictPropertyStub,
|
||||||
JSPROP_ENUMERATE);
|
JSPROP_ENUMERATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CacheableWrapper for Window {
|
impl CacheableWrapper for Window {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
use dom::bindings::utils::{DOMString, null_string, str};
|
use dom::bindings::utils::{DOMString, null_string, str};
|
||||||
use dom::node::{Node, NodeTypeId, ScriptView};
|
use dom::node::{Node, NodeTypeId, ScriptView};
|
||||||
|
|
||||||
use core::str;
|
use std::str;
|
||||||
|
|
||||||
pub struct CharacterData {
|
pub struct CharacterData {
|
||||||
parent: Node<ScriptView>,
|
parent: Node<ScriptView>,
|
||||||
|
@ -46,7 +46,7 @@ impl CharacterData {
|
||||||
|
|
||||||
pub fn AppendData(&mut self, arg: DOMString) {
|
pub fn AppendData(&mut self, arg: DOMString) {
|
||||||
let s = self.data.to_str();
|
let s = self.data.to_str();
|
||||||
self.data = str(str::append(s, arg.to_str()));
|
self.data = str(s.append(arg.to_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn InsertData(&mut self, _offset: u32, _arg: DOMString) {
|
pub fn InsertData(&mut self, _offset: u32, _arg: DOMString) {
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
use dom::bindings::utils::WrapperCache;
|
use dom::bindings::utils::WrapperCache;
|
||||||
|
|
||||||
|
use std::f32;
|
||||||
|
|
||||||
pub struct ClientRect {
|
pub struct ClientRect {
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
top: f32,
|
top: f32,
|
||||||
|
|
|
@ -10,8 +10,8 @@ pub struct ClientRectList {
|
||||||
rects: ~[@mut ClientRect]
|
rects: ~[@mut ClientRect]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl ClientRectList {
|
impl ClientRectList {
|
||||||
fn new(rects: ~[@mut ClientRect]) -> @mut ClientRectList {
|
pub fn new(rects: ~[@mut ClientRect]) -> @mut ClientRectList {
|
||||||
let list = @mut ClientRectList {
|
let list = @mut ClientRectList {
|
||||||
wrapper: WrapperCache::new(),
|
wrapper: WrapperCache::new(),
|
||||||
rects: rects
|
rects: rects
|
||||||
|
@ -20,11 +20,11 @@ pub impl ClientRectList {
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Length(&self) -> u32 {
|
pub fn Length(&self) -> u32 {
|
||||||
self.rects.len() as u32
|
self.rects.len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Item(&self, index: u32) -> Option<@mut ClientRect> {
|
pub fn Item(&self, index: u32) -> Option<@mut ClientRect> {
|
||||||
if index < self.rects.len() as u32 {
|
if index < self.rects.len() as u32 {
|
||||||
Some(self.rects[index])
|
Some(self.rects[index])
|
||||||
} else {
|
} else {
|
||||||
|
@ -32,7 +32,7 @@ pub impl ClientRectList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut ClientRect> {
|
pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<@mut ClientRect> {
|
||||||
*found = index < self.rects.len() as u32;
|
*found = index < self.rects.len() as u32;
|
||||||
self.Item(index)
|
self.Item(index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use dom::node::{AbstractNode, ScriptView};
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use script_task::global_script_context;
|
use script_task::global_script_context;
|
||||||
|
|
||||||
use js::jsapi::bindgen::{JS_AddObjectRoot, JS_RemoveObjectRoot};
|
use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot};
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
|
@ -19,23 +19,25 @@ pub struct Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Document(root: AbstractNode<ScriptView>, window: Option<@mut Window>) -> @mut Document {
|
pub fn Document(root: AbstractNode<ScriptView>, window: Option<@mut Window>) -> @mut Document {
|
||||||
let doc = @mut Document {
|
unsafe {
|
||||||
root: root,
|
let doc = @mut Document {
|
||||||
wrapper: WrapperCache::new(),
|
root: root,
|
||||||
window: window
|
wrapper: WrapperCache::new(),
|
||||||
};
|
window: window
|
||||||
let compartment = global_script_context().js_compartment;
|
};
|
||||||
do root.with_base |base| {
|
let compartment = global_script_context().js_compartment;
|
||||||
assert!(base.wrapper.get_wrapper().is_not_null());
|
do root.with_base |base| {
|
||||||
let rootable = base.wrapper.get_rootable();
|
assert!(base.wrapper.get_wrapper().is_not_null());
|
||||||
JS_AddObjectRoot(compartment.cx.ptr, rootable);
|
let rootable = base.wrapper.get_rootable();
|
||||||
|
JS_AddObjectRoot(compartment.cx.ptr, rootable);
|
||||||
|
}
|
||||||
|
document::create(compartment, doc);
|
||||||
|
doc
|
||||||
}
|
}
|
||||||
document::create(compartment, doc);
|
|
||||||
doc
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Document {
|
impl Document {
|
||||||
fn getElementsByTagName(&self, tag: DOMString) -> Option<@mut HTMLCollection> {
|
pub fn getElementsByTagName(&self, tag: DOMString) -> Option<@mut HTMLCollection> {
|
||||||
let mut elements = ~[];
|
let mut elements = ~[];
|
||||||
let tag = tag.to_str();
|
let tag = tag.to_str();
|
||||||
let _ = for self.root.traverse_preorder |child| {
|
let _ = for self.root.traverse_preorder |child| {
|
||||||
|
@ -50,18 +52,20 @@ pub impl Document {
|
||||||
Some(HTMLCollection::new(elements))
|
Some(HTMLCollection::new(elements))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_changed(&self) {
|
pub fn content_changed(&self) {
|
||||||
for self.window.each |window| {
|
for self.window.iter().advance |window| {
|
||||||
window.content_changed()
|
window.content_changed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn teardown(&self) {
|
pub fn teardown(&self) {
|
||||||
let compartment = global_script_context().js_compartment;
|
unsafe {
|
||||||
do self.root.with_base |node| {
|
let compartment = global_script_context().js_compartment;
|
||||||
assert!(node.wrapper.get_wrapper().is_not_null());
|
do self.root.with_base |node| {
|
||||||
let rootable = node.wrapper.get_rootable();
|
assert!(node.wrapper.get_wrapper().is_not_null());
|
||||||
JS_RemoveObjectRoot(compartment.cx.ptr, rootable);
|
let rootable = node.wrapper.get_rootable();
|
||||||
|
JS_RemoveObjectRoot(compartment.cx.ptr, rootable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@ use dom::node::{ElementNodeTypeId, Node, ScriptView};
|
||||||
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
|
use layout_interface::{ContentBoxQuery, ContentBoxResponse, ContentBoxesQuery};
|
||||||
use layout_interface::{ContentBoxesResponse};
|
use layout_interface::{ContentBoxesResponse};
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::str::eq_slice;
|
use std::uint;
|
||||||
use std::net::url::Url;
|
use std::str::eq_slice;
|
||||||
|
use extra::net::url::Url;
|
||||||
|
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
parent: Node<ScriptView>,
|
parent: Node<ScriptView>,
|
||||||
|
@ -114,7 +115,7 @@ pub struct HTMLImageElement {
|
||||||
// Element methods
|
// Element methods
|
||||||
//
|
//
|
||||||
|
|
||||||
pub impl<'self> Element {
|
impl<'self> Element {
|
||||||
pub fn new(type_id: ElementTypeId, tag_name: ~str) -> Element {
|
pub fn new(type_id: ElementTypeId, tag_name: ~str) -> Element {
|
||||||
Element {
|
Element {
|
||||||
parent: Node::new(ElementNodeTypeId(type_id)),
|
parent: Node::new(ElementNodeTypeId(type_id)),
|
||||||
|
@ -123,7 +124,7 @@ pub impl<'self> Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_attr(&'self self, name: &str) -> Option<&'self str> {
|
pub fn get_attr(&'self self, name: &str) -> Option<&'self str> {
|
||||||
// FIXME: Need an each() that links lifetimes in Rust.
|
// FIXME: Need an each() that links lifetimes in Rust.
|
||||||
for uint::range(0, self.attrs.len()) |i| {
|
for uint::range(0, self.attrs.len()) |i| {
|
||||||
if eq_slice(self.attrs[i].name, name) {
|
if eq_slice(self.attrs[i].name, name) {
|
||||||
|
@ -134,11 +135,11 @@ pub impl<'self> Element {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_attr(&mut self, name: &DOMString, value: &DOMString) {
|
pub fn set_attr(&mut self, name: &DOMString, value: &DOMString) {
|
||||||
let name = name.to_str();
|
let name = name.to_str();
|
||||||
let value = value.to_str();
|
let value = value.to_str();
|
||||||
// FIXME: We need a better each_mut in Rust; this is ugly.
|
// FIXME: We need a better each_mut in Rust; this is ugly.
|
||||||
let value_cell = Cell(value);
|
let value_cell = Cell::new(value);
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for uint::range(0, self.attrs.len()) |i| {
|
for uint::range(0, self.attrs.len()) |i| {
|
||||||
if eq_slice(self.attrs[i].name, name) {
|
if eq_slice(self.attrs[i].name, name) {
|
||||||
|
@ -157,7 +158,7 @@ pub impl<'self> Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getClientRects(&self) -> Option<@mut ClientRectList> {
|
pub fn getClientRects(&self) -> Option<@mut ClientRectList> {
|
||||||
let rects = match self.parent.owner_doc {
|
let rects = match self.parent.owner_doc {
|
||||||
Some(doc) => {
|
Some(doc) => {
|
||||||
match doc.window {
|
match doc.window {
|
||||||
|
@ -199,7 +200,7 @@ pub impl<'self> Element {
|
||||||
Some(ClientRectList::new(rects))
|
Some(ClientRectList::new(rects))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBoundingClientRect(&self) -> Option<@mut ClientRect> {
|
pub fn getBoundingClientRect(&self) -> Option<@mut ClientRect> {
|
||||||
match self.parent.owner_doc {
|
match self.parent.owner_doc {
|
||||||
Some(doc) => {
|
Some(doc) => {
|
||||||
match doc.window {
|
match doc.window {
|
||||||
|
|
|
@ -9,6 +9,8 @@ use dom::bindings::utils::{DOMString, ErrorResult, WrapperCache};
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
|
||||||
|
use std::comm;
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
ResizeEvent(uint, uint),
|
ResizeEvent(uint, uint),
|
||||||
ReflowEvent,
|
ReflowEvent,
|
||||||
|
|
|
@ -8,8 +8,8 @@ pub struct EventTarget {
|
||||||
wrapper: WrapperCache
|
wrapper: WrapperCache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl EventTarget {
|
impl EventTarget {
|
||||||
fn new() -> ~EventTarget {
|
pub fn new() -> ~EventTarget {
|
||||||
~EventTarget {
|
~EventTarget {
|
||||||
wrapper: WrapperCache::new()
|
wrapper: WrapperCache::new()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,15 @@ use dom::node::{AbstractNode, ScriptView};
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
pub struct HTMLCollection {
|
pub struct HTMLCollection {
|
||||||
elements: ~[AbstractNode<ScriptView>],
|
elements: ~[AbstractNode<ScriptView>],
|
||||||
wrapper: WrapperCache
|
wrapper: WrapperCache
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl HTMLCollection {
|
impl HTMLCollection {
|
||||||
fn new(elements: ~[AbstractNode<ScriptView>]) -> @mut HTMLCollection {
|
pub fn new(elements: ~[AbstractNode<ScriptView>]) -> @mut HTMLCollection {
|
||||||
let collection = @mut HTMLCollection {
|
let collection = @mut HTMLCollection {
|
||||||
elements: elements,
|
elements: elements,
|
||||||
wrapper: WrapperCache::new()
|
wrapper: WrapperCache::new()
|
||||||
|
@ -23,11 +25,11 @@ pub impl HTMLCollection {
|
||||||
collection
|
collection
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Length(&self) -> u32 {
|
pub fn Length(&self) -> u32 {
|
||||||
self.elements.len() as u32
|
self.elements.len() as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Item(&self, index: u32) -> Option<AbstractNode<ScriptView>> {
|
pub fn Item(&self, index: u32) -> Option<AbstractNode<ScriptView>> {
|
||||||
if index < self.Length() {
|
if index < self.Length() {
|
||||||
Some(self.elements[index])
|
Some(self.elements[index])
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,12 +37,12 @@ pub impl HTMLCollection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn NamedItem(&self, _cx: *JSContext, _name: DOMString, rv: &mut ErrorResult) -> *JSObject {
|
pub fn NamedItem(&self, _cx: *JSContext, _name: DOMString, rv: &mut ErrorResult) -> *JSObject {
|
||||||
*rv = Ok(());
|
*rv = Ok(());
|
||||||
ptr::null()
|
ptr::null()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode<ScriptView>> {
|
pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<AbstractNode<ScriptView>> {
|
||||||
*found = true;
|
*found = true;
|
||||||
self.Item(index)
|
self.Item(index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,10 @@ use dom::element::{Element, ElementTypeId, HTMLImageElement, HTMLImageElementTyp
|
||||||
use dom::element::{HTMLStyleElementTypeId};
|
use dom::element::{HTMLStyleElementTypeId};
|
||||||
use script_task::global_script_context;
|
use script_task::global_script_context;
|
||||||
|
|
||||||
use core::cast::transmute;
|
use std::cast;
|
||||||
use core::libc::c_void;
|
use std::cast::transmute;
|
||||||
|
use std::libc::c_void;
|
||||||
|
use std::uint;
|
||||||
use js::rust::Compartment;
|
use js::rust::Compartment;
|
||||||
use netsurfcss::util::VoidPtrLike;
|
use netsurfcss::util::VoidPtrLike;
|
||||||
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
||||||
|
|
|
@ -8,10 +8,15 @@ use dom::bindings::window;
|
||||||
use layout_interface::ReflowForScriptQuery;
|
use layout_interface::ReflowForScriptQuery;
|
||||||
use script_task::{ExitMsg, FireTimerMsg, ScriptChan, ScriptContext};
|
use script_task::{ExitMsg, FireTimerMsg, ScriptChan, ScriptContext};
|
||||||
|
|
||||||
use core::comm::Chan;
|
use std::comm;
|
||||||
|
use std::comm::Chan;
|
||||||
|
use std::libc;
|
||||||
|
use std::int;
|
||||||
|
use std::io;
|
||||||
|
use std::ptr;
|
||||||
use js::jsapi::JSVal;
|
use js::jsapi::JSVal;
|
||||||
use std::timer;
|
use extra::timer;
|
||||||
use std::uv_global_loop;
|
use extra::uv_global_loop;
|
||||||
|
|
||||||
pub enum TimerControlMsg {
|
pub enum TimerControlMsg {
|
||||||
TimerMessage_Fire(~TimerData),
|
TimerMessage_Fire(~TimerData),
|
||||||
|
@ -61,17 +66,17 @@ pub fn TimerData(argc: libc::c_uint, argv: *JSVal) -> TimerData {
|
||||||
|
|
||||||
// FIXME: delayed_send shouldn't require Copy
|
// FIXME: delayed_send shouldn't require Copy
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
#[allow(non_implicitly_copyable_typarams)]
|
||||||
pub impl Window {
|
impl Window {
|
||||||
fn alert(&self, s: &str) {
|
pub fn alert(&self, s: &str) {
|
||||||
// Right now, just print to the console
|
// Right now, just print to the console
|
||||||
io::println(fmt!("ALERT: %s", s));
|
io::println(fmt!("ALERT: %s", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&self) {
|
pub fn close(&self) {
|
||||||
self.timer_chan.send(TimerMessage_TriggerExit);
|
self.timer_chan.send(TimerMessage_TriggerExit);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *JSVal) {
|
pub fn setTimeout(&self, timeout: int, argc: libc::c_uint, argv: *JSVal) {
|
||||||
let timeout = int::max(0, timeout) as uint;
|
let timeout = int::max(0, timeout) as uint;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -82,7 +87,7 @@ pub impl Window {
|
||||||
TimerMessage_Fire(~TimerData(argc, argv)));
|
TimerMessage_Fire(~TimerData(argc, argv)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_changed(&self) {
|
pub fn content_changed(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.script_context).reflow_all(ReflowForScriptQuery)
|
(*self.script_context).reflow_all(ReflowForScriptQuery)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
|
|
||||||
/// Some little helpers for hooking up the HTML parser with the CSS parser.
|
/// Some little helpers for hooking up the HTML parser with the CSS parser.
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::Port;
|
use std::comm;
|
||||||
use core::str;
|
use std::comm::Port;
|
||||||
|
use std::task;
|
||||||
|
use std::str;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::util::DataStream;
|
use newcss::util::DataStream;
|
||||||
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
/// Where a style sheet comes from.
|
/// Where a style sheet comes from.
|
||||||
pub enum StylesheetProvenance {
|
pub enum StylesheetProvenance {
|
||||||
|
@ -23,12 +25,12 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance,
|
||||||
-> Port<Stylesheet> {
|
-> Port<Stylesheet> {
|
||||||
let (result_port, result_chan) = comm::stream();
|
let (result_port, result_chan) = comm::stream();
|
||||||
|
|
||||||
let provenance_cell = Cell(provenance);
|
let provenance_cell = Cell::new(provenance);
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
let url = do provenance_cell.with_ref |p| {
|
let url = do provenance_cell.with_ref |p| {
|
||||||
match *p {
|
match *p {
|
||||||
UrlProvenance(copy the_url) => the_url,
|
UrlProvenance(ref the_url) => copy *the_url,
|
||||||
InlineProvenance(copy the_url, _) => the_url
|
InlineProvenance(ref the_url, _) => copy *the_url
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -64,13 +66,14 @@ fn resource_port_to_data_stream(input_port: Port<ProgressMsg>) -> DataStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_to_data_stream(data: ~str) -> DataStream {
|
fn data_to_data_stream(data: ~str) -> DataStream {
|
||||||
let data_cell = Cell(data);
|
let data_cell = Cell::new(data);
|
||||||
return || {
|
return || {
|
||||||
if data_cell.is_empty() {
|
if data_cell.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Blech, a copy.
|
// FIXME: Blech, a copy.
|
||||||
Some(str::to_bytes(data_cell.take()))
|
let data = data_cell.take();
|
||||||
|
Some(data.as_bytes().to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,17 +8,21 @@ use dom::node::{Text};
|
||||||
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
use html::cssparse::{InlineProvenance, StylesheetProvenance, UrlProvenance, spawn_css_parser};
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use std::cast;
|
||||||
use core::comm::{Chan, Port, SharedChan};
|
use std::cell::Cell;
|
||||||
use core::str::eq_slice;
|
use std::comm;
|
||||||
|
use std::comm::{Chan, Port, SharedChan};
|
||||||
|
use std::str::eq_slice;
|
||||||
|
use std::result;
|
||||||
|
use std::task;
|
||||||
use hubbub::hubbub;
|
use hubbub::hubbub;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::image_cache_task;
|
use servo_net::image_cache_task;
|
||||||
use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
|
use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeUtils;
|
||||||
use servo_util::url::make_url;
|
use servo_util::url::make_url;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
use std::net::url;
|
use extra::net::url;
|
||||||
|
|
||||||
macro_rules! handle_element(
|
macro_rules! handle_element(
|
||||||
($tag:expr, $string:expr, $type_id:expr, $ctor:ident, [ $(($field:ident : $field_init:expr)),* ]) => (
|
($tag:expr, $string:expr, $type_id:expr, $ctor:ident, [ $(($field:ident : $field_init:expr)),* ]) => (
|
||||||
|
@ -101,7 +105,7 @@ fn css_link_listener(to_parent: Chan<Option<Stylesheet>>,
|
||||||
|
|
||||||
// Send the sheets back in order
|
// Send the sheets back in order
|
||||||
// FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these
|
// FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these
|
||||||
do vec::consume(result_vec) |_i, port| {
|
do result_vec.consume |_i, port| {
|
||||||
to_parent.send(Some(port.recv()));
|
to_parent.send(Some(port.recv()));
|
||||||
}
|
}
|
||||||
to_parent.send(None);
|
to_parent.send(None);
|
||||||
|
@ -140,7 +144,7 @@ fn js_script_listener(to_parent: Chan<~[~[u8]]>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec::push(&mut result_vec, result_port);
|
result_vec.push(result_port);
|
||||||
}
|
}
|
||||||
JSTaskExit => {
|
JSTaskExit => {
|
||||||
break;
|
break;
|
||||||
|
@ -148,7 +152,7 @@ fn js_script_listener(to_parent: Chan<~[~[u8]]>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let js_scripts = vec::filter_map(result_vec, |result_port| result_port.recv());
|
let js_scripts = result_vec.iter().filter_map(|result_port| result_port.recv()).collect();
|
||||||
to_parent.send(js_scripts);
|
to_parent.send(js_scripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,9 +215,9 @@ pub fn parse_html(url: Url,
|
||||||
let resource_task2 = resource_task.clone();
|
let resource_task2 = resource_task.clone();
|
||||||
|
|
||||||
let (stylesheet_port, stylesheet_chan) = comm::stream();
|
let (stylesheet_port, stylesheet_chan) = comm::stream();
|
||||||
let stylesheet_chan = Cell(stylesheet_chan);
|
let stylesheet_chan = Cell::new(stylesheet_chan);
|
||||||
let (css_msg_port, css_msg_chan) = comm::stream();
|
let (css_msg_port, css_msg_chan) = comm::stream();
|
||||||
let css_msg_port = Cell(css_msg_port);
|
let css_msg_port = Cell::new(css_msg_port);
|
||||||
do spawn {
|
do spawn {
|
||||||
css_link_listener(stylesheet_chan.take(), css_msg_port.take(), resource_task2.clone());
|
css_link_listener(stylesheet_chan.take(), css_msg_port.take(), resource_task2.clone());
|
||||||
}
|
}
|
||||||
|
@ -223,15 +227,16 @@ pub fn parse_html(url: Url,
|
||||||
// Spawn a JS parser to receive JavaScript.
|
// Spawn a JS parser to receive JavaScript.
|
||||||
let resource_task2 = resource_task.clone();
|
let resource_task2 = resource_task.clone();
|
||||||
let (js_result_port, js_result_chan) = comm::stream();
|
let (js_result_port, js_result_chan) = comm::stream();
|
||||||
let js_result_chan = Cell(js_result_chan);
|
let js_result_chan = Cell::new(js_result_chan);
|
||||||
let (js_msg_port, js_msg_chan) = comm::stream();
|
let (js_msg_port, js_msg_chan) = comm::stream();
|
||||||
let js_msg_port = Cell(js_msg_port);
|
let js_msg_port = Cell::new(js_msg_port);
|
||||||
do spawn {
|
do spawn {
|
||||||
js_script_listener(js_result_chan.take(), js_msg_port.take(), resource_task2.clone());
|
js_script_listener(js_result_chan.take(), js_msg_port.take(), resource_task2.clone());
|
||||||
}
|
}
|
||||||
let js_chan = SharedChan::new(js_msg_chan);
|
let js_chan = SharedChan::new(js_msg_chan);
|
||||||
|
|
||||||
let url2 = url.clone(), url3 = url.clone();
|
let url2 = url.clone();
|
||||||
|
let url3 = url.clone();
|
||||||
|
|
||||||
// Build the root node.
|
// Build the root node.
|
||||||
let root = ~HTMLHtmlElement { parent: Element::new(HTMLHtmlElementTypeId, ~"html") };
|
let root = ~HTMLHtmlElement { parent: Element::new(HTMLHtmlElementTypeId, ~"html") };
|
||||||
|
@ -239,7 +244,7 @@ pub fn parse_html(url: Url,
|
||||||
debug!("created new node");
|
debug!("created new node");
|
||||||
let mut parser = hubbub::Parser("UTF-8", false);
|
let mut parser = hubbub::Parser("UTF-8", false);
|
||||||
debug!("created parser");
|
debug!("created parser");
|
||||||
parser.set_document_node(root.to_hubbub_node());
|
parser.set_document_node(unsafe { root.to_hubbub_node() });
|
||||||
parser.enable_scripting(true);
|
parser.enable_scripting(true);
|
||||||
|
|
||||||
// Performs various actions necessary after appending has taken place. Currently, this
|
// Performs various actions necessary after appending has taken place. Currently, this
|
||||||
|
@ -250,7 +255,7 @@ pub fn parse_html(url: Url,
|
||||||
if parent_node.is_style_element() && child_node.is_text() {
|
if parent_node.is_style_element() && child_node.is_text() {
|
||||||
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 url_cell = Cell(url);
|
let url_cell = Cell::new(url);
|
||||||
do child_node.with_imm_text |text_node| {
|
do child_node.with_imm_text |text_node| {
|
||||||
let data = text_node.parent.data.to_str(); // FIXME: Bad copy.
|
let data = text_node.parent.data.to_str(); // FIXME: Bad copy.
|
||||||
let provenance = InlineProvenance(result::unwrap(url_cell.take()), data);
|
let provenance = InlineProvenance(result::unwrap(url_cell.take()), data);
|
||||||
|
@ -330,7 +335,7 @@ pub fn parse_html(url: Url,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
node.to_hubbub_node()
|
unsafe { node.to_hubbub_node() }
|
||||||
},
|
},
|
||||||
create_text: |data: ~str| {
|
create_text: |data: ~str| {
|
||||||
debug!("create text");
|
debug!("create text");
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
use dom::node::{AbstractNode, ScriptView, LayoutView};
|
use dom::node::{AbstractNode, ScriptView, LayoutView};
|
||||||
use script_task::{ScriptMsg, ScriptChan};
|
use script_task::{ScriptMsg, ScriptChan};
|
||||||
|
|
||||||
use core::comm::{Chan, SharedChan};
|
use std::comm::{Chan, SharedChan};
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
|
|
||||||
/// Asynchronous messages that script can send to layout.
|
/// Asynchronous messages that script can send to layout.
|
||||||
///
|
///
|
||||||
|
|
|
@ -20,7 +20,7 @@ extern mod newcss (name = "css");
|
||||||
extern mod servo_net (name = "net");
|
extern mod servo_net (name = "net");
|
||||||
extern mod servo_util (name = "util");
|
extern mod servo_util (name = "util");
|
||||||
extern mod servo_msg (name = "msg");
|
extern mod servo_msg (name = "msg");
|
||||||
extern mod std;
|
extern mod extra;
|
||||||
|
|
||||||
pub mod dom {
|
pub mod dom {
|
||||||
pub mod bindings {
|
pub mod bindings {
|
||||||
|
|
|
@ -19,30 +19,31 @@ use layout_interface::{ReflowForDisplay, ReflowForScriptQuery, ReflowGoal, Reflo
|
||||||
use layout_interface;
|
use layout_interface;
|
||||||
use servo_msg::engine::{EngineChan, LoadUrlMsg};
|
use servo_msg::engine::{EngineChan, LoadUrlMsg};
|
||||||
|
|
||||||
use core::cast::transmute;
|
use std::cast::transmute;
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Port, SharedChan};
|
use std::comm;
|
||||||
use core::io::read_whole_file;
|
use std::comm::{Port, SharedChan};
|
||||||
use core::local_data;
|
use std::io::read_whole_file;
|
||||||
use core::ptr::null;
|
use std::local_data;
|
||||||
use core::task::{SingleThreaded, task};
|
use std::ptr::null;
|
||||||
use core::util::replace;
|
use std::task::{SingleThreaded, task};
|
||||||
|
use std::util::replace;
|
||||||
use dom::window::TimerData;
|
use dom::window::TimerData;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use html::hubbub_html_parser;
|
use html::hubbub_html_parser;
|
||||||
use js::JSVAL_NULL;
|
use js::JSVAL_NULL;
|
||||||
use js::global::{global_class, debug_fns};
|
use js::global::{global_class, debug_fns};
|
||||||
use js::glue::bindgen::RUST_JSVAL_TO_OBJECT;
|
use js::glue::RUST_JSVAL_TO_OBJECT;
|
||||||
use js::jsapi::JSContext;
|
use js::jsapi::JSContext;
|
||||||
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
|
use js::jsapi::{JS_CallFunctionValue, JS_GetContextPrivate};
|
||||||
use js::rust::{Compartment, Cx};
|
use js::rust::{Compartment, Cx};
|
||||||
use js;
|
use js;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
use servo_util::url::make_url;
|
use servo_util::url::make_url;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
use std::net::url;
|
use extra::net::url;
|
||||||
|
|
||||||
/// Messages used to control the script task.
|
/// Messages used to control the script task.
|
||||||
pub enum ScriptMsg {
|
pub enum ScriptMsg {
|
||||||
|
@ -146,7 +147,9 @@ pub fn global_script_context() -> @ScriptContext {
|
||||||
///
|
///
|
||||||
/// FIXME: Rename to `script_context_from_js_context`.
|
/// FIXME: Rename to `script_context_from_js_context`.
|
||||||
pub fn task_from_context(js_context: *JSContext) -> *mut ScriptContext {
|
pub fn task_from_context(js_context: *JSContext) -> *mut ScriptContext {
|
||||||
JS_GetContextPrivate(js_context) as *mut ScriptContext
|
unsafe {
|
||||||
|
JS_GetContextPrivate(js_context) as *mut ScriptContext
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
|
@ -200,7 +203,7 @@ impl ScriptContext {
|
||||||
|
|
||||||
root_frame: None,
|
root_frame: None,
|
||||||
|
|
||||||
window_size: Size2D(800, 600),
|
window_size: Size2D(800u, 600),
|
||||||
damage: None,
|
damage: None,
|
||||||
};
|
};
|
||||||
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
|
// Indirection for Rust Issue #6248, dynamic freeze scope artifically extended
|
||||||
|
@ -208,9 +211,9 @@ impl ScriptContext {
|
||||||
let borrowed_ctx= &mut *script_context;
|
let borrowed_ctx= &mut *script_context;
|
||||||
borrowed_ctx as *mut ScriptContext
|
borrowed_ctx as *mut ScriptContext
|
||||||
};
|
};
|
||||||
js_context.set_cx_private(script_context_ptr as *());
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
js_context.set_cx_private(script_context_ptr as *());
|
||||||
local_data::local_data_set(global_script_context_key, transmute(script_context))
|
local_data::local_data_set(global_script_context_key, transmute(script_context))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,8 +235,8 @@ impl ScriptContext {
|
||||||
compositor_task: ~fn(ReadyState),
|
compositor_task: ~fn(ReadyState),
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
image_cache_task: ImageCacheTask) {
|
image_cache_task: ImageCacheTask) {
|
||||||
let script_port = Cell(script_port);
|
let script_port = Cell::new(script_port);
|
||||||
let compositor_task = Cell(compositor_task);
|
let compositor_task = Cell::new(compositor_task);
|
||||||
// FIXME: rust#6399
|
// FIXME: rust#6399
|
||||||
let mut the_task = task();
|
let mut the_task = task();
|
||||||
the_task.sched_mode(SingleThreaded);
|
the_task.sched_mode(SingleThreaded);
|
||||||
|
@ -298,22 +301,24 @@ impl ScriptContext {
|
||||||
|
|
||||||
/// Handles a timer that fired.
|
/// Handles a timer that fired.
|
||||||
fn handle_fire_timer_msg(&mut self, timer_data: ~TimerData) {
|
fn handle_fire_timer_msg(&mut self, timer_data: ~TimerData) {
|
||||||
let this_value = if timer_data.args.len() > 0 {
|
unsafe {
|
||||||
RUST_JSVAL_TO_OBJECT(timer_data.args[0])
|
let this_value = if timer_data.args.len() > 0 {
|
||||||
} else {
|
RUST_JSVAL_TO_OBJECT(timer_data.args[0])
|
||||||
self.js_compartment.global_obj.ptr
|
} else {
|
||||||
};
|
self.js_compartment.global_obj.ptr
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
|
// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
|
||||||
let rval = JSVAL_NULL;
|
let rval = JSVAL_NULL;
|
||||||
JS_CallFunctionValue(self.js_context.ptr,
|
JS_CallFunctionValue(self.js_context.ptr,
|
||||||
this_value,
|
this_value,
|
||||||
timer_data.funval,
|
timer_data.funval,
|
||||||
0,
|
0,
|
||||||
null(),
|
null(),
|
||||||
&rval);
|
&rval);
|
||||||
|
|
||||||
self.reflow(ReflowForScriptQuery)
|
self.reflow(ReflowForScriptQuery)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a notification that reflow completed.
|
/// Handles a notification that reflow completed.
|
||||||
|
@ -325,7 +330,7 @@ impl ScriptContext {
|
||||||
/// Handles a request to exit the script task and shut down layout.
|
/// Handles a request to exit the script task and shut down layout.
|
||||||
fn handle_exit_msg(&mut self) {
|
fn handle_exit_msg(&mut self) {
|
||||||
self.join_layout();
|
self.join_layout();
|
||||||
for self.root_frame.each |frame| {
|
for self.root_frame.iter().advance |frame| {
|
||||||
frame.document.teardown();
|
frame.document.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +406,7 @@ impl ScriptContext {
|
||||||
self.js_compartment.define_functions(debug_fns);
|
self.js_compartment.define_functions(debug_fns);
|
||||||
|
|
||||||
// Evaluate every script in the document.
|
// Evaluate every script in the document.
|
||||||
do vec::consume(js_scripts) |_, bytes| {
|
do js_scripts.consume |_, bytes| {
|
||||||
let _ = self.js_context.evaluate_script(self.js_compartment.global_obj,
|
let _ = self.js_context.evaluate_script(self.js_compartment.global_obj,
|
||||||
bytes,
|
bytes,
|
||||||
~"???",
|
~"???",
|
||||||
|
@ -472,7 +477,7 @@ impl ScriptContext {
|
||||||
///
|
///
|
||||||
/// FIXME: This should basically never be used.
|
/// FIXME: This should basically never be used.
|
||||||
pub fn reflow_all(&mut self, goal: ReflowGoal) {
|
pub fn reflow_all(&mut self, goal: ReflowGoal) {
|
||||||
for self.root_frame.each |root_frame| {
|
for self.root_frame.iter().advance |root_frame| {
|
||||||
ScriptContext::damage(&mut self.damage,
|
ScriptContext::damage(&mut self.damage,
|
||||||
root_frame.document.root,
|
root_frame.document.root,
|
||||||
MatchSelectorsDocumentDamage)
|
MatchSelectorsDocumentDamage)
|
||||||
|
@ -520,7 +525,7 @@ impl ScriptContext {
|
||||||
|
|
||||||
self.window_size = Size2D(new_width, new_height);
|
self.window_size = Size2D(new_width, new_height);
|
||||||
|
|
||||||
for self.root_frame.each |root_frame| {
|
for self.root_frame.iter().advance |root_frame| {
|
||||||
ScriptContext::damage(&mut self.damage,
|
ScriptContext::damage(&mut self.damage,
|
||||||
root_frame.document.root,
|
root_frame.document.root,
|
||||||
ReflowDocumentDamage);
|
ReflowDocumentDamage);
|
||||||
|
@ -535,7 +540,7 @@ impl ScriptContext {
|
||||||
ReflowEvent => {
|
ReflowEvent => {
|
||||||
debug!("script got reflow event");
|
debug!("script got reflow event");
|
||||||
|
|
||||||
for self.root_frame.each |root_frame| {
|
for self.root_frame.iter().advance |root_frame| {
|
||||||
ScriptContext::damage(&mut self.damage,
|
ScriptContext::damage(&mut self.damage,
|
||||||
root_frame.document.root,
|
root_frame.document.root,
|
||||||
MatchSelectorsDocumentDamage);
|
MatchSelectorsDocumentDamage);
|
||||||
|
|
|
@ -13,8 +13,8 @@ pub struct MonoCache<K, V> {
|
||||||
entry: Option<(K,V)>,
|
entry: Option<(K,V)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<K: Copy + Eq, V: Copy> MonoCache<K,V> {
|
impl<K: Copy + Eq, V: Copy> MonoCache<K,V> {
|
||||||
fn new(_size: uint) -> MonoCache<K,V> {
|
pub fn new(_size: uint) -> MonoCache<K,V> {
|
||||||
MonoCache { entry: None }
|
MonoCache { entry: None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ impl<K: Copy + Eq, V: Copy> Cache<K,V> for MonoCache<K,V> {
|
||||||
fn find(&mut self, key: &K) -> Option<V> {
|
fn find(&mut self, key: &K) -> Option<V> {
|
||||||
match self.entry {
|
match self.entry {
|
||||||
None => None,
|
None => None,
|
||||||
Some((ref k,v)) => if *k == *key { Some(v) } else { None }
|
Some((ref k, ref v)) => if *k == *key { Some(copy *v) } else { None }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,19 +65,19 @@ pub struct LRUCache<K, V> {
|
||||||
cache_size: uint,
|
cache_size: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl<K: Copy + Eq, V: Copy> LRUCache<K,V> {
|
impl<K: Copy + Eq, V: Copy> LRUCache<K,V> {
|
||||||
fn new(size: uint) -> LRUCache<K, V> {
|
pub fn new(size: uint) -> LRUCache<K, V> {
|
||||||
LRUCache {
|
LRUCache {
|
||||||
entries: ~[],
|
entries: ~[],
|
||||||
cache_size: size,
|
cache_size: size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn touch(&mut self, pos: uint) -> V {
|
pub fn touch(&mut self, pos: uint) -> V {
|
||||||
let (key, val) = copy self.entries[pos];
|
let (key, val) = copy self.entries[pos];
|
||||||
if pos != self.cache_size {
|
if pos != self.cache_size {
|
||||||
self.entries.remove(pos);
|
self.entries.remove(pos);
|
||||||
self.entries.push((key, val));
|
self.entries.push((key, copy val));
|
||||||
}
|
}
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ impl<K: Copy + Eq, V: Copy> Cache<K,V> for LRUCache<K,V> {
|
||||||
Some(pos) => self.touch(pos),
|
Some(pos) => self.touch(pos),
|
||||||
None => {
|
None => {
|
||||||
let val = blk(key);
|
let val = blk(key);
|
||||||
self.insert(key, val);
|
self.insert(key, copy val);
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::uint;
|
||||||
|
|
||||||
enum RangeRelation {
|
enum RangeRelation {
|
||||||
OverlapsBegin(/* overlap */ uint),
|
OverlapsBegin(/* overlap */ uint),
|
||||||
OverlapsEnd(/* overlap */ uint),
|
OverlapsEnd(/* overlap */ uint),
|
||||||
|
@ -17,7 +19,7 @@ pub struct Range {
|
||||||
priv len: uint
|
priv len: uint
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Range {
|
impl Range {
|
||||||
pub fn new(off: uint, len: uint) -> Range {
|
pub fn new(off: uint, len: uint) -> Range {
|
||||||
Range { off: off, len: len }
|
Range { off: off, len: len }
|
||||||
}
|
}
|
||||||
|
@ -27,12 +29,12 @@ pub impl Range {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub impl Range {
|
impl Range {
|
||||||
fn begin(&self) -> uint { self.off }
|
pub fn begin(&self) -> uint { self.off }
|
||||||
fn length(&self) -> uint { self.len }
|
pub fn length(&self) -> uint { self.len }
|
||||||
fn end(&self) -> uint { self.off + self.len }
|
pub fn end(&self) -> uint { self.off + self.len }
|
||||||
|
|
||||||
fn eachi(&self, callback: &fn(uint) -> bool) -> bool {
|
pub fn eachi(&self, callback: &fn(uint) -> bool) -> bool {
|
||||||
for uint::range(self.off, self.off + self.len) |i| {
|
for uint::range(self.off, self.off + self.len) |i| {
|
||||||
if !callback(i) {
|
if !callback(i) {
|
||||||
break
|
break
|
||||||
|
@ -41,32 +43,32 @@ pub impl Range {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains(&self, i: uint) -> bool {
|
pub fn contains(&self, i: uint) -> bool {
|
||||||
i >= self.begin() && i < self.end()
|
i >= self.begin() && i < self.end()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_valid_for_string(&self, s: &str) -> bool {
|
pub fn is_valid_for_string(&self, s: &str) -> bool {
|
||||||
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
|
self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_by(&mut self, i: int) {
|
pub fn shift_by(&mut self, i: int) {
|
||||||
self.off = ((self.off as int) + i) as uint;
|
self.off = ((self.off as int) + i) as uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_by(&mut self, i: int) {
|
pub fn extend_by(&mut self, i: int) {
|
||||||
self.len = ((self.len as int) + i) as uint;
|
self.len = ((self.len as int) + i) as uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extend_to(&mut self, i: uint) {
|
pub fn extend_to(&mut self, i: uint) {
|
||||||
self.len = i - self.off;
|
self.len = i - self.off;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adjust_by(&mut self, off_i: int, len_i: int) {
|
pub fn adjust_by(&mut self, off_i: int, len_i: int) {
|
||||||
self.off = ((self.off as int) + off_i) as uint;
|
self.off = ((self.off as int) + off_i) as uint;
|
||||||
self.len = ((self.len as int) + len_i) as uint;
|
self.len = ((self.len as int) + len_i) as uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(&mut self, off_i: uint, len_i: uint) {
|
pub fn reset(&mut self, off_i: uint, len_i: uint) {
|
||||||
self.off = off_i;
|
self.off = off_i;
|
||||||
self.len = len_i;
|
self.len = len_i;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +76,7 @@ pub impl Range {
|
||||||
/// Computes the relationship between two ranges (`self` and `other`),
|
/// Computes the relationship between two ranges (`self` and `other`),
|
||||||
/// from the point of view of `self`. So, 'EntirelyBefore' means
|
/// from the point of view of `self`. So, 'EntirelyBefore' means
|
||||||
/// that the `self` range is entirely before `other` range.
|
/// that the `self` range is entirely before `other` range.
|
||||||
fn relation_to_range(&self, other: &Range) -> RangeRelation {
|
pub fn relation_to_range(&self, other: &Range) -> RangeRelation {
|
||||||
if other.begin() > self.end() {
|
if other.begin() > self.end() {
|
||||||
return EntirelyBefore;
|
return EntirelyBefore;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +104,7 @@ pub impl Range {
|
||||||
self, other));
|
self, other));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn repair_after_coalesced_range(&mut self, other: &Range) {
|
pub fn repair_after_coalesced_range(&mut self, other: &Range) {
|
||||||
let relation = self.relation_to_range(other);
|
let relation = self.relation_to_range(other);
|
||||||
debug!("repair_after_coalesced_range: possibly repairing range %?", self);
|
debug!("repair_after_coalesced_range: possibly repairing range %?", self);
|
||||||
debug!("repair_after_coalesced_range: relation of original range and coalesced range(%?): %?",
|
debug!("repair_after_coalesced_range: relation of original range and coalesced range(%?): %?",
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
// Timing functions.
|
// Timing functions.
|
||||||
use std::time::precise_time_ns;
|
use extra::time::precise_time_ns;
|
||||||
use core::cell::Cell;
|
use std::cell::Cell;
|
||||||
use core::comm::{Port, SharedChan};
|
use std::comm::{Port, SharedChan};
|
||||||
use std::sort::tim_sort;
|
use extra::sort::tim_sort;
|
||||||
|
|
||||||
// front-end representation of the profiler used to communicate with the profiler
|
// front-end representation of the profiler used to communicate with the profiler
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -111,7 +111,7 @@ impl ProfilerCategory {
|
||||||
|
|
||||||
impl Profiler {
|
impl Profiler {
|
||||||
pub fn create(port: Port<ProfilerMsg>) {
|
pub fn create(port: Port<ProfilerMsg>) {
|
||||||
let port = Cell(port);
|
let port = Cell::new(port);
|
||||||
do spawn {
|
do spawn {
|
||||||
let mut profiler = Profiler::new(port.take());
|
let mut profiler = Profiler::new(port.take());
|
||||||
profiler.start();
|
profiler.start();
|
||||||
|
@ -154,7 +154,7 @@ impl Profiler {
|
||||||
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
||||||
"_category (ms)_", "_mean (ms)_", "_median (ms)_",
|
"_category (ms)_", "_mean (ms)_", "_median (ms)_",
|
||||||
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
||||||
for vec::each_mut(self.buckets) |bucket| {
|
for self.buckets.mut_iter().advance |bucket| {
|
||||||
match *bucket {
|
match *bucket {
|
||||||
(category, ref mut data) => {
|
(category, ref mut data) => {
|
||||||
tim_sort(*data);
|
tim_sort(*data);
|
||||||
|
@ -163,8 +163,8 @@ impl Profiler {
|
||||||
let (mean, median, min, max) =
|
let (mean, median, min, max) =
|
||||||
(data.foldl(0f64, |a, b| a + *b) / (data_len as f64),
|
(data.foldl(0f64, |a, b| a + *b) / (data_len as f64),
|
||||||
data[data_len / 2],
|
data[data_len / 2],
|
||||||
data.min(),
|
data.iter().min(),
|
||||||
data.max());
|
data.iter().max());
|
||||||
println(fmt!("%-30s: %15.4? %15.4? %15.4? %15.4? %15u",
|
println(fmt!("%-30s: %15.4? %15.4? %15.4? %15.4? %15u",
|
||||||
category.format(), mean, median, min, max, data_len));
|
category.format(), mean, median, min, max, data_len));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::net::url;
|
use extra::net::url;
|
||||||
use std::net::url::Url;
|
use extra::net::url::Url;
|
||||||
use core::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
|
use std::os;
|
||||||
|
use std::result;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
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
|
||||||
|
@ -36,15 +38,15 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
||||||
str_url.starts_with("/") {
|
str_url.starts_with("/") {
|
||||||
current_url.scheme + "://" +
|
current_url.scheme + "://" +
|
||||||
current_url.host + "/" +
|
current_url.host + "/" +
|
||||||
str_url.trim_left_chars([ '/' ])
|
str_url.trim_left_chars(&'/')
|
||||||
} else {
|
} else {
|
||||||
let mut path = ~[];
|
let mut path = ~[];
|
||||||
for str::each_split_char(current_url.path, '/') |p| {
|
for current_url.path.split_iter('/').advance |p| {
|
||||||
path.push(p.to_str());
|
path.push(p.to_str());
|
||||||
}
|
}
|
||||||
let path = path; // FIXME: borrow checker workaround
|
let path = path; // FIXME: borrow checker workaround
|
||||||
let path = path.init();
|
let path = path.init();
|
||||||
let path = str::connect(path.map(|x| copy *x) + ~[str_url], "/");
|
let path = (path.map(|x| copy *x) + [str_url]).connect("/");
|
||||||
|
|
||||||
current_url.scheme + "://" + current_url.host + path
|
current_url.scheme + "://" + current_url.host + path
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
url = "http://servo.org/")];
|
url = "http://servo.org/")];
|
||||||
#[crate_type = "lib"];
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
extern mod std;
|
extern mod extra;
|
||||||
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
pub mod range;
|
pub mod range;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use core::cmp::{Ord, Eq};
|
use std::cmp::{Ord, Eq};
|
||||||
|
|
||||||
pub trait BinarySearchMethods<'self, T: Ord + Eq> {
|
pub trait BinarySearchMethods<'self, T: Ord + Eq> {
|
||||||
fn binary_search(&self, key: &T) -> Option<&'self T>;
|
fn binary_search(&self, key: &T) -> Option<&'self T>;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7cb7a7aace99b17f99f15649377bb13a0dac9b63
|
Subproject commit faca1281aaf112e96ee03041744fe85ac4273192
|
|
@ -1 +1 @@
|
||||||
Subproject commit cde4fdcfe2c956f070c2b0e26c5fd99821248cdc
|
Subproject commit 5247c3e97f7eafa336c8a028a3175c3bc3a2d95a
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0ac7b8dc20c4142ac6ad4500d7ae90c2bd3e7424
|
Subproject commit 788f41a6e924e5c3f9d254d3e5dabf2b3e622f00
|
|
@ -1 +1 @@
|
||||||
Subproject commit d916b9796668d4bb46a3b1b4976c95ab7da79837
|
Subproject commit 3ef4cf7fdaaaa51026ec546a71426ff03a0899fd
|
|
@ -1 +1 @@
|
||||||
Subproject commit 40b2a4eaf80287a4c4727b97313151705b4f04c6
|
Subproject commit ea8d2bd026cd91d3fb5fd753677da3fd7d21dbab
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3433fbda15cf2f16e00ff8103ae7652468a43a2c
|
Subproject commit bf9d0ebf3e0283f8bdb505d29d93de9631f7877c
|
|
@ -1 +1 @@
|
||||||
Subproject commit 98e2d7e3870759fe91c93ba520452a700fec8756
|
Subproject commit 72c7673ac50cc1ffb518de65022fb034df334ed9
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0cba81aab4858442e9a995cf3b0149d0d116627c
|
Subproject commit 8a15a3bd2bd98ee4fb0513b71d7055c8be40a4b7
|
|
@ -1 +1 @@
|
||||||
Subproject commit cf5641f5b0b7720e3841518ab7fbfafb4d2443a4
|
Subproject commit 6daaffe3b6cf226c6da4979d0fb907a8258b0288
|
|
@ -1 +1 @@
|
||||||
Subproject commit 865f539114383a021822583801e8362faf916699
|
Subproject commit 5e8c30cc69286e68ba9bf843f146a580381bff83
|
|
@ -1 +1 @@
|
||||||
Subproject commit efba52c020945e08f00bebf8ff54ec292e95eced
|
Subproject commit a23cb0bc99a933efa9104c2471ccd14638744ea4
|
|
@ -1 +1 @@
|
||||||
Subproject commit 453bf81e021008f5eba29b135f07f4529e6c8b2e
|
Subproject commit 42931c8e0894c0d3d70d29abdf16639b30e6bf92
|
|
@ -1 +1 @@
|
||||||
Subproject commit 56e106b9aa05f3a341397c0e116695fb8a826226
|
Subproject commit 4d576047b5b94d98669080f3ac25efa053024d7e
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue