Update to Rust 0.6.

This commit is contained in:
Jack Moffitt 2013-04-03 16:29:53 -06:00
parent b9f82b8d05
commit c850b59680
97 changed files with 1049 additions and 1135 deletions

View file

@ -230,6 +230,8 @@ package: servo
else else
bindings: $(AUTOGEN_SRC_servo)
.PHONY: package .PHONY: package
package: package:

@ -1 +1 @@
Subproject commit 95b4bd335549b74c4d50f34ecb074122572291ea Subproject commit c6402195adc8830d4b2eba3f755044842edb3ae6

@ -1 +1 @@
Subproject commit 6fc47a3120d652e68522a0f1dfe85af0c7e23145 Subproject commit 19a4939e13f2387cb7831623480d91301092c202

@ -1 +1 @@
Subproject commit 0ad3a110be9070b87ecd7e1c71d20a02660d8959 Subproject commit 783392f70fcfd6770782796bef06bed47043cabf

@ -1 +1 @@
Subproject commit a016a795bb9a021c06a665563c4aaf793b0b97ca Subproject commit 5fc77111bbb003fbcd9ba15e4813b31eccf6943c

@ -1 +1 @@
Subproject commit 252672fd902723cca59423a135c829a70a0b3f0b Subproject commit 861292b11bd66a654286c3731e5d1054da4e5cc4

@ -1 +1 @@
Subproject commit c8cf6f388da1446b267014154b36af85a752a438 Subproject commit 12a7bb3fde3941be1050d46c495fb0fb23aa1880

@ -1 +1 @@
Subproject commit 363b2f0e6b064e7a6fbf850706fe62597af28f03 Subproject commit 2a69e1c0eeb30d659f784e00224647d6a40404df

@ -1 +1 @@
Subproject commit bc86ccb773758b3e2ad7f689b67f77165048b9e6 Subproject commit 12a5b33342fb0efdff9998838542026dd08f1fe9

@ -1 +1 @@
Subproject commit 97949ebdfd8adb13eea639f1799a3bbb93868512 Subproject commit 99d5af7047c219feaf7fa6d723dadfde0545b686

@ -1 +1 @@
Subproject commit 9f406c72c22fb68691d8d137df679a7d047ec135 Subproject commit 200034f493565ddfc12c8899b2615aa113a74521

@ -1 +1 @@
Subproject commit 260f7062a4cae7e3575a3cf97d1119bc076ab221 Subproject commit 2cdbb170c3591c08a872e30584fcaf490680a100

@ -1 +1 @@
Subproject commit b414d3bf445ac63860a9cf44532280228f001a2b Subproject commit 6852c4a04e44d29dc410666ef551654a7e181d6c

@ -1 +1 @@
Subproject commit cdc1b0b8d173be4e1c79961742a367dac39d7d86 Subproject commit 89e5937773c265b0fd58ed0cedac777442f5c81c

@ -1 +1 @@
Subproject commit 337bc5cb49b2a518527d62cd9af08e169f4f6456 Subproject commit e094a0254778c042229ea031cb9f2b4821e5ed93

@ -1 +1 @@
Subproject commit e416f03f4898825bc8f24cfd890004a130e2457b Subproject commit e1967e565616a973c4a4ab398cc31bb4142bf35a

@ -1 +1 @@
Subproject commit 886cf481cbf9c9eedfbab0344e5f887c11220497 Subproject commit 26b20203db925e11cb5885da15a236067398c1a6

@ -1 +1 @@
Subproject commit 8e04c939c72083fa311ea709f5aafeaccd83975d Subproject commit 9045a321b5d40f604da0e3cd8920ef7d6e9e65a5

@ -1 +1 @@
Subproject commit 020deaffff282f36d8b1be8a98ee0e68f4a2b13b Subproject commit 669971ff0424f9d298ffcdebf3510026cfb354e5

@ -1 +1 @@
Subproject commit 276a57d204f2d0ae74bda4ed76e63b830ca6332b Subproject commit 92355d7224c16323c9d09b17ebcb340c6011e1e3

@ -1 +1 @@
Subproject commit 62558783027d1aaccb4e689d3ff5aed057a1f5f5 Subproject commit b6a306a26901ed7ce49f2b750c37972215c8ddaa

@ -1 +1 @@
Subproject commit 9b6d463d9045a90e6e3f31e35806af87e46e3852 Subproject commit 6770cdad275cd5c269955dd2ff844448d0947971

@ -1 +1 @@
Subproject commit 7e127420530640c7ec3c79883b702041dfe13b14 Subproject commit 942eac05bfd7397da0c8f9f92280bea4cf6021c4

@ -1 +1 @@
Subproject commit 06b790f226819e30c59b35523407bc671fe4d2ca Subproject commit fd38ef064bbac1444079a5262922c7bb73311216

@ -1 +1 @@
Subproject commit ce75a42685824a4c3c63a638a2c76762b7fac813 Subproject commit 6a8f6677d38a8d2e85850971ef3e578a550ed6de

@ -1 +1 @@
Subproject commit c8328148ec5d1ec4fb8a496a41e34badf53e7f88 Subproject commit 754ac8e774d9ac7b8577b6a0b775a54e1f00a262

View file

@ -5,7 +5,6 @@ use render_context::RenderContext;
use text::SendableTextRun; use text::SendableTextRun;
use util::range::Range; use util::range::Range;
use azure::azure_hl::DrawTarget;
use clone_arc = std::arc::clone; use clone_arc = std::arc::clone;
use geom::Rect; use geom::Rect;
use geom::Point2D; use geom::Point2D;
@ -15,8 +14,8 @@ struct DisplayItemData {
bounds : Rect<Au>, // TODO: whose coordinate system should this use? bounds : Rect<Au>, // TODO: whose coordinate system should this use?
} }
impl DisplayItemData { pub impl DisplayItemData {
static pure fn new(bounds: &Rect<Au>) -> DisplayItemData { fn new(bounds: &Rect<Au>) -> DisplayItemData {
DisplayItemData { bounds: copy *bounds } DisplayItemData { bounds: copy *bounds }
} }
} }
@ -31,8 +30,8 @@ pub enum DisplayItem {
Border(DisplayItemData, Au, Color) Border(DisplayItemData, Au, Color)
} }
impl DisplayItem { pub impl DisplayItem {
pure fn d(&self) -> &self/DisplayItemData { fn d(&self) -> &'self DisplayItemData {
match *self { match *self {
SolidColor(ref d, _) => d, SolidColor(ref d, _) => d,
Text(ref d, _, _, _) => d, Text(ref d, _, _, _) => d,
@ -68,23 +67,23 @@ impl DisplayItem {
() }); () });
} }
static pure fn new_SolidColor(bounds: &Rect<Au>, color: Color) -> DisplayItem { fn new_SolidColor(bounds: &Rect<Au>, color: Color) -> DisplayItem {
SolidColor(DisplayItemData::new(bounds), color) SolidColor(DisplayItemData::new(bounds), color)
} }
static pure fn new_Border(bounds: &Rect<Au>, width: Au, color: Color) -> DisplayItem { fn new_Border(bounds: &Rect<Au>, width: Au, color: Color) -> DisplayItem {
Border(DisplayItemData::new(bounds), width, color) Border(DisplayItemData::new(bounds), width, color)
} }
static pure fn new_Text(bounds: &Rect<Au>, fn new_Text(bounds: &Rect<Au>,
run: ~SendableTextRun, run: ~SendableTextRun,
range: Range, range: Range,
color: Color) -> DisplayItem { color: Color) -> DisplayItem {
Text(DisplayItemData::new(bounds), run, range, color) Text(DisplayItemData::new(bounds), run, range, color)
} }
// ARC should be cloned into ImageData, but Images are not sendable // ARC should be cloned into ImageData, but Images are not sendable
static pure fn new_Image(bounds: &Rect<Au>, image: ARC<~Image>) -> DisplayItem { fn new_Image(bounds: &Rect<Au>, image: ARC<~Image>) -> DisplayItem {
Image(DisplayItemData::new(bounds), image) Image(DisplayItemData::new(bounds), image)
} }
} }
@ -95,7 +94,7 @@ pub struct DisplayList {
} }
pub impl DisplayList { pub impl DisplayList {
static fn new() -> DisplayList { fn new() -> DisplayList {
DisplayList { list: ~[] } DisplayList { list: ~[] }
} }

View file

@ -8,8 +8,7 @@ use text::shaper::ShaperMethods;
use text::{Shaper, TextRun}; use text::{Shaper, TextRun};
use text::shaper::ShaperMethods; use text::shaper::ShaperMethods;
use azure::{AzFloat, AzScaledFontRef, struct__AzDrawOptions, struct__AzGlyph}; use azure::{AzFloat, AzScaledFontRef};
use azure::{struct__AzGlyphBuffer, struct__AzPoint};
use azure::scaled_font::ScaledFont; use azure::scaled_font::ScaledFont;
use azure::azure_hl::{BackendType, ColorPattern}; use azure::azure_hl::{BackendType, ColorPattern};
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
@ -26,18 +25,18 @@ use native;
// resources needed by the graphics layer to draw glyphs. // resources needed by the graphics layer to draw glyphs.
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub type FontHandle/& = quartz::font::QuartzFontHandle; pub type FontHandle = quartz::font::QuartzFontHandle;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub type FontHandle/& = freetype_impl::font::FreeTypeFontHandle; pub type FontHandle = freetype_impl::font::FreeTypeFontHandle;
pub trait FontHandleMethods { pub trait FontHandleMethods {
// an identifier usable by FontContextHandle to recreate this FontHandle. // an identifier usable by FontContextHandle to recreate this FontHandle.
pure fn face_identifier(&self) -> ~str; fn face_identifier(&self) -> ~str;
pure fn family_name(&self) -> ~str; fn family_name(&self) -> ~str;
pure fn face_name(&self) -> ~str; fn face_name(&self) -> ~str;
pure fn is_italic(&self) -> bool; fn is_italic(&self) -> bool;
pure fn boldness(&self) -> CSSFontWeight; fn boldness(&self) -> CSSFontWeight;
fn clone_with_style(&self, fctx: &native::FontContextHandle, style: &UsedFontStyle) -> Result<FontHandle, ()>; fn clone_with_style(&self, fctx: &native::FontContextHandle, style: &UsedFontStyle) -> Result<FontHandle, ()>;
fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex>; fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex>;
@ -53,18 +52,18 @@ pub trait FontHandleMethods {
pub impl FontHandle { pub impl FontHandle {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
static pub fn new_from_buffer(fctx: &native::FontContextHandle, pub fn new_from_buffer(fctx: &native::FontContextHandle,
buf: ~[u8], buf: ~[u8],
style: &SpecifiedFontStyle) style: &SpecifiedFontStyle)
-> Result<FontHandle, ()> { -> Result<FontHandle, ()> {
quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, style) quartz::font::QuartzFontHandle::new_from_buffer(fctx, buf, style)
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
static pub fn new_from_buffer(fctx: &native::FontContextHandle, pub fn new_from_buffer(fctx: &native::FontContextHandle,
buf: ~[u8], buf: ~[u8],
style: &SpecifiedFontStyle) style: &SpecifiedFontStyle)
-> Result<FontHandle, ()> { -> Result<FontHandle, ()> {
freetype_impl::font::FreeTypeFontHandle::new_from_buffer(fctx, @buf, style) freetype_impl::font::FreeTypeFontHandle::new_from_buffer(fctx, @buf, style)
} }
} }
@ -75,11 +74,11 @@ pub type FractionalPixel = float;
pub type FontTableTag = u32; pub type FontTableTag = u32;
trait FontTableTagConversions { trait FontTableTagConversions {
pub pure fn tag_to_str(&self) -> ~str; pub fn tag_to_str(&self) -> ~str;
} }
impl FontTableTagConversions for FontTableTag { impl FontTableTagConversions for FontTableTag {
pub pure fn tag_to_str(&self) -> ~str { pub fn tag_to_str(&self) -> ~str {
unsafe { unsafe {
let reversed = str::raw::from_buf_len(cast::transmute(self), 4); let reversed = str::raw::from_buf_len(cast::transmute(self), 4);
return str::from_chars([reversed.char_at(3), return str::from_chars([reversed.char_at(3),
@ -91,10 +90,10 @@ impl FontTableTagConversions for FontTableTag {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub type FontTable/& = quartz::font::QuartzFontTable; pub type FontTable = quartz::font::QuartzFontTable;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub type FontTable/& = freetype_impl::font::FreeTypeFontTable; pub type FontTable = freetype_impl::font::FreeTypeFontTable;
pub trait FontTableMethods { pub trait FontTableMethods {
fn with_buffer(&self, &fn(*u8, uint)); fn with_buffer(&self, &fn(*u8, uint));
@ -112,7 +111,7 @@ pub struct FontMetrics {
} }
// TODO(Issue #200): use enum from CSS bindings for 'font-weight' // TODO(Issue #200): use enum from CSS bindings for 'font-weight'
#[deriving_eq] #[deriving(Eq)]
pub enum CSSFontWeight { pub enum CSSFontWeight {
FontWeight100, FontWeight100,
FontWeight200, FontWeight200,
@ -126,7 +125,7 @@ pub enum CSSFontWeight {
} }
pub impl CSSFontWeight { pub impl CSSFontWeight {
pub pure 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,
_ => false _ => false
@ -140,7 +139,7 @@ pub impl CSSFontWeight {
// the instance's properties. // the instance's properties.
// //
// For now, the cases are differentiated with a typedef // For now, the cases are differentiated with a typedef
#[deriving_eq] #[deriving(Eq)]
pub struct FontStyle { pub struct FontStyle {
pt_size: float, pt_size: float,
weight: CSSFontWeight, weight: CSSFontWeight,
@ -165,14 +164,14 @@ struct ResolvedFont {
// It's used to swizzle/unswizzle gfx::Font instances when // It's used to swizzle/unswizzle gfx::Font instances when
// communicating across tasks, such as the display list between layout // communicating across tasks, such as the display list between layout
// and render tasks. // and render tasks.
#[deriving_eq] #[deriving(Eq)]
pub struct FontDescriptor { pub struct FontDescriptor {
style: UsedFontStyle, style: UsedFontStyle,
selector: FontSelector, selector: FontSelector,
} }
pub impl FontDescriptor { pub impl FontDescriptor {
static pure fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor { fn new(style: UsedFontStyle, selector: FontSelector) -> FontDescriptor {
FontDescriptor { FontDescriptor {
style: style, style: style,
selector: selector, selector: selector,
@ -181,7 +180,7 @@ pub impl FontDescriptor {
} }
// A FontSelector is a platform-specific strategy for serializing face names. // A FontSelector is a platform-specific strategy for serializing face names.
#[deriving_eq] #[deriving(Eq)]
pub enum FontSelector { pub enum FontSelector {
SelectorPlatformIdentifier(~str), SelectorPlatformIdentifier(~str),
SelectorStubDummy, // aka, use Josephin Sans SelectorStubDummy, // aka, use Josephin Sans
@ -203,7 +202,7 @@ pub struct FontGroup {
} }
pub impl FontGroup { pub impl FontGroup {
static fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup { fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup {
FontGroup { FontGroup {
families: families, families: families,
style: copy *style, style: copy *style,
@ -212,7 +211,7 @@ pub impl FontGroup {
} }
fn create_textrun(&self, text: ~str) -> TextRun { fn create_textrun(&self, text: ~str) -> TextRun {
fail_unless!(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.
return TextRun::new(self.fonts[0], text); return TextRun::new(self.fonts[0], text);
@ -243,11 +242,11 @@ pub struct Font {
} }
pub impl Font { pub impl Font {
static fn new_from_buffer(ctx: &FontContext, fn new_from_buffer(ctx: &FontContext,
buffer: ~[u8], buffer: ~[u8],
style: &SpecifiedFontStyle, style: &SpecifiedFontStyle,
backend: BackendType) backend: BackendType)
-> Result<@mut Font, ()> { -> Result<@mut Font, ()> {
let handle = FontHandle::new_from_buffer(&ctx.handle, buffer, style); let handle = FontHandle::new_from_buffer(&ctx.handle, buffer, style);
let handle = if handle.is_ok() { let handle = if handle.is_ok() {
result::unwrap(handle) result::unwrap(handle)
@ -268,8 +267,8 @@ pub impl Font {
}); });
} }
static fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle, fn new_from_adopted_handle(_fctx: &FontContext, handle: FontHandle,
style: &SpecifiedFontStyle, backend: BackendType) -> @mut Font { style: &SpecifiedFontStyle, backend: BackendType) -> @mut Font {
let metrics = handle.get_metrics(); let metrics = handle.get_metrics();
@mut Font { @mut Font {
@ -282,8 +281,8 @@ pub impl Font {
} }
} }
static fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle, fn new_from_existing_handle(fctx: &FontContext, handle: &FontHandle,
style: &SpecifiedFontStyle, backend: BackendType) -> Result<@mut Font,()> { style: &SpecifiedFontStyle, backend: BackendType) -> Result<@mut Font,()> {
// TODO(Issue #179): convert between specified and used font style here? // TODO(Issue #179): convert between specified and used font style here?
let styled_handle = match handle.clone_with_style(&fctx.handle, style) { let styled_handle = match handle.clone_with_style(&fctx.handle, style) {
@ -334,7 +333,7 @@ pub impl Font {
} }
#[cfg(target_os="macos")] #[cfg(target_os="macos")]
priv fn create_azure_font() -> ScaledFont { priv fn create_azure_font(&mut self) -> ScaledFont {
let cg_font = self.handle.get_CGFont(); let cg_font = self.handle.get_CGFont();
let size = self.style.pt_size as AzFloat; let size = self.style.pt_size as AzFloat;
ScaledFont::new(self.backend, &cg_font, size) ScaledFont::new(self.backend, &cg_font, size)
@ -353,26 +352,21 @@ pub impl Font {
fn draw_text_into_context(&mut self, fn draw_text_into_context(&mut self,
rctx: &RenderContext, rctx: &RenderContext,
run: &TextRun, run: &TextRun,
range: &const 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 core::libc::types::common::c99::{uint16_t, uint32_t};
use azure::{AzDrawOptions, use azure::{struct__AzDrawOptions,
struct__AzDrawOptions,
AzGlyph,
struct__AzGlyph, struct__AzGlyph,
AzGlyphBuffer,
struct__AzGlyphBuffer, struct__AzGlyphBuffer,
struct__AzPoint}; struct__AzPoint};
use azure::azure::bindgen::{AzCreateColorPattern};
use azure::azure::bindgen::{AzDrawTargetFillGlyphs}; use azure::azure::bindgen::{AzDrawTargetFillGlyphs};
use azure::azure::bindgen::{AzReleaseColorPattern};
let target = rctx.get_draw_target(); let target = rctx.get_draw_target();
let azfontref = self.get_azure_font(); let azfontref = self.get_azure_font();
let pattern = ColorPattern(color); let pattern = ColorPattern(color);
let azure_pattern = pattern.azure_color_pattern; let azure_pattern = pattern.azure_color_pattern;
fail_unless!(azure_pattern.is_not_null()); assert!(azure_pattern.is_not_null());
let options = struct__AzDrawOptions { let options = struct__AzDrawOptions {
mAlpha: 1f as AzFloat, mAlpha: 1f as AzFloat,
@ -417,7 +411,7 @@ pub impl Font {
ptr::null()); ptr::null());
} }
fn measure_text(&self, run: &TextRun, range: &const Range) -> RunMetrics { 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);
@ -479,7 +473,7 @@ fn should_get_glyph_indexes() {
let matcher = @FontMatcher(fctx); let matcher = @FontMatcher(fctx);
let font = matcher.get_test_font(); let font = matcher.get_test_font();
let glyph_idx = font.glyph_index('w'); let glyph_idx = font.glyph_index('w');
fail_unless!(glyph_idx == Some(40u as GlyphIndex)); assert!(glyph_idx == Some(40u as GlyphIndex));
} }
fn should_get_glyph_advance() { fn should_get_glyph_advance() {
@ -490,7 +484,7 @@ fn should_get_glyph_advance() {
let matcher = @FontMatcher(fctx); let matcher = @FontMatcher(fctx);
let font = matcher.get_test_font(); let font = matcher.get_test_font();
let x = font.glyph_h_advance(40u as GlyphIndex); let x = font.glyph_h_advance(40u as GlyphIndex);
fail_unless!(x == 15f || x == 16f); assert!(x == 15f || x == 16f);
} }
// Testing thread safety // Testing thread safety
@ -508,7 +502,7 @@ fn should_get_glyph_advance_stress() {
let matcher = @FontMatcher(fctx); let matcher = @FontMatcher(fctx);
let _font = matcher.get_test_font(); let _font = matcher.get_test_font();
let x = font.glyph_h_advance(40u as GlyphIndex); let x = font.glyph_h_advance(40u as GlyphIndex);
fail_unless!(x == 15f || x == 16f); assert!(x == 15f || x == 16f);
chan.send(()); chan.send(());
} }
} }

View file

@ -6,8 +6,7 @@ use util::cache::Cache;
use util::cache::MonoCache; use util::cache::MonoCache;
use azure::azure_hl::BackendType; use azure::azure_hl::BackendType;
use core::hashmap::linear::LinearMap; use core::hashmap::HashMap;
use core::hashmap::linear;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use quartz; use quartz;
@ -16,7 +15,7 @@ use freetype_impl;
use font_context; use font_context;
// TODO(Issue #164): delete, and get default font from font list // TODO(Issue #164): delete, and get default font from font list
const TEST_FONT: [u8 * 33004] = include_bin!("JosefinSans-SemiBold.ttf"); static TEST_FONT: [u8, ..33004] = include_bin!("JosefinSans-SemiBold.ttf");
fn test_font_bin() -> ~[u8] { fn test_font_bin() -> ~[u8] {
return vec::from_fn(33004, |i| TEST_FONT[i]); return vec::from_fn(33004, |i| TEST_FONT[i]);
@ -36,13 +35,13 @@ pub fn dummy_style() -> FontStyle {
} }
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
type FontContextHandle/& = quartz::font_context::QuartzFontContextHandle; type FontContextHandle = quartz::font_context::QuartzFontContextHandle;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
type FontContextHandle/& = freetype_impl::font_context::FreeTypeFontContextHandle; type FontContextHandle = freetype_impl::font_context::FreeTypeFontContextHandle;
pub trait FontContextHandleMethods { pub trait FontContextHandleMethods {
pure fn clone(&const self) -> FontContextHandle; fn clone(&self) -> FontContextHandle;
fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>; fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
} }
@ -50,12 +49,12 @@ pub trait FontContextHandleMethods {
// and typedefs not working well together. It should be removed. // and typedefs not working well together. It should be removed.
pub impl FontContextHandle { pub impl FontContextHandle {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
static pub fn new() -> FontContextHandle { pub fn new() -> FontContextHandle {
quartz::font_context::QuartzFontContextHandle::new() quartz::font_context::QuartzFontContextHandle::new()
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
static pub fn new() -> FontContextHandle { pub fn new() -> FontContextHandle {
freetype_impl::font_context::FreeTypeFontContextHandle::new() freetype_impl::font_context::FreeTypeFontContextHandle::new()
} }
} }
@ -66,17 +65,17 @@ pub struct FontContext {
font_list: Option<FontList>, // only needed by layout font_list: Option<FontList>, // only needed by layout
handle: FontContextHandle, handle: FontContextHandle,
backend: BackendType, backend: BackendType,
generic_fonts: LinearMap<~str,~str>, generic_fonts: HashMap<~str,~str>,
} }
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
pub impl FontContext { pub impl<'self> FontContext {
static fn new(backend: BackendType, needs_font_list: bool) -> FontContext { fn new(backend: BackendType, needs_font_list: bool) -> FontContext {
let handle = FontContextHandle::new(); let handle = FontContextHandle::new();
let font_list = if needs_font_list { Some(FontList::new(&handle)) } else { None }; let font_list = if needs_font_list { Some(FontList::new(&handle)) } else { None };
// TODO: Allow users to specify these. // TODO: Allow users to specify these.
let mut generic_fonts = linear::linear_map_with_capacity(5); let mut generic_fonts = HashMap::with_capacity(5);
generic_fonts.insert(~"serif", ~"Times New Roman"); generic_fonts.insert(~"serif", ~"Times New Roman");
generic_fonts.insert(~"sans-serif", ~"Arial"); generic_fonts.insert(~"sans-serif", ~"Arial");
generic_fonts.insert(~"cursive", ~"Apple Chancery"); generic_fonts.insert(~"cursive", ~"Apple Chancery");
@ -94,11 +93,11 @@ pub impl FontContext {
} }
} }
priv pure fn get_font_list(&self) -> &self/FontList { priv fn get_font_list(&self) -> &'self FontList {
option::get_ref(&self.font_list) self.font_list.get_ref()
} }
fn get_resolved_font_for_style(&mut self, style: &SpecifiedFontStyle) -> @FontGroup { fn get_resolved_font_for_style(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
// TODO(Issue #178, E): implement a cache of FontGroup instances. // TODO(Issue #178, E): implement a cache of FontGroup instances.
self.create_font_group(style) self.create_font_group(style)
} }
@ -119,7 +118,7 @@ pub impl FontContext {
} }
priv fn transform_family(&self, family: &str) -> ~str { priv fn transform_family(&self, family: &str) -> ~str {
// FIXME: Need a find_like() in LinearMap. // FIXME: Need a find_like() in HashMap.
let family = family.to_str(); let family = family.to_str();
debug!("(transform family) searching for `%s`", family); debug!("(transform family) searching for `%s`", family);
match self.generic_fonts.find(&family) { match self.generic_fonts.find(&family) {
@ -129,13 +128,13 @@ pub impl FontContext {
} }
// TODO:(Issue #196): cache font groups on the font context. // TODO:(Issue #196): cache font groups on the font context.
priv fn create_font_group(&mut self, style: &SpecifiedFontStyle) -> @FontGroup { priv fn create_font_group(@mut self, style: &SpecifiedFontStyle) -> @FontGroup {
let mut fonts = ~[]; let mut fonts = ~[];
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::split_char_each(style.families, ',') |family| { for str::each_split_char(style.families, ',') |family| {
let family_name = str::trim(family); let family_name = str::trim(family);
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);
@ -168,7 +167,7 @@ pub impl FontContext {
Err(()) => {} Err(()) => {}
} }
} }
fail_unless!(fonts.len() > 0); assert!(fonts.len() > 0);
// TODO(Issue #179): Split FontStyle into specified and used styles // TODO(Issue #179): Split FontStyle into specified and used styles
let used_style = copy *style; let used_style = copy *style;

View file

@ -1,9 +1,9 @@
use font::{CSSFontWeight, SpecifiedFontStyle, UsedFontStyle}; use font::{CSSFontWeight, SpecifiedFontStyle};
use gfx_font::FontHandleMethods; use gfx_font::FontHandleMethods;
use native::FontHandle; use native::FontHandle;
use gfx_font::FontHandleMethods; use gfx_font::FontHandleMethods;
use core::hashmap::linear; use core::hashmap::HashMap;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use fontconfig; use fontconfig;
@ -13,28 +13,28 @@ use native;
use util::time::time; use util::time::time;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
type FontListHandle/& = quartz::font_list::QuartzFontListHandle; type FontListHandle = quartz::font_list::QuartzFontListHandle;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
type FontListHandle/& = fontconfig::font_list::FontconfigFontListHandle; type FontListHandle = fontconfig::font_list::FontconfigFontListHandle;
pub impl FontListHandle { pub impl FontListHandle {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
static pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> { pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> {
Ok(quartz::font_list::QuartzFontListHandle::new(fctx)) Ok(quartz::font_list::QuartzFontListHandle::new(fctx))
} }
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
static pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> { pub fn new(fctx: &native::FontContextHandle) -> Result<FontListHandle, ()> {
Ok(fontconfig::font_list::FontconfigFontListHandle::new(fctx)) Ok(fontconfig::font_list::FontconfigFontListHandle::new(fctx))
} }
} }
pub type FontFamilyMap = linear::LinearMap<~str, @mut FontFamily>; pub type FontFamilyMap = HashMap<~str, @mut FontFamily>;
trait FontListHandleMethods { trait FontListHandleMethods {
fn get_available_families(&const self, fctx: &native::FontContextHandle) -> FontFamilyMap; fn get_available_families(&self, fctx: &native::FontContextHandle) -> FontFamilyMap;
fn load_variations_for_family(&const self, family: @mut FontFamily); fn load_variations_for_family(&self, family: @mut FontFamily);
} }
pub struct FontList { pub struct FontList {
@ -43,11 +43,11 @@ pub struct FontList {
} }
pub impl FontList { pub impl FontList {
static fn new(fctx: &native::FontContextHandle) -> FontList { fn new(fctx: &native::FontContextHandle) -> FontList {
let handle = result::unwrap(FontListHandle::new(fctx)); let handle = result::unwrap(FontListHandle::new(fctx));
let mut list = FontList { let mut list = FontList {
handle: handle, handle: handle,
family_map: linear::LinearMap::new(), family_map: HashMap::new(),
}; };
list.refresh(fctx); list.refresh(fctx);
return list; return list;
@ -90,7 +90,7 @@ pub impl FontList {
debug!("FontList: %s font family with name=%s", decision, family_name); debug!("FontList: %s font family with name=%s", decision, family_name);
// TODO(Issue #188): look up localized font family names if canonical name not found // TODO(Issue #188): look up localized font family names if canonical name not found
return family.map(|f| **f); family.map(|f| **f)
} }
} }
@ -101,7 +101,7 @@ pub struct FontFamily {
} }
pub impl FontFamily { pub impl FontFamily {
static fn new(family_name: &str) -> FontFamily { fn new(family_name: &str) -> FontFamily {
FontFamily { FontFamily {
family_name: str::from_slice(family_name), family_name: str::from_slice(family_name),
entries: ~[], entries: ~[],
@ -109,9 +109,10 @@ pub impl FontFamily {
} }
priv fn load_family_variations(@mut self, list: &native::FontListHandle) { priv fn load_family_variations(@mut self, list: &native::FontListHandle) {
if self.entries.len() > 0 { return; } let this : &mut FontFamily = self; // FIXME: borrow checker workaround
if this.entries.len() > 0 { return; }
list.load_variations_for_family(self); list.load_variations_for_family(self);
fail_unless!(self.entries.len() > 0); assert!(this.entries.len() > 0);
} }
fn find_font_for_style(@mut self, list: &native::FontListHandle, style: &SpecifiedFontStyle) -> Option<@FontEntry> { fn find_font_for_style(@mut self, list: &native::FontListHandle, style: &SpecifiedFontStyle) -> Option<@FontEntry> {
@ -124,7 +125,8 @@ pub impl FontFamily {
// TODO(Issue #190): if not in the fast path above, do // TODO(Issue #190): if not in the fast path above, do
// expensive matching of weights, etc. // expensive matching of weights, etc.
for self.entries.each |entry| { let this : &mut FontFamily = self; // FIXME: borrow checker workaround
for this.entries.each |entry| {
if (style.weight.is_bold() == entry.is_bold()) && if (style.weight.is_bold() == entry.is_bold()) &&
(style.italic == entry.is_italic()) { (style.italic == entry.is_italic()) {
@ -151,7 +153,7 @@ pub struct FontEntry {
} }
pub impl FontEntry { pub impl FontEntry {
static fn new(family: @mut FontFamily, handle: FontHandle) -> FontEntry { fn new(family: @mut FontFamily, handle: FontHandle) -> FontEntry {
FontEntry { FontEntry {
family: family, family: family,
face_name: handle.face_name(), face_name: handle.face_name(),
@ -161,9 +163,9 @@ pub impl FontEntry {
} }
} }
pure fn is_bold(&self) -> bool { fn is_bold(&self) -> bool {
self.weight.is_bold() self.weight.is_bold()
} }
pure fn is_italic(&self) -> bool { self.italic } fn is_italic(&self) -> bool { self.italic }
} }

View file

@ -29,7 +29,7 @@ pub struct FontconfigFontListHandle {
} }
pub impl FontconfigFontListHandle { pub impl FontconfigFontListHandle {
static pub fn new(fctx: &native::FontContextHandle) -> FontconfigFontListHandle { pub fn new(fctx: &native::FontContextHandle) -> FontconfigFontListHandle {
FontconfigFontListHandle { fctx: fctx.clone() } FontconfigFontListHandle { fctx: fctx.clone() }
} }

View file

@ -100,7 +100,7 @@ impl Drop for FreeTypeFontHandle {
} }
pub impl FreeTypeFontHandle { pub impl FreeTypeFontHandle {
static 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;
@ -110,8 +110,8 @@ pub impl FreeTypeFontHandle {
if result.succeeded() { Ok(()) } else { Err(()) } if result.succeeded() { Ok(()) } else { Err(()) }
} }
static pub fn new_from_file(fctx: &FreeTypeFontContextHandle, file: ~str, pub fn new_from_file(fctx: &FreeTypeFontContextHandle, file: ~str,
style: &SpecifiedFontStyle) -> Result<FreeTypeFontHandle, ()> { style: &SpecifiedFontStyle) -> Result<FreeTypeFontHandle, ()> {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
@ -131,7 +131,7 @@ pub impl FreeTypeFontHandle {
} }
} }
static pub fn new_from_file_unstyled(fctx: &FreeTypeFontContextHandle, file: ~str) pub fn new_from_file_unstyled(fctx: &FreeTypeFontContextHandle, file: ~str)
-> Result<FreeTypeFontHandle, ()> { -> Result<FreeTypeFontHandle, ()> {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
@ -149,8 +149,8 @@ pub impl FreeTypeFontHandle {
Ok(FreeTypeFontHandle { source: FontSourceFile(file), face: face }) Ok(FreeTypeFontHandle { source: FontSourceFile(file), face: face })
} }
static pub fn new_from_buffer(fctx: &FreeTypeFontContextHandle, pub fn new_from_buffer(fctx: &FreeTypeFontContextHandle,
buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FreeTypeFontHandle, ()> { buf: @~[u8], style: &SpecifiedFontStyle) -> Result<FreeTypeFontHandle, ()> {
let ft_ctx: FT_Library = fctx.ctx.ctx; let ft_ctx: FT_Library = fctx.ctx.ctx;
if ft_ctx.is_null() { return Err(()); } if ft_ctx.is_null() { return Err(()); }
@ -189,21 +189,21 @@ pub impl FreeTypeFontHandle {
impl FontHandleMethods for FreeTypeFontHandle { impl FontHandleMethods for FreeTypeFontHandle {
// an identifier usable by FontContextHandle to recreate this FontHandle. // an identifier usable by FontContextHandle to recreate this FontHandle.
pure fn face_identifier(&self) -> ~str { fn face_identifier(&self) -> ~str {
/* FT_Get_Postscript_Name seems like a better choice here, but it /* FT_Get_Postscript_Name seems like a better choice here, but it
doesn't give usable results for fontconfig when deserializing. */ doesn't give usable results for fontconfig when deserializing. */
unsafe { str::raw::from_c_str((*self.face).family_name) } unsafe { str::raw::from_c_str((*self.face).family_name) }
} }
pure fn family_name(&self) -> ~str { fn family_name(&self) -> ~str {
unsafe { str::raw::from_c_str((*self.face).family_name) } unsafe { str::raw::from_c_str((*self.face).family_name) }
} }
pure fn face_name(&self) -> ~str { fn face_name(&self) -> ~str {
unsafe { str::raw::from_c_str(FT_Get_Postscript_Name(self.face)) } unsafe { str::raw::from_c_str(FT_Get_Postscript_Name(self.face)) }
} }
pure fn is_italic(&self) -> bool { fn is_italic(&self) -> bool {
unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 } unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 }
} }
pure fn boldness(&self) -> CSSFontWeight { fn boldness(&self) -> CSSFontWeight {
let default_weight = FontWeight400; let default_weight = FontWeight400;
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
@ -305,7 +305,7 @@ impl FontHandleMethods for FreeTypeFontHandle {
} }
pub impl FreeTypeFontHandle { pub impl FreeTypeFontHandle {
priv fn get_face_rec(&self) -> &self/FT_FaceRec { priv fn get_face_rec(&self) -> &'self FT_FaceRec {
unsafe { unsafe {
&(*self.face) &(*self.face)
} }

View file

@ -35,7 +35,7 @@ pub struct FreeTypeFontContextHandle {
} }
pub impl FreeTypeFontContextHandle { pub impl FreeTypeFontContextHandle {
static pub fn new() -> FreeTypeFontContextHandle { pub fn new() -> FreeTypeFontContextHandle {
let ctx: FT_Library = ptr::null(); let ctx: FT_Library = ptr::null();
let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx)); let result = FT_Init_FreeType(ptr::to_unsafe_ptr(&ctx));
if !result.succeeded() { fail!(); } if !result.succeeded() { fail!(); }
@ -47,7 +47,7 @@ pub impl FreeTypeFontContextHandle {
} }
impl FontContextHandleMethods for FreeTypeFontContextHandle { impl FontContextHandleMethods for FreeTypeFontContextHandle {
pure fn clone(&const self) -> FreeTypeFontContextHandle { fn clone(&self) -> FreeTypeFontContextHandle {
FreeTypeFontContextHandle { ctx: self.ctx } FreeTypeFontContextHandle { ctx: self.ctx }
} }

View file

@ -7,62 +7,62 @@ use core::num::NumCast;
pub struct Au(i32); pub struct Au(i32);
impl Add<Au,Au> for Au { impl Add<Au,Au> for Au {
pure fn add(&self, other: &Au) -> Au { Au(**self + **other) } fn add(&self, other: &Au) -> Au { Au(**self + **other) }
} }
impl Sub<Au,Au> for Au { impl Sub<Au,Au> for Au {
pure fn sub(&self, other: &Au) -> Au { Au(**self - **other) } fn sub(&self, other: &Au) -> Au { Au(**self - **other) }
} }
impl Mul<Au,Au> for Au { impl Mul<Au,Au> for Au {
pure fn mul(&self, other: &Au) -> Au { Au(**self * **other) } fn mul(&self, other: &Au) -> Au { Au(**self * **other) }
} }
impl Div<Au,Au> for Au { impl Div<Au,Au> for Au {
pure fn div(&self, other: &Au) -> Au { Au(**self / **other) } fn div(&self, other: &Au) -> Au { Au(**self / **other) }
} }
impl Modulo<Au,Au> for Au { impl Modulo<Au,Au> for Au {
pure fn modulo(&self, other: &Au) -> Au { Au(**self % **other) } fn modulo(&self, other: &Au) -> Au { Au(**self % **other) }
} }
impl Neg<Au> for Au { impl Neg<Au> for Au {
pure fn neg(&self) -> Au { Au(-**self) } fn neg(&self) -> Au { Au(-**self) }
} }
impl cmp::Ord for Au { impl cmp::Ord for Au {
pure fn lt(&self, other: &Au) -> bool { **self < **other } fn lt(&self, other: &Au) -> bool { **self < **other }
pure fn le(&self, other: &Au) -> bool { **self <= **other } fn le(&self, other: &Au) -> bool { **self <= **other }
pure fn ge(&self, other: &Au) -> bool { **self >= **other } fn ge(&self, other: &Au) -> bool { **self >= **other }
pure fn gt(&self, other: &Au) -> bool { **self > **other } fn gt(&self, other: &Au) -> bool { **self > **other }
} }
impl cmp::Eq for Au { impl cmp::Eq for Au {
pure fn eq(&self, other: &Au) -> bool { **self == **other } fn eq(&self, other: &Au) -> bool { **self == **other }
pure fn ne(&self, other: &Au) -> bool { **self != **other } fn ne(&self, other: &Au) -> bool { **self != **other }
} }
pub pure fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } } pub fn min(x: Au, y: Au) -> Au { if x < y { x } else { y } }
pub pure fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } } pub fn max(x: Au, y: Au) -> Au { if x > y { x } else { y } }
impl NumCast for Au { impl NumCast for Au {
static pure fn from<T:NumCast>(n: T) -> Au { Au(n.to_i32()) } fn from<T:NumCast>(n: T) -> Au { Au(n.to_i32()) }
pure fn to_u8(&self) -> u8 { (**self).to_u8() } fn to_u8(&self) -> u8 { (**self).to_u8() }
pure fn to_u16(&self) -> u16 { (**self).to_u16() } fn to_u16(&self) -> u16 { (**self).to_u16() }
pure fn to_u32(&self) -> u32 { (**self).to_u32() } fn to_u32(&self) -> u32 { (**self).to_u32() }
pure fn to_u64(&self) -> u64 { (**self).to_u64() } fn to_u64(&self) -> u64 { (**self).to_u64() }
pure fn to_uint(&self) -> uint { (**self).to_uint() } fn to_uint(&self) -> uint { (**self).to_uint() }
pure fn to_i8(&self) -> i8 { (**self).to_i8() } fn to_i8(&self) -> i8 { (**self).to_i8() }
pure fn to_i16(&self) -> i16 { (**self).to_i16() } fn to_i16(&self) -> i16 { (**self).to_i16() }
pure fn to_i32(&self) -> i32 { (**self).to_i32() } fn to_i32(&self) -> i32 { (**self).to_i32() }
pure fn to_i64(&self) -> i64 { (**self).to_i64() } fn to_i64(&self) -> i64 { (**self).to_i64() }
pure fn to_int(&self) -> int { (**self).to_int() } fn to_int(&self) -> int { (**self).to_int() }
pure fn to_f32(&self) -> f32 { (**self).to_f32() } fn to_f32(&self) -> f32 { (**self).to_f32() }
pure fn to_f64(&self) -> f64 { (**self).to_f64() } fn to_f64(&self) -> f64 { (**self).to_f64() }
pure 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:Copy + Ord + Add<T,T> + Sub<T,T>>(x: T, y: T, w: T, h: T) -> Rect<T> {
@ -70,76 +70,76 @@ pub fn box<T:Copy + Ord + Add<T,T> + Sub<T,T>>(x: T, y: T, w: T, h: T) -> Rect<T
} }
pub impl Au { pub impl Au {
pub pure 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)
} }
static pub pure fn from_px(i: int) -> Au { pub fn from_px(i: int) -> Au {
NumCast::from(i * 60) NumCast::from(i * 60)
} }
pub pure fn to_px(&const self) -> int { pub fn to_px(&self) -> int {
(**self / 60) as int (**self / 60) as int
} }
pub pure fn to_snapped(&const self) -> Au { pub fn to_snapped(&self) -> Au {
let res = **self % 60i32; let res = **self % 60i32;
return if res >= 30i32 { return Au(**self - res + 60i32) } return if res >= 30i32 { return Au(**self - res + 60i32) }
else { return Au(**self - res) }; else { return Au(**self - res) };
} }
static pub pure fn zero_point() -> Point2D<Au> { pub fn zero_point() -> Point2D<Au> {
Point2D(Au(0), Au(0)) Point2D(Au(0), Au(0))
} }
static pub pure fn zero_rect() -> Rect<Au> { pub fn zero_rect() -> Rect<Au> {
let z = Au(0); let z = Au(0);
Rect(Point2D(z, z), Size2D(z, z)) Rect(Point2D(z, z), Size2D(z, z))
} }
// assumes 72 points per inch, and 96 px per inch // assumes 72 points per inch, and 96 px per inch
static pub pure fn from_pt(f: float) -> Au { pub fn from_pt(f: float) -> Au {
from_px((f / 72f * 96f) as int) from_px((f / 72f * 96f) as int)
} }
static pub pure fn from_frac_px(f: float) -> Au { pub fn from_frac_px(f: float) -> Au {
Au((f * 60f) as i32) Au((f * 60f) as i32)
} }
static pub pure fn min(x: Au, y: Au) -> Au { if *x < *y { x } else { y } } pub fn min(x: Au, y: Au) -> Au { if *x < *y { x } else { y } }
static pub pure fn max(x: Au, y: Au) -> Au { if *x > *y { x } else { y } } pub fn max(x: Au, y: Au) -> Au { if *x > *y { x } else { y } }
} }
pub pure fn zero_rect() -> Rect<Au> { pub fn zero_rect() -> Rect<Au> {
let z = Au(0); let z = Au(0);
Rect(Point2D(z, z), Size2D(z, z)) Rect(Point2D(z, z), Size2D(z, z))
} }
pub pure fn zero_point() -> Point2D<Au> { pub fn zero_point() -> Point2D<Au> {
Point2D(Au(0), Au(0)) Point2D(Au(0), Au(0))
} }
pub pure fn zero_size() -> Size2D<Au> { pub fn zero_size() -> Size2D<Au> {
Size2D(Au(0), Au(0)) Size2D(Au(0), Au(0))
} }
pub pure fn from_frac_px(f: float) -> Au { pub fn from_frac_px(f: float) -> Au {
Au((f * 60f) as i32) Au((f * 60f) as i32)
} }
pub pure fn from_px(i: int) -> Au { pub fn from_px(i: int) -> Au {
NumCast::from(i * 60) NumCast::from(i * 60)
} }
pub pure fn to_px(au: Au) -> int { pub fn to_px(au: Au) -> int {
(*au / 60) as int (*au / 60) as int
} }
pub pure fn to_frac_px(au: Au) -> float { pub fn to_frac_px(au: Au) -> float {
(*au as float) / 60f (*au as float) / 60f
} }
// assumes 72 points per inch, and 96 px per inch // assumes 72 points per inch, and 96 px per inch
pub pure fn from_pt(f: float) -> Au { pub fn from_pt(f: float) -> Au {
from_px((f / 72f * 96f) as int) from_px((f / 72f * 96f) as int)
} }

View file

@ -9,7 +9,7 @@ pub fn Image(width: uint, height: uint, depth: uint, data: ~[u8]) -> Image {
stb_image::new_image(width, height, depth, data) stb_image::new_image(width, height, depth, data)
} }
const TEST_IMAGE: [u8 * 4962] = include_bin!("test.jpeg"); static TEST_IMAGE: [u8, ..4962] = include_bin!("test.jpeg");
pub fn test_image_bin() -> ~[u8] { pub fn test_image_bin() -> ~[u8] {
return vec::from_fn(4962, |i| TEST_IMAGE[i]); return vec::from_fn(4962, |i| TEST_IMAGE[i]);
@ -18,11 +18,11 @@ pub fn test_image_bin() -> ~[u8] {
pub fn load_from_memory(buffer: &[u8]) -> Option<Image> { pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
// Can't remember why we do this. Maybe it's what cairo wants // Can't remember why we do this. Maybe it's what cairo wants
const FORCE_DEPTH: uint = 4; static FORCE_DEPTH: uint = 4;
match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) { match stb_image::load_from_memory_with_depth(buffer, FORCE_DEPTH, true) {
stb_image::ImageU8(image) => { stb_image::ImageU8(image) => {
fail_unless!(image.depth == 4); assert!(image.depth == 4);
// Do color space conversion :( // Do color space conversion :(
let data = do vec::from_fn(image.width * image.height * 4) |i| { let data = do vec::from_fn(image.width * image.height * 4) |i| {
let color = i % 4; let color = i % 4;
@ -36,7 +36,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
} }
}; };
fail_unless!(image.data.len() == data.len()); assert!(image.data.len() == data.len());
Some(Image(image.width, image.height, image.depth, data)) Some(Image(image.width, image.height, image.depth, data))
} }

View file

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

View file

@ -1,6 +1,5 @@
use image::base::Image; use image::base::Image;
use resource::image_cache_task::{ImageCacheTask, ImageReady, ImageNotReady, ImageFailed}; use resource::image_cache_task::{ImageReady, ImageNotReady, ImageFailed};
use resource::image_cache_task;
use resource::local_image_cache::LocalImageCache; use resource::local_image_cache::LocalImageCache;
use core::util::replace; use core::util::replace;
@ -23,25 +22,25 @@ pub struct ImageHolder {
} }
pub impl ImageHolder { pub impl ImageHolder {
static 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 {
url: url, url: url,
image: None, image: None,
cached_size: Size2D(0,0), cached_size: Size2D(0,0),
local_image_cache: local_image_cache, local_image_cache: local_image_cache,
}; };
// Tell the image cache we're going to be interested in this url // Tell the image cache we're going to be interested in this url
// FIXME: These two messages must be sent to prep an image for use // FIXME: These two messages must be sent to prep an image for use
// but they are intended to be spread out in time. Ideally prefetch // but they are intended to be spread out in time. Ideally prefetch
// should be done as early as possible and decode only once we // should be done as early as possible and decode only once we
// are sure that the image will be used. // are sure that the image will be used.
local_image_cache.prefetch(&holder.url); local_image_cache.prefetch(&holder.url);
local_image_cache.decode(&holder.url); local_image_cache.decode(&holder.url);
holder holder
} }
/** /**
This version doesn't perform any computation, but may be stale w.r.t. This version doesn't perform any computation, but may be stale w.r.t.
@ -50,7 +49,7 @@ pub impl ImageHolder {
The intent is that the impure version is used during layout when The intent is that the impure version is used during layout when
dimensions are used for computing layout. dimensions are used for computing layout.
*/ */
pure fn size(&self) -> Size2D<int> { fn size(&self) -> Size2D<int> {
self.cached_size self.cached_size
} }

View file

@ -9,22 +9,19 @@ use gfx_font::{CSSFontWeight, FontHandleMethods, FontMetrics, FontTable, FontTab
use gfx_font::{FontTableTag, FontWeight100, FontWeight200, FontWeight300, FontWeight400}; use gfx_font::{FontTableTag, FontWeight100, FontWeight200, FontWeight300, FontWeight400};
use gfx_font::{FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900}; use gfx_font::{FontWeight500, FontWeight600, FontWeight700, FontWeight800, FontWeight900};
use gfx_font::{FractionalPixel, SpecifiedFontStyle}; use gfx_font::{FractionalPixel, SpecifiedFontStyle};
use quartz::font::core_foundation::base::{CFIndex, CFTypeRef, CFWrapper}; use quartz::font::core_foundation::base::{CFIndex, CFWrapper};
use quartz::font::core_foundation::data::{CFData, CFDataRef}; use quartz::font::core_foundation::data::CFData;
use quartz::font::core_foundation::string::UniChar; use quartz::font::core_foundation::string::UniChar;
use quartz::font::core_graphics::base::{CGFloat, CGAffineTransform}; use quartz::font::core_graphics::data_provider::CGDataProvider;
use quartz::font::core_graphics::data_provider::{CGDataProviderRef, CGDataProvider}; use quartz::font::core_graphics::font::{CGFont, CGGlyph};
use quartz::font::core_graphics::font::{CGFont, CGFontRef, CGGlyph};
use quartz::font::core_graphics::geometry::CGRect; use quartz::font::core_graphics::geometry::CGRect;
use quartz::font::core_text::font::CTFont; use quartz::font::core_text::font::{CTFont, CTFontMethods, CTFontMethodsPrivate};
use quartz::font::core_text::font_descriptor::{SymbolicTraitAccessors}; use quartz::font::core_text::font_descriptor::{SymbolicTraitAccessors, TraitAccessors};
use quartz::font::core_text::font_descriptor::{kCTFontDefaultOrientation, CTFontSymbolicTraits}; use quartz::font::core_text::font_descriptor::kCTFontDefaultOrientation;
use quartz::font_context::QuartzFontContextHandle; use quartz::font_context::QuartzFontContextHandle;
use quartz; use quartz;
use text::glyph::GlyphIndex; use text::glyph::GlyphIndex;
use core::libc::size_t;
struct QuartzFontTable { struct QuartzFontTable {
data: CFData, data: CFData,
} }
@ -34,27 +31,25 @@ struct QuartzFontTable {
impl Drop for QuartzFontTable { fn finalize(&self) {} } impl Drop for QuartzFontTable { fn finalize(&self) {} }
pub impl QuartzFontTable { pub impl QuartzFontTable {
static fn wrap(data: CFData) -> QuartzFontTable { fn wrap(data: CFData) -> QuartzFontTable {
QuartzFontTable { data: data } QuartzFontTable { data: data }
} }
} }
impl FontTableMethods for QuartzFontTable { impl FontTableMethods for QuartzFontTable {
fn with_buffer(blk: &fn(*u8, uint)) { fn with_buffer(&self, blk: &fn(*u8, uint)) {
blk(self.data.bytes(), self.data.len()); blk(self.data.bytes(), self.data.len());
} }
} }
pub struct QuartzFontHandle { pub struct QuartzFontHandle {
priv mut cgfont: Option<CGFont>, priv cgfont: Option<CGFont>,
ctfont: CTFont, ctfont: CTFont,
drop { }
} }
pub impl QuartzFontHandle { pub impl QuartzFontHandle {
static fn new_from_buffer(_fctx: &QuartzFontContextHandle, buf: ~[u8], fn new_from_buffer(_fctx: &QuartzFontContextHandle, buf: ~[u8],
style: &SpecifiedFontStyle) -> Result<QuartzFontHandle, ()> { style: &SpecifiedFontStyle) -> Result<QuartzFontHandle, ()> {
let fontprov : CGDataProvider = vec::as_imm_buf(buf, |cbuf, len| { let fontprov : CGDataProvider = vec::as_imm_buf(buf, |cbuf, len| {
quartz::font::core_graphics::data_provider::new_from_buffer(cbuf, len) quartz::font::core_graphics::data_provider::new_from_buffer(cbuf, len)
}); });
@ -70,7 +65,7 @@ pub impl QuartzFontHandle {
return result; return result;
} }
static fn new_from_CTFont(_fctx: &QuartzFontContextHandle, ctfont: CTFont) -> Result<QuartzFontHandle, ()> { fn new_from_CTFont(_fctx: &QuartzFontContextHandle, ctfont: CTFont) -> Result<QuartzFontHandle, ()> {
let result = Ok(QuartzFontHandle { let result = Ok(QuartzFontHandle {
mut cgfont: None, mut cgfont: None,
ctfont: ctfont, ctfont: ctfont,
@ -79,9 +74,9 @@ pub impl QuartzFontHandle {
return result; return result;
} }
fn get_CGFont() -> CGFont { fn get_CGFont(&mut self) -> CGFont {
match self.cgfont { match self.cgfont {
Some(ref font) => CFWrapper::wrap_shared(*font.borrow_ref()), Some(ref font) => CFWrapper::wrap_shared(*(font.borrow_ref())),
None => { None => {
let cgfont = self.ctfont.copy_to_CGFont(); let cgfont = self.ctfont.copy_to_CGFont();
self.cgfont = Some(CFWrapper::clone(&cgfont)); self.cgfont = Some(CFWrapper::clone(&cgfont));
@ -92,19 +87,19 @@ pub impl QuartzFontHandle {
} }
impl FontHandleMethods for QuartzFontHandle { impl FontHandleMethods for QuartzFontHandle {
pure fn family_name() -> ~str { fn family_name(&self) -> ~str {
self.ctfont.family_name() self.ctfont.family_name()
} }
pure fn face_name() -> ~str { fn face_name(&self) -> ~str {
self.ctfont.face_name() self.ctfont.face_name()
} }
pure fn is_italic() -> bool { fn is_italic(&self) -> bool {
self.ctfont.symbolic_traits().is_italic() self.ctfont.symbolic_traits().is_italic()
} }
pure fn boldness() -> CSSFontWeight { fn boldness(&self) -> CSSFontWeight {
// -1.0 to 1.0 // -1.0 to 1.0
let normalized = unsafe { self.ctfont.all_traits().normalized_weight() }; let normalized = unsafe { self.ctfont.all_traits().normalized_weight() };
// 0.0 to 9.0 // 0.0 to 9.0
@ -120,16 +115,16 @@ impl FontHandleMethods for QuartzFontHandle {
return FontWeight900; return FontWeight900;
} }
fn clone_with_style(fctx: &QuartzFontContextHandle, fn clone_with_style(&self, fctx: &QuartzFontContextHandle,
style: &SpecifiedFontStyle) style: &SpecifiedFontStyle)
-> Result<QuartzFontHandle,()> { -> Result<QuartzFontHandle,()> {
let new_font = self.ctfont.clone_with_font_size(style.pt_size); let new_font = self.ctfont.clone_with_font_size(style.pt_size);
return QuartzFontHandle::new_from_CTFont(fctx, new_font); return QuartzFontHandle::new_from_CTFont(fctx, new_font);
} }
fn glyph_index(codepoint: char) -> Option<GlyphIndex> { fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
let characters: [UniChar * 1] = [codepoint as UniChar]; let characters: [UniChar, ..1] = [codepoint as UniChar];
let glyphs: [CGGlyph * 1] = [0 as CGGlyph]; let glyphs: [CGGlyph, ..1] = [0 as CGGlyph];
let count: CFIndex = 1; let count: CFIndex = 1;
let result = self.ctfont.get_glyphs_for_characters(ptr::to_unsafe_ptr(&characters[0]), let result = self.ctfont.get_glyphs_for_characters(ptr::to_unsafe_ptr(&characters[0]),
@ -141,11 +136,11 @@ impl FontHandleMethods for QuartzFontHandle {
return None; return None;
} }
fail_unless!(glyphs[0] != 0); // FIXME: error handling assert!(glyphs[0] != 0); // FIXME: error handling
return Some(glyphs[0] as GlyphIndex); return Some(glyphs[0] as GlyphIndex);
} }
fn glyph_h_advance(glyph: GlyphIndex) -> Option<FractionalPixel> { fn glyph_h_advance(&self, glyph: GlyphIndex) -> Option<FractionalPixel> {
let glyphs = [glyph as CGGlyph]; let glyphs = [glyph as CGGlyph];
unsafe { unsafe {
let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation, let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation,
@ -156,7 +151,7 @@ impl FontHandleMethods for QuartzFontHandle {
} }
} }
fn get_metrics() -> FontMetrics { fn get_metrics(&self) -> FontMetrics {
let bounding_rect: CGRect = self.ctfont.bounding_box(); let bounding_rect: CGRect = self.ctfont.bounding_box();
let ascent = Au::from_pt(self.ctfont.ascent() as float); let ascent = Au::from_pt(self.ctfont.ascent() as float);
let descent = Au::from_pt(self.ctfont.descent() as float); let descent = Au::from_pt(self.ctfont.descent() as float);
@ -181,14 +176,14 @@ impl FontHandleMethods for QuartzFontHandle {
return metrics; return metrics;
} }
fn get_table_for_tag(tag: FontTableTag) -> Option<FontTable> { fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
let result : Option<CFData> = self.ctfont.get_font_table(tag); let result : Option<CFData> = self.ctfont.get_font_table(tag);
return option::chain(result, |data| { result.chain(|data| {
Some(QuartzFontTable::wrap(data)) Some(QuartzFontTable::wrap(data))
}); })
} }
pure fn face_identifier() -> ~str { fn face_identifier(&self) -> ~str {
self.ctfont.postscript_name() self.ctfont.postscript_name()
} }
} }

View file

@ -4,34 +4,31 @@ extern mod core_text;
use quartz; use quartz;
use quartz::font::QuartzFontHandle; use quartz::font::QuartzFontHandle;
use quartz::font_context::core_text::font::CTFont;
use gfx_font::{FontHandle, UsedFontStyle}; use gfx_font::{FontHandle, UsedFontStyle};
use gfx_font_context::FontContextHandleMethods; use gfx_font_context::FontContextHandleMethods;
pub struct QuartzFontContextHandle { pub struct QuartzFontContextHandle {
ctx: (), ctx: ()
drop { }
} }
pub impl QuartzFontContextHandle { pub impl QuartzFontContextHandle {
// this is a placeholder until NSFontManager or whatever is bound in here. // this is a placeholder until NSFontManager or whatever is bound in here.
static pub fn new() -> QuartzFontContextHandle { pub fn new() -> QuartzFontContextHandle {
QuartzFontContextHandle { ctx: () } QuartzFontContextHandle { ctx: () }
} }
} }
impl FontContextHandleMethods for QuartzFontContextHandle { impl FontContextHandleMethods for QuartzFontContextHandle {
pure fn clone(&const self) -> QuartzFontContextHandle { fn clone(&self) -> QuartzFontContextHandle {
QuartzFontContextHandle { ctx: self.ctx } QuartzFontContextHandle { ctx: self.ctx }
} }
fn create_font_from_identifier(name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> { fn create_font_from_identifier(&self, name: ~str, style: UsedFontStyle) -> Result<FontHandle, ()> {
let ctfont_result = quartz::font_context::core_text::font::new_from_name(name, let ctfont_result = quartz::font_context::core_text::font::new_from_name(name,
style.pt_size); style.pt_size);
do result::chain(ctfont_result) |ctfont| { do result::chain(ctfont_result) |ctfont| {
QuartzFontHandle::new_from_CTFont(&self, ctfont) QuartzFontHandle::new_from_CTFont(self, ctfont)
} }
} }
} }

View file

@ -7,45 +7,43 @@ use quartz::font_list::core_foundation::array::CFArray;
use quartz::font_list::core_foundation::base::CFWrapper; use quartz::font_list::core_foundation::base::CFWrapper;
use quartz::font_list::core_foundation::string::{CFString, CFStringRef}; use quartz::font_list::core_foundation::string::{CFString, CFStringRef};
use quartz::font_list::core_text::font::{CTFont, debug_font_names, debug_font_traits}; use quartz::font_list::core_text::font_descriptor::CTFontDescriptorRef;
use quartz::font_list::core_text::font_collection::CTFontCollection; use quartz::font_list::core_text::font_collection::CTFontCollectionMethods;
use quartz::font_list::core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef};
use quartz::font_list::core_text::font_descriptor::{debug_descriptor};
use quartz::font::QuartzFontHandle; use quartz::font::QuartzFontHandle;
use quartz::font_context::QuartzFontContextHandle; use quartz::font_context::QuartzFontContextHandle;
use gfx_font::{FontHandle, FontHandleMethods}; use gfx_font::FontHandleMethods;
use gfx_font_context::FontContextHandleMethods; use gfx_font_context::FontContextHandleMethods;
use gfx_font_list::{FontEntry, FontFamily, FontFamilyMap}; use gfx_font_list::{FontEntry, FontFamily, FontFamilyMap};
use core::dvec::DVec; use core::hashmap::HashMap;
use core::hashmap::linear::LinearMap;
pub struct QuartzFontListHandle { pub struct QuartzFontListHandle {
fctx: QuartzFontContextHandle, fctx: QuartzFontContextHandle,
} }
pub impl QuartzFontListHandle { pub impl QuartzFontListHandle {
static fn new(fctx: &native::FontContextHandle) -> QuartzFontListHandle { fn new(fctx: &native::FontContextHandle) -> QuartzFontListHandle {
QuartzFontListHandle { fctx: fctx.clone() } QuartzFontListHandle { fctx: fctx.clone() }
} }
fn get_available_families() -> FontFamilyMap { fn get_available_families(&self) -> FontFamilyMap {
let family_names: CFArray<CFStringRef> = let family_names: CFArray<CFStringRef> =
quartz::font_list::core_text::font_collection::get_family_names(); quartz::font_list::core_text::font_collection::get_family_names();
let mut family_map : FontFamilyMap = LinearMap::new(); let mut family_map : FontFamilyMap = HashMap::new();
for family_names.each |&strref: &CFStringRef| { for family_names.each |&strref: &CFStringRef| {
let family_name = CFString::wrap_extern(strref).to_str(); let family_name = CFString::wrap_extern(strref).to_str();
debug!("Creating new FontFamily for family: %s", family_name); debug!("Creating new FontFamily for family: %s", family_name);
let new_family = @FontFamily::new(family_name); let new_family = @mut FontFamily::new(family_name);
family_map.insert(family_name, new_family); family_map.insert(family_name, new_family);
} }
return family_map; return family_map;
} }
fn load_variations_for_family(family: @FontFamily) { fn load_variations_for_family(&self, family: @mut FontFamily) {
let family_name = &family.family_name; let fam : &mut FontFamily = family; // FIXME: borrow checker workaround
let family_name = &fam.family_name;
debug!("Looking for faces of family: %s", *family_name); debug!("Looking for faces of family: %s", *family_name);
let family_collection = let family_collection =

View file

@ -3,27 +3,25 @@ use font_context::FontContext;
use geometry::Au; use geometry::Au;
use image::base::Image; use image::base::Image;
use opts::Opts; use opts::Opts;
use text::TextRun;
use azure::azure_hl::{AsAzureRect, 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::{AzDrawOptions, AzFloat}; use azure::AzFloat;
use core::libc::types::common::c99::uint16_t; use core::libc::types::common::c99::uint16_t;
use core::ptr::to_unsafe_ptr;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use std::arc; use std::arc;
use std::arc::ARC; use std::arc::ARC;
pub struct RenderContext { pub struct RenderContext<'self> {
canvas: &'self LayerBuffer, canvas: &'self LayerBuffer,
font_ctx: @mut FontContext, font_ctx: @mut FontContext,
opts: &'self Opts opts: &'self Opts
} }
pub impl<'self> RenderContext<'self> { pub 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
} }

View file

@ -3,25 +3,20 @@ use display_list::DisplayList;
use opts::Opts; use opts::Opts;
use util::time; use util::time;
use azure::AzFloat;
use azure::azure_hl::{B8G8R8A8, DrawTarget}; use azure::azure_hl::{B8G8R8A8, DrawTarget};
use core::libc::c_int;
use core::comm::Chan; use core::comm::Chan;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use std::arc::ARC;
use std::arc;
pub struct RenderLayer { pub struct RenderLayer {
display_list: DisplayList, display_list: DisplayList,
size: Size2D<uint> size: Size2D<uint>
} }
type RenderFn = &'self fn(layer: *RenderLayer, type RenderFn<'self> = &'self fn(layer: *RenderLayer,
buffer: LayerBuffer, buffer: LayerBuffer,
return_buffer: Chan<LayerBuffer>); return_buffer: Chan<LayerBuffer>);
/// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format) /// Given a layer and a buffer, either reuses the buffer (if it's of the right size and format)
/// or creates a new buffer (if it's not of the appropriate size and format) and invokes the /// or creates a new buffer (if it's not of the appropriate size and format) and invokes the
@ -56,8 +51,8 @@ pub fn render_layers(layer_ref: *RenderLayer,
if stride % 32 != 0 { if stride % 32 != 0 {
stride = (stride & !(32 - 1)) + 32; stride = (stride & !(32 - 1)) + 32;
} }
fail_unless!(stride % 32 == 0); assert!(stride % 32 == 0);
fail_unless!(stride >= width); assert!(stride >= width);
debug!("tile stride %u", stride); debug!("tile stride %u", stride);

View file

@ -10,13 +10,9 @@ use render_layers::{RenderLayer, render_layers};
use resource::util::spawn_listener; use resource::util::spawn_listener;
use util::time::time; use util::time::time;
use core::libc::size_t;
use core::libc::types::common::c99::uint16_t;
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan}; use core::comm::{Port, SharedChan};
use core::task::SingleThreaded; use core::task::SingleThreaded;
use std::arc::ARC;
use std::arc;
use std::task_pool::TaskPool; use std::task_pool::TaskPool;
pub enum Msg { pub enum Msg {

View file

@ -1,14 +1,12 @@
use core::comm::Chan;
use core::task::spawn; use core::task::spawn;
use resource::resource_task::{ProgressMsg, Payload, Done, LoaderTask}; use resource::resource_task::{Payload, Done, LoaderTask};
use std::net::url::Url;
use core::io::{file_reader, ReaderUtil}; use core::io::{file_reader, ReaderUtil};
const READ_SIZE: uint = 1024; static READ_SIZE: uint = 1024;
pub fn factory() -> LoaderTask { pub fn factory() -> LoaderTask {
let f: LoaderTask = |url, progress_chan| { let f: LoaderTask = |url, progress_chan| {
fail_unless!(url.scheme == ~"file"); assert!(url.scheme == ~"file");
do spawn { do spawn {
// FIXME: Resolve bug prevents us from moving the path out of the URL. // FIXME: Resolve bug prevents us from moving the path out of the URL.
match file_reader(&Path(url.path)) { match file_reader(&Path(url.path)) {

View file

@ -1,25 +1,23 @@
use core::comm::{Chan, SharedChan}; use core::comm::SharedChan;
use core::task::spawn; use core::task::spawn;
use resource::resource_task::{ProgressMsg, Payload, Done, LoaderTask}; use resource::resource_task::{Payload, Done, LoaderTask};
use core::cell::Cell;
use std::net::url::Url;
use http_client; use http_client;
use http_client::{uv_http_request}; use http_client::{uv_http_request};
pub fn factory() -> LoaderTask { pub fn factory() -> LoaderTask {
let f: LoaderTask = |url, progress_chan| { let f: LoaderTask = |url, progress_chan| {
fail_unless!(url.scheme == ~"http"); assert!(url.scheme == ~"http");
let progress_chan = SharedChan(progress_chan); let progress_chan = SharedChan(progress_chan);
do spawn { do spawn {
debug!("http_loader: requesting via http: %?", copy url); debug!("http_loader: requesting via http: %?", url.clone());
let mut request = uv_http_request(copy url); let mut request = uv_http_request(url.clone());
let errored = @mut false; let errored = @mut false;
let url = copy url; let url = url.clone();
{ {
let progress_chan = progress_chan.clone(); let progress_chan = progress_chan.clone();
do request.begin |event| { do request.begin |event| {
let url = copy url; let url = url.clone();
match event { match event {
http_client::Status(*) => { } http_client::Status(*) => { }
http_client::Payload(data) => { http_client::Payload(data) => {

View file

@ -1,12 +1,11 @@
use image::base::{Image, load_from_memory, test_image_bin}; use image::base::{Image, load_from_memory};
use resource::resource_task; use resource::resource_task;
use resource::resource_task::ResourceTask; use resource::resource_task::ResourceTask;
use util::url::{make_url, UrlMap, url_map}; use util::url::{UrlMap, url_map};
use clone_arc = std::arc::clone; use clone_arc = std::arc::clone;
use core::comm::{Chan, Port, SharedChan, stream}; use core::comm::{Chan, Port, SharedChan, stream};
use core::task::spawn; use core::task::spawn;
use resource::util::spawn_listener;
use core::to_str::ToStr; use core::to_str::ToStr;
use core::util::replace; use core::util::replace;
use std::arc::ARC; use std::arc::ARC;
@ -49,7 +48,7 @@ pub enum ImageResponseMsg {
} }
impl ImageResponseMsg { impl ImageResponseMsg {
pure fn clone(&self) -> ImageResponseMsg { fn clone(&self) -> ImageResponseMsg {
match *self { match *self {
ImageReady(ref img) => ImageReady(unsafe { clone_arc(img) }), ImageReady(ref img) => ImageReady(unsafe { clone_arc(img) }),
ImageNotReady => ImageNotReady, ImageNotReady => ImageNotReady,
@ -59,7 +58,7 @@ impl ImageResponseMsg {
} }
impl Eq for ImageResponseMsg { impl Eq for ImageResponseMsg {
pure fn eq(&self, other: &ImageResponseMsg) -> bool { fn eq(&self, other: &ImageResponseMsg) -> bool {
// FIXME: Bad copies // FIXME: Bad copies
match (self.clone(), other.clone()) { match (self.clone(), other.clone()) {
(ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"), (ImageReady(*), ImageReady(*)) => fail!(~"unimplemented comparison"),
@ -71,7 +70,7 @@ impl Eq for ImageResponseMsg {
| (ImageFailed, _) => false | (ImageFailed, _) => false
} }
} }
pure fn ne(&self, other: &ImageResponseMsg) -> bool { fn ne(&self, other: &ImageResponseMsg) -> bool {
return !(*self).eq(other); return !(*self).eq(other);
} }
} }
@ -199,7 +198,7 @@ impl ImageCache {
} }
OnMsg(handler) => msg_handlers.push(handler), OnMsg(handler) => msg_handlers.push(handler),
Exit(response) => { Exit(response) => {
fail_unless!(self.need_exit.is_none()); assert!(self.need_exit.is_none());
self.need_exit = Some(response); self.need_exit = Some(response);
} }
} }
@ -234,7 +233,7 @@ impl ImageCache {
priv fn get_state(&self, url: Url) -> ImageState { priv fn get_state(&self, url: Url) -> ImageState {
match self.state_map.find(&url) { match self.state_map.find(&url) {
Some(state) => state, Some(state) => *state,
None => Init None => Init
} }
} }
@ -317,7 +316,7 @@ impl ImageCache {
} }
Prefetched(data_cell) => { Prefetched(data_cell) => {
fail_unless!(!data_cell.is_empty()); assert!(!data_cell.is_empty());
let data = data_cell.take(); let data = data_cell.take();
let to_cache = self.chan.clone(); let to_cache = self.chan.clone();
@ -329,7 +328,7 @@ impl ImageCache {
debug!("image_cache_task: started image decode for %s", url.to_str()); debug!("image_cache_task: started image decode for %s", url.to_str());
let image = decode(data); let image = decode(data);
let image = if image.is_some() { let image = if image.is_some() {
Some(ARC(~option::unwrap(image))) Some(ARC(~image.unwrap()))
} else { } else {
None None
}; };
@ -376,7 +375,7 @@ impl ImageCache {
priv fn purge_waiters(&self, url: Url, f: &fn() -> ImageResponseMsg) { priv fn purge_waiters(&self, url: Url, f: &fn() -> ImageResponseMsg) {
match self.wait_map.find(&url) { match self.wait_map.find(&url) {
Some(waiters) => { Some(waiters) => {
let waiters = &mut *waiters; let waiters = *waiters;
let mut new_waiters = ~[]; let mut new_waiters = ~[];
new_waiters <-> *waiters; new_waiters <-> *waiters;
@ -427,7 +426,7 @@ impl ImageCache {
// We don't have this image yet // We don't have this image yet
match self.wait_map.find(&url) { match self.wait_map.find(&url) {
Some(waiters) => { Some(waiters) => {
vec::push(&mut *waiters, response); vec::push(*waiters, response);
} }
None => { None => {
self.wait_map.insert(url, @mut ~[response]); self.wait_map.insert(url, @mut ~[response]);
@ -598,7 +597,7 @@ fn should_not_request_url_from_resource_task_on_multiple_prefetches() {
url_requested.recv(); url_requested.recv();
image_cache_task.exit(); image_cache_task.exit();
mock_resource_task.send(resource_task::Exit); mock_resource_task.send(resource_task::Exit);
fail_unless!(!url_requested.peek()) assert!(!url_requested.peek())
} }
#[test] #[test]
@ -621,7 +620,7 @@ fn should_return_image_not_ready_if_data_has_not_arrived() {
image_cache_task.send(Decode(copy url)); image_cache_task.send(Decode(copy url));
let (response_chan, response_port) = stream(); let (response_chan, response_port) = stream();
image_cache_task.send(GetImage(url, response_chan)); image_cache_task.send(GetImage(url, response_chan));
fail_unless!(response_port.recv() == ImageNotReady); assert!(response_port.recv() == ImageNotReady);
wait_chan.send(()); wait_chan.send(());
image_cache_task.exit(); image_cache_task.exit();
mock_resource_task.send(resource_task::Exit); mock_resource_task.send(resource_task::Exit);
@ -747,7 +746,7 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
// Our resource task should not have received another request for the image // Our resource task should not have received another request for the image
// because it's already cached // because it's already cached
fail_unless!(!image_bin_sent.peek()); assert!(!image_bin_sent.peek());
} }
#[test] #[test]
@ -794,7 +793,7 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
// Our resource task should not have received another request for the image // Our resource task should not have received another request for the image
// because it's already cached // because it's already cached
fail_unless!(!image_bin_sent.peek()); assert!(!image_bin_sent.peek());
} }
#[test] #[test]

View file

@ -6,7 +6,7 @@ multiple times and thus triggering reflows multiple times.
use clone_arc = std::arc::clone; use clone_arc = std::arc::clone;
use std::net::url::Url; use std::net::url::Url;
use core::comm::{Port, Chan, stream}; use core::comm::Port;
use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg, Prefetch, Decode, GetImage}; use resource::image_cache_task::{ImageCacheTask, ImageResponseMsg, Prefetch, Decode, GetImage};
use resource::image_cache_task::{ WaitForImage, ImageReady, ImageNotReady, ImageFailed}; use resource::image_cache_task::{ WaitForImage, ImageReady, ImageNotReady, ImageFailed};
use util::url::{UrlMap, url_map}; use util::url::{UrlMap, url_map};
@ -107,7 +107,7 @@ pub impl LocalImageCache {
// the compositor should be resonsible for waiting // the compositor should be resonsible for waiting
// on the image to load and triggering layout // on the image to load and triggering layout
let image_cache_task = self.image_cache_task.clone(); let image_cache_task = self.image_cache_task.clone();
fail_unless!(self.on_image_available.is_some()); assert!(self.on_image_available.is_some());
let on_image_available = self.on_image_available.get()(); let on_image_available = self.on_image_available.get()();
let url = copy *url; let url = copy *url;
do task::spawn { do task::spawn {
@ -134,7 +134,7 @@ pub impl LocalImageCache {
priv fn get_state(&self, url: &Url) -> @mut ImageState { priv fn get_state(&self, url: &Url) -> @mut ImageState {
match self.state_map.find(url) { match self.state_map.find(url) {
Some(state) => state, Some(state) => *state,
None => { None => {
let new_state = @mut ImageState { let new_state = @mut ImageState {
prefetched: false, prefetched: false,

View file

@ -7,7 +7,6 @@ A task that takes a URL and streams back the binary data
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan}; use core::comm::{Chan, Port, SharedChan};
use resource::util::spawn_listener; use resource::util::spawn_listener;
use std::net::url;
use std::net::url::{Url, to_str}; use std::net::url::{Url, to_str};
use super::{file_loader, http_loader}; use super::{file_loader, http_loader};
@ -18,7 +17,7 @@ pub enum ControlMsg {
} }
/// Messages sent in response to a `Load` message /// Messages sent in response to a `Load` message
#[deriving_eq] #[deriving(Eq)]
pub enum ProgressMsg { pub enum ProgressMsg {
/// Binary data - there may be multiple of these /// Binary data - there may be multiple of these
Payload(~[u8]), Payload(~[u8]),
@ -80,7 +79,7 @@ impl ResourceManager {
loop { loop {
match self.from_client.recv() { match self.from_client.recv() {
Load(url, progress_chan) => { Load(url, progress_chan) => {
self.load(copy url, progress_chan) self.load(url.clone(), progress_chan)
} }
Exit => { Exit => {
break break
@ -130,7 +129,7 @@ fn test_bad_scheme() {
let progress = Port(); let progress = Port();
resource_task.send(Load(url::from_str(~"bogus://whatever").get(), progress.chan())); resource_task.send(Load(url::from_str(~"bogus://whatever").get(), progress.chan()));
match progress.recv() { match progress.recv() {
Done(result) => { fail_unless!(result.is_err()) } Done(result) => { assert!(result.is_err()) }
_ => fail _ => fail
} }
resource_task.send(Exit); resource_task.send(Exit);
@ -148,7 +147,7 @@ fn should_delegate_to_scheme_loader() {
let resource_task = create_resource_task_with_loaders(loader_factories); let resource_task = create_resource_task_with_loaders(loader_factories);
let progress = Port(); let progress = Port();
resource_task.send(Load(url::from_str(~"snicklefritz://heya").get(), progress.chan())); resource_task.send(Load(url::from_str(~"snicklefritz://heya").get(), progress.chan()));
fail_unless!(progress.recv() == Payload(payload)); assert!(progress.recv() == Payload(payload));
fail_unless!(progress.recv() == Done(Ok(()))); assert!(progress.recv() == Done(Ok(())));
resource_task.send(Exit); resource_task.send(Exit);
} }

View file

@ -11,6 +11,14 @@ extern mod http_client;
extern mod stb_image; extern mod stb_image;
extern mod std; extern mod std;
pub use servo_util = util;
pub use gfx_font = font;
pub use gfx_font_context = font_context;
pub use gfx_font_list = font_list;
pub use servo_gfx_font = font;
pub use servo_gfx_font_list = font_list;
pub use servo_gfx_util = util;
priv mod render_context; priv mod render_context;
// Rendering // Rendering
@ -82,12 +90,3 @@ pub mod util {
pub mod url; pub mod url;
pub mod vec; pub mod vec;
} }
pub use servo_util = util;
pub use gfx_font = font;
pub use gfx_font_context = font_context;
pub use gfx_font_list = font_list;
pub use servo_gfx_font = font;
pub use servo_gfx_font_list = font_list;
pub use servo_gfx_util = util;

View file

@ -1,6 +1,6 @@
use geom::size::Size2D; use geom::size::Size2D;
#[deriving_eq] #[deriving(Eq)]
pub enum format { pub enum format {
fo_rgba_8888 fo_rgba_8888
// TODO: RGB 565, others? // TODO: RGB 565, others?
@ -21,12 +21,12 @@ pub struct ImageSurface {
} }
impl ImageSurface { impl ImageSurface {
static pub fn new(size: Size2D<int>, format: format) -> ImageSurface { pub fn new(size: Size2D<int>, format: format) -> ImageSurface {
ImageSurface { ImageSurface {
size: copy size, size: copy size,
format: format, format: format,
buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8) buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8)
}
} }
}
} }

View file

@ -26,30 +26,30 @@ struct GlyphEntry {
value : u32 value : u32
} }
pure fn GlyphEntry(value: u32) -> GlyphEntry { GlyphEntry { value: value } } fn GlyphEntry(value: u32) -> GlyphEntry { GlyphEntry { value: value } }
/// The index of a particular glyph within a font /// The index of a particular glyph within a font
pub type GlyphIndex = u32; pub type GlyphIndex = u32;
// TODO: unify with bit flags? // TODO: unify with bit flags?
#[deriving_eq] #[deriving(Eq)]
pub enum BreakType { pub enum BreakType {
BreakTypeNone, BreakTypeNone,
BreakTypeNormal, BreakTypeNormal,
BreakTypeHyphen BreakTypeHyphen
} }
const BREAK_TYPE_NONE : u8 = 0x0u8; static BREAK_TYPE_NONE : u8 = 0x0u8;
const BREAK_TYPE_NORMAL : u8 = 0x1u8; static BREAK_TYPE_NORMAL : u8 = 0x1u8;
const BREAK_TYPE_HYPHEN : u8 = 0x2u8; static BREAK_TYPE_HYPHEN : u8 = 0x2u8;
pure fn break_flag_to_enum(flag: u8) -> BreakType { fn break_flag_to_enum(flag: u8) -> BreakType {
if (flag & BREAK_TYPE_NORMAL) != 0 { return BreakTypeNormal; } if (flag & BREAK_TYPE_NORMAL) != 0 { return BreakTypeNormal; }
if (flag & BREAK_TYPE_HYPHEN) != 0 { return BreakTypeHyphen; } if (flag & BREAK_TYPE_HYPHEN) != 0 { return BreakTypeHyphen; }
BreakTypeNone BreakTypeNone
} }
pure fn break_enum_to_flag(e: BreakType) -> u8 { fn break_enum_to_flag(e: BreakType) -> u8 {
match e { match e {
BreakTypeNone => BREAK_TYPE_NONE, BreakTypeNone => BREAK_TYPE_NONE,
BreakTypeNormal => BREAK_TYPE_NORMAL, BreakTypeNormal => BREAK_TYPE_NORMAL,
@ -59,16 +59,16 @@ pure fn break_enum_to_flag(e: BreakType) -> u8 {
// TODO: make this more type-safe. // TODO: make this more type-safe.
const FLAG_CHAR_IS_SPACE : u32 = 0x10000000u32; static FLAG_CHAR_IS_SPACE : u32 = 0x10000000u32;
// These two bits store some BREAK_TYPE_* flags // These two bits store some BREAK_TYPE_* flags
const FLAG_CAN_BREAK_MASK : u32 = 0x60000000u32; static FLAG_CAN_BREAK_MASK : u32 = 0x60000000u32;
const FLAG_CAN_BREAK_SHIFT : u32 = 29; static FLAG_CAN_BREAK_SHIFT : u32 = 29;
const FLAG_IS_SIMPLE_GLYPH : u32 = 0x80000000u32; static FLAG_IS_SIMPLE_GLYPH : u32 = 0x80000000u32;
// glyph advance; in Au's. // glyph advance; in Au's.
const GLYPH_ADVANCE_MASK : u32 = 0x0FFF0000u32; static GLYPH_ADVANCE_MASK : u32 = 0x0FFF0000u32;
const GLYPH_ADVANCE_SHIFT : u32 = 16; static GLYPH_ADVANCE_SHIFT : u32 = 16;
const GLYPH_ID_MASK : u32 = 0x0000FFFFu32; static GLYPH_ID_MASK : u32 = 0x0000FFFFu32;
// Non-simple glyphs (more than one glyph per char; missing glyph, // Non-simple glyphs (more than one glyph per char; missing glyph,
// newline, tab, large advance, or nonzero x/y offsets) may have one // newline, tab, large advance, or nonzero x/y offsets) may have one
@ -79,38 +79,38 @@ const GLYPH_ID_MASK : u32 = 0x0000FFFFu32;
// The number of detailed glyphs for this char. If the char couldn't // The number of detailed glyphs for this char. If the char couldn't
// be mapped to a glyph (!FLAG_NOT_MISSING), then this actually holds // be mapped to a glyph (!FLAG_NOT_MISSING), then this actually holds
// the UTF8 code point instead. // the UTF8 code point instead.
const GLYPH_COUNT_MASK : u32 = 0x00FFFF00u32; static GLYPH_COUNT_MASK : u32 = 0x00FFFF00u32;
const GLYPH_COUNT_SHIFT : u32 = 8; static GLYPH_COUNT_SHIFT : u32 = 8;
// N.B. following Gecko, these are all inverted so that a lot of // N.B. following Gecko, these are all inverted so that a lot of
// missing chars can be memset with zeros in one fell swoop. // missing chars can be memset with zeros in one fell swoop.
const FLAG_NOT_MISSING : u32 = 0x00000001u32; static FLAG_NOT_MISSING : u32 = 0x00000001u32;
const FLAG_NOT_CLUSTER_START : u32 = 0x00000002u32; static FLAG_NOT_CLUSTER_START : u32 = 0x00000002u32;
const FLAG_NOT_LIGATURE_GROUP_START : u32 = 0x00000004u32; static FLAG_NOT_LIGATURE_GROUP_START : u32 = 0x00000004u32;
const FLAG_CHAR_IS_TAB : u32 = 0x00000008u32; static FLAG_CHAR_IS_TAB : u32 = 0x00000008u32;
const FLAG_CHAR_IS_NEWLINE : u32 = 0x00000010u32; static FLAG_CHAR_IS_NEWLINE : u32 = 0x00000010u32;
const FLAG_CHAR_IS_LOW_SURROGATE : u32 = 0x00000020u32; static FLAG_CHAR_IS_LOW_SURROGATE : u32 = 0x00000020u32;
const CHAR_IDENTITY_FLAGS_MASK : u32 = 0x00000038u32; static CHAR_IDENTITY_FLAGS_MASK : u32 = 0x00000038u32;
pure fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool { fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool {
((glyphId as u32) & GLYPH_ID_MASK) == glyphId ((glyphId as u32) & GLYPH_ID_MASK) == glyphId
} }
pure fn is_simple_advance(advance: Au) -> bool { fn is_simple_advance(advance: Au) -> bool {
let unsignedAu = advance.to_int() as u32; let unsignedAu = advance.to_int() as u32;
(unsignedAu & (GLYPH_ADVANCE_MASK >> GLYPH_ADVANCE_SHIFT)) == unsignedAu (unsignedAu & (GLYPH_ADVANCE_MASK >> GLYPH_ADVANCE_SHIFT)) == unsignedAu
} }
type DetailedGlyphCount = u16; type DetailedGlyphCount = u16;
pure fn InitialGlyphEntry() -> GlyphEntry { fn InitialGlyphEntry() -> GlyphEntry {
GlyphEntry { value: 0 } GlyphEntry { value: 0 }
} }
// Creates a GlyphEntry for the common case // Creates a GlyphEntry for the common case
pure fn SimpleGlyphEntry(index: GlyphIndex, advance: Au) -> GlyphEntry { fn SimpleGlyphEntry(index: GlyphIndex, advance: Au) -> GlyphEntry {
fail_unless!(is_simple_glyph_id(index)); assert!(is_simple_glyph_id(index));
fail_unless!(is_simple_advance(advance)); assert!(is_simple_advance(advance));
let index_mask = index as u32; let index_mask = index as u32;
let advance_mask = (*advance as u32) << GLYPH_ADVANCE_SHIFT; let advance_mask = (*advance as u32) << GLYPH_ADVANCE_SHIFT;
@ -122,8 +122,8 @@ pure fn SimpleGlyphEntry(index: GlyphIndex, advance: Au) -> GlyphEntry {
// Create a GlyphEntry for uncommon case; should be accompanied by // Create a GlyphEntry for uncommon case; should be accompanied by
// initialization of the actual DetailedGlyph data in DetailedGlyphStore // initialization of the actual DetailedGlyph data in DetailedGlyphStore
pure fn ComplexGlyphEntry(startsCluster: bool, startsLigature: bool, glyphCount: uint) -> GlyphEntry { fn ComplexGlyphEntry(startsCluster: bool, startsLigature: bool, glyphCount: uint) -> GlyphEntry {
fail_unless!(glyphCount <= u16::max_value as uint); assert!(glyphCount <= u16::max_value as uint);
debug!("Creating complex glyph entry: startsCluster=%?, startsLigature=%?, glyphCount=%?", debug!("Creating complex glyph entry: startsCluster=%?, startsLigature=%?, glyphCount=%?",
startsCluster, startsLigature, glyphCount); startsCluster, startsLigature, glyphCount);
@ -145,8 +145,8 @@ pure fn ComplexGlyphEntry(startsCluster: bool, startsLigature: bool, glyphCount:
// Create a GlyphEntry for the case where glyphs couldn't be found // Create a GlyphEntry for the case where glyphs couldn't be found
// for the specified character. // for the specified character.
pure fn MissingGlyphsEntry(glyphCount: uint) -> GlyphEntry { fn MissingGlyphsEntry(glyphCount: uint) -> GlyphEntry {
fail_unless!(glyphCount <= u16::max_value as uint); assert!(glyphCount <= u16::max_value as uint);
GlyphEntry { GlyphEntry {
value: (glyphCount as u32) << GLYPH_COUNT_SHIFT value: (glyphCount as u32) << GLYPH_COUNT_SHIFT
@ -158,91 +158,91 @@ pure fn MissingGlyphsEntry(glyphCount: uint) -> GlyphEntry {
impl GlyphEntry { impl GlyphEntry {
// getter methods // getter methods
#[inline(always)] #[inline(always)]
pure fn advance(&self) -> Au { fn advance(&self) -> Au {
//fail_unless!(self.is_simple()); //assert!(self.is_simple());
NumCast::from((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) NumCast::from((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT)
} }
pure fn index(&self) -> GlyphIndex { fn index(&self) -> GlyphIndex {
//fail_unless!(self.is_simple()); //assert!(self.is_simple());
self.value & GLYPH_ID_MASK self.value & GLYPH_ID_MASK
} }
pure fn offset(&self) -> Point2D<Au> { fn offset(&self) -> Point2D<Au> {
//fail_unless!(self.is_simple()); //assert!(self.is_simple());
Point2D(Au(0), Au(0)) Point2D(Au(0), Au(0))
} }
pure fn is_ligature_start(&self) -> bool { fn is_ligature_start(&self) -> bool {
self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START) self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START)
} }
pure fn is_cluster_start(&self) -> bool { fn is_cluster_start(&self) -> bool {
self.has_flag(!FLAG_NOT_CLUSTER_START) self.has_flag(!FLAG_NOT_CLUSTER_START)
} }
// True if original char was normal (U+0020) space. Other chars may // True if original char was normal (U+0020) space. Other chars may
// map to space glyph, but this does not account for them. // map to space glyph, but this does not account for them.
pure fn char_is_space(&self) -> bool { fn char_is_space(&self) -> bool {
self.has_flag(FLAG_CHAR_IS_SPACE) self.has_flag(FLAG_CHAR_IS_SPACE)
} }
pure fn char_is_tab(&self) -> bool { fn char_is_tab(&self) -> bool {
!self.is_simple() && self.has_flag(FLAG_CHAR_IS_TAB) !self.is_simple() && self.has_flag(FLAG_CHAR_IS_TAB)
} }
pure fn char_is_newline(&self) -> bool { fn char_is_newline(&self) -> bool {
!self.is_simple() && self.has_flag(FLAG_CHAR_IS_NEWLINE) !self.is_simple() && self.has_flag(FLAG_CHAR_IS_NEWLINE)
} }
pure fn can_break_before(&self) -> BreakType { fn can_break_before(&self) -> BreakType {
let flag = ((self.value & FLAG_CAN_BREAK_MASK) >> FLAG_CAN_BREAK_SHIFT) as u8; let flag = ((self.value & FLAG_CAN_BREAK_MASK) >> FLAG_CAN_BREAK_SHIFT) as u8;
break_flag_to_enum(flag) break_flag_to_enum(flag)
} }
// setter methods // setter methods
#[inline(always)] #[inline(always)]
pure fn set_char_is_space(&self) -> GlyphEntry { fn set_char_is_space(&self) -> GlyphEntry {
GlyphEntry(self.value | FLAG_CHAR_IS_SPACE) GlyphEntry(self.value | FLAG_CHAR_IS_SPACE)
} }
#[inline(always)] #[inline(always)]
pure fn set_char_is_tab(&self) -> GlyphEntry { fn set_char_is_tab(&self) -> GlyphEntry {
fail_unless!(!self.is_simple()); assert!(!self.is_simple());
GlyphEntry(self.value | FLAG_CHAR_IS_TAB) GlyphEntry(self.value | FLAG_CHAR_IS_TAB)
} }
#[inline(always)] #[inline(always)]
pure fn set_char_is_newline(&self) -> GlyphEntry { fn set_char_is_newline(&self) -> GlyphEntry {
fail_unless!(!self.is_simple()); assert!(!self.is_simple());
GlyphEntry(self.value | FLAG_CHAR_IS_NEWLINE) GlyphEntry(self.value | FLAG_CHAR_IS_NEWLINE)
} }
#[inline(always)] #[inline(always)]
pure fn set_can_break_before(&self, e: BreakType) -> GlyphEntry { fn set_can_break_before(&self, e: BreakType) -> GlyphEntry {
let flag = (break_enum_to_flag(e) as u32) << FLAG_CAN_BREAK_SHIFT; let flag = (break_enum_to_flag(e) as u32) << FLAG_CAN_BREAK_SHIFT;
GlyphEntry(self.value | flag) GlyphEntry(self.value | flag)
} }
// helper methods // helper methods
/*priv*/ pure fn glyph_count(&self) -> u16 { /*priv*/ fn glyph_count(&self) -> u16 {
fail_unless!(!self.is_simple()); assert!(!self.is_simple());
((self.value & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT) as u16 ((self.value & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT) as u16
} }
#[inline(always)] #[inline(always)]
pure fn is_simple(&self) -> bool { fn is_simple(&self) -> bool {
self.has_flag(FLAG_IS_SIMPLE_GLYPH) self.has_flag(FLAG_IS_SIMPLE_GLYPH)
} }
#[inline(always)] #[inline(always)]
/*priv*/ pure fn has_flag(&self, flag: u32) -> bool { /*priv*/ fn has_flag(&self, flag: u32) -> bool {
(self.value & flag) != 0 (self.value & flag) != 0
} }
#[inline(always)] #[inline(always)]
pure fn adapt_character_flags_of_entry(&self, other: GlyphEntry) -> GlyphEntry { fn adapt_character_flags_of_entry(&self, other: GlyphEntry) -> GlyphEntry {
GlyphEntry { value: self.value | other.value } GlyphEntry { value: self.value | other.value }
} }
} }
@ -267,7 +267,7 @@ fn DetailedGlyph(index: GlyphIndex,
} }
} }
#[deriving_eq] #[deriving(Eq)]
struct DetailedGlyphRecord { struct DetailedGlyphRecord {
// source string offset/GlyphEntry offset in the TextRun // source string offset/GlyphEntry offset in the TextRun
entry_offset: uint, entry_offset: uint,
@ -276,16 +276,16 @@ struct DetailedGlyphRecord {
} }
impl Ord for DetailedGlyphRecord { impl Ord for DetailedGlyphRecord {
pure fn lt(&self, other: &DetailedGlyphRecord) -> bool { fn lt(&self, other: &DetailedGlyphRecord) -> bool {
self.entry_offset < other.entry_offset self.entry_offset < other.entry_offset
} }
pure fn le(&self, other: &DetailedGlyphRecord) -> bool { fn le(&self, other: &DetailedGlyphRecord) -> bool {
self.entry_offset <= other.entry_offset self.entry_offset <= other.entry_offset
} }
pure fn ge(&self, other: &DetailedGlyphRecord) -> bool { fn ge(&self, other: &DetailedGlyphRecord) -> bool {
self.entry_offset >= other.entry_offset self.entry_offset >= other.entry_offset
} }
pure fn gt(&self, other: &DetailedGlyphRecord) -> bool { fn gt(&self, other: &DetailedGlyphRecord) -> bool {
self.entry_offset > other.entry_offset self.entry_offset > other.entry_offset
} }
} }
@ -333,7 +333,7 @@ impl DetailedGlyphStore {
self.lookup_is_sorted = false; self.lookup_is_sorted = false;
} }
pure fn get_detailed_glyphs_for_entry(&self, entry_offset: uint, count: u16) -> &self/[DetailedGlyph] { fn get_detailed_glyphs_for_entry(&self, entry_offset: uint, count: u16) -> &'self [DetailedGlyph] {
debug!("Requesting detailed glyphs[n=%u] for entry[off=%u]", count as uint, entry_offset); debug!("Requesting detailed glyphs[n=%u] for entry[off=%u]", count as uint, entry_offset);
// FIXME: Is this right? --pcwalton // FIXME: Is this right? --pcwalton
@ -342,8 +342,8 @@ impl DetailedGlyphStore {
return vec::slice(self.detail_buffer, 0, 0); return vec::slice(self.detail_buffer, 0, 0);
} }
fail_unless!((count as uint) <= self.detail_buffer.len()); assert!((count as uint) <= self.detail_buffer.len());
fail_unless!(self.lookup_is_sorted); assert!(self.lookup_is_sorted);
let key = DetailedGlyphRecord { let key = DetailedGlyphRecord {
entry_offset: entry_offset, entry_offset: entry_offset,
@ -355,19 +355,19 @@ impl DetailedGlyphStore {
match records.binary_search_index(&key) { match records.binary_search_index(&key) {
None => fail!(~"Invalid index not found in detailed glyph lookup table!"), None => fail!(~"Invalid index not found in detailed glyph lookup table!"),
Some(i) => { Some(i) => {
fail_unless!(i + (count as uint) <= self.detail_buffer.len()); assert!(i + (count as uint) <= self.detail_buffer.len());
// return a slice into the buffer // return a slice into the buffer
vec::slice(self.detail_buffer, i, i + count as uint) vec::slice(self.detail_buffer, i, i + count as uint)
} }
} }
} }
pure fn get_detailed_glyph_with_index(&self, fn get_detailed_glyph_with_index(&self,
entry_offset: uint, entry_offset: uint,
detail_offset: u16) detail_offset: u16)
-> &self/DetailedGlyph { -> &'self DetailedGlyph {
fail_unless!((detail_offset as uint) <= self.detail_buffer.len()); assert!((detail_offset as uint) <= self.detail_buffer.len());
fail_unless!(self.lookup_is_sorted); assert!(self.lookup_is_sorted);
let key = DetailedGlyphRecord { let key = DetailedGlyphRecord {
entry_offset: entry_offset, entry_offset: entry_offset,
@ -379,7 +379,7 @@ impl DetailedGlyphStore {
match records.binary_search_index(&key) { match records.binary_search_index(&key) {
None => fail!(~"Invalid index not found in detailed glyph lookup table!"), None => fail!(~"Invalid index not found in detailed glyph lookup table!"),
Some(i) => { Some(i) => {
fail_unless!(i + (detail_offset as uint) < self.detail_buffer.len()); assert!(i + (detail_offset as uint) < self.detail_buffer.len());
&self.detail_buffer[i+(detail_offset as uint)] &self.detail_buffer[i+(detail_offset as uint)]
} }
} }
@ -417,13 +417,12 @@ pub struct GlyphData {
ligature_start: bool, ligature_start: bool,
} }
pub pure fn GlyphData(index: GlyphIndex, pub fn GlyphData(index: GlyphIndex,
advance: Au, advance: Au,
offset: Option<Point2D<Au>>, offset: Option<Point2D<Au>>,
is_missing: bool, is_missing: bool,
cluster_start: bool, cluster_start: bool,
ligature_start: bool) -> GlyphData { ligature_start: bool) -> GlyphData {
let _offset = match offset { let _offset = match offset {
None => geometry::zero_point(), None => geometry::zero_point(),
Some(o) => o Some(o) => o
@ -443,7 +442,7 @@ pub pure fn GlyphData(index: GlyphIndex,
// through glyphs (either for a particular TextRun offset, or all glyphs). // through glyphs (either for a particular TextRun offset, or all glyphs).
// Rather than eagerly assembling and copying glyph data, it only retrieves // Rather than eagerly assembling and copying glyph data, it only retrieves
// values as they are needed from the GlyphStore, using provided offsets. // values as they are needed from the GlyphStore, using provided offsets.
enum GlyphInfo { enum GlyphInfo<'self> {
SimpleGlyphInfo(&'self GlyphStore, uint), SimpleGlyphInfo(&'self GlyphStore, uint),
DetailGlyphInfo(&'self GlyphStore, uint, u16) DetailGlyphInfo(&'self GlyphStore, uint, u16)
} }
@ -496,8 +495,8 @@ pub struct GlyphStore {
pub impl GlyphStore { pub impl 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.
static fn new(length: uint) -> GlyphStore { fn new(length: uint) -> GlyphStore {
fail_unless!(length > 0); assert!(length > 0);
GlyphStore { GlyphStore {
entry_buffer: vec::from_elem(length, InitialGlyphEntry()), entry_buffer: vec::from_elem(length, InitialGlyphEntry()),
@ -511,15 +510,15 @@ pub impl GlyphStore {
fn add_glyph_for_char_index(&mut self, i: uint, data: &GlyphData) { fn add_glyph_for_char_index(&mut self, i: uint, data: &GlyphData) {
pure 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)
&& data.offset == geometry::zero_point() && data.offset == geometry::zero_point()
&& data.cluster_start // others are stored in detail buffer && data.cluster_start // others are stored in detail buffer
} }
fail_unless!(data.ligature_start); // can't compress ligature continuation glyphs. assert!(data.ligature_start); // can't compress ligature continuation glyphs.
fail_unless!(i < self.entry_buffer.len()); assert!(i < self.entry_buffer.len());
let entry = match (data.is_missing, glyph_is_compressible(data)) { let entry = match (data.is_missing, glyph_is_compressible(data)) {
(true, _) => MissingGlyphsEntry(1), (true, _) => MissingGlyphsEntry(1),
@ -535,8 +534,8 @@ pub impl GlyphStore {
} }
fn add_glyphs_for_char_index(&mut self, i: uint, data_for_glyphs: &[GlyphData]) { fn add_glyphs_for_char_index(&mut self, i: uint, data_for_glyphs: &[GlyphData]) {
fail_unless!(i < self.entry_buffer.len()); assert!(i < self.entry_buffer.len());
fail_unless!(data_for_glyphs.len() > 0); assert!(data_for_glyphs.len() > 0);
let glyph_count = data_for_glyphs.len(); let glyph_count = data_for_glyphs.len();
@ -564,7 +563,7 @@ pub impl 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) { fn add_nonglyph_for_char_index(&mut self, i: uint, cluster_start: bool, ligature_start: bool) {
fail_unless!(i < self.entry_buffer.len()); assert!(i < self.entry_buffer.len());
let entry = ComplexGlyphEntry(cluster_start, ligature_start, 0); let entry = ComplexGlyphEntry(cluster_start, ligature_start, 0);
debug!("adding spacer for chracter without associated glyph[idx=%u]", i); debug!("adding spacer for chracter without associated glyph[idx=%u]", i);
@ -572,20 +571,20 @@ pub impl GlyphStore {
self.entry_buffer[i] = entry; self.entry_buffer[i] = entry;
} }
pure fn iter_glyphs_for_char_index(&self, i: uint, cb: &fn(uint, GlyphInfo/&self) -> bool) -> bool { fn iter_glyphs_for_char_index(&self, i: uint, cb: &fn(uint, &GlyphInfo<'self>) -> bool) -> bool {
fail_unless!(i < self.entry_buffer.len()); assert!(i < self.entry_buffer.len());
let entry = &self.entry_buffer[i]; let entry = &self.entry_buffer[i];
match entry.is_simple() { match entry.is_simple() {
true => { true => {
let proxy = SimpleGlyphInfo(self, i); let proxy = &SimpleGlyphInfo(self, i);
cb(i, proxy); cb(i, proxy);
}, },
false => { false => {
let glyphs = self.detail_store.get_detailed_glyphs_for_entry(i, let glyphs = self.detail_store.get_detailed_glyphs_for_entry(i,
entry.glyph_count()); entry.glyph_count());
for uint::range(0, glyphs.len()) |j| { for uint::range(0, glyphs.len()) |j| {
let proxy = DetailGlyphInfo(self, i, j as u16); let proxy = &DetailGlyphInfo(self, i, j as u16);
cb(i, proxy); cb(i, proxy);
} }
} }
@ -593,7 +592,7 @@ pub impl GlyphStore {
return true; return true;
} }
pure fn iter_glyphs_for_char_range(&self, range: &const Range, cb: &fn(uint, GlyphInfo/&self) -> bool) { fn iter_glyphs_for_char_range(&self, range: &Range, cb: &fn(uint, &GlyphInfo<'self>) -> bool) {
if range.begin() >= self.entry_buffer.len() { if range.begin() >= self.entry_buffer.len() {
error!("iter_glyphs_for_range: range.begin beyond length!"); error!("iter_glyphs_for_range: range.begin beyond length!");
return; return;
@ -608,64 +607,64 @@ pub impl GlyphStore {
} }
} }
pure fn iter_all_glyphs(&self, cb: &fn(uint, GlyphInfo/&self) -> bool) { fn iter_all_glyphs(&self, cb: &fn(uint, &GlyphInfo<'self>) -> 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) { break; } if !self.iter_glyphs_for_char_index(i, cb) { break; }
} }
} }
// getter methods // getter methods
pure fn char_is_space(&self, i: uint) -> bool { fn char_is_space(&self, i: uint) -> bool {
fail_unless!(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()
} }
pure fn char_is_tab(&self, i: uint) -> bool { fn char_is_tab(&self, i: uint) -> bool {
fail_unless!(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()
} }
pure fn char_is_newline(&self, i: uint) -> bool { fn char_is_newline(&self, i: uint) -> bool {
fail_unless!(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()
} }
pure fn is_ligature_start(&self, i: uint) -> bool { fn is_ligature_start(&self, i: uint) -> bool {
fail_unless!(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()
} }
pure fn is_cluster_start(&self, i: uint) -> bool { fn is_cluster_start(&self, i: uint) -> bool {
fail_unless!(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()
} }
pure fn can_break_before(&self, i: uint) -> BreakType { fn can_break_before(&self, i: uint) -> BreakType {
fail_unless!(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) { fn set_char_is_space(&mut self, i: uint) {
fail_unless!(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) { fn set_char_is_tab(&mut self, i: uint) {
fail_unless!(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) { fn set_char_is_newline(&mut self, i: uint) {
fail_unless!(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) { fn set_can_break_before(&mut self, i: uint, t: BreakType) {
fail_unless!(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);
} }

View file

@ -10,22 +10,18 @@ use text::glyph::{GlyphStore, GlyphIndex, GlyphData};
use text::shaper::ShaperMethods; use text::shaper::ShaperMethods;
use gfx_font::{FontHandleMethods, FontTableMethods}; use gfx_font::{FontHandleMethods, FontTableMethods};
use servo_util::range;
use util::range::Range; use util::range::Range;
use core::libc::types::common::c99::int32_t;
use core::libc::{c_uint, c_int, c_void, c_char}; use core::libc::{c_uint, c_int, c_void, c_char};
use core::util::ignore; use core::util::ignore;
//use dvec::DVec;
use std::arc;
use text::harfbuzz::shaper::harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR, hb_blob_t}; use text::harfbuzz::shaper::harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR, hb_blob_t};
use text::harfbuzz::shaper::harfbuzz::{hb_face_t, hb_font_t}; use text::harfbuzz::shaper::harfbuzz::{hb_face_t, hb_font_t};
use text::harfbuzz::shaper::harfbuzz::{hb_font_funcs_t, hb_buffer_t, hb_codepoint_t, hb_bool_t}; use text::harfbuzz::shaper::harfbuzz::{hb_font_funcs_t, hb_buffer_t, hb_codepoint_t, hb_bool_t};
use text::harfbuzz::shaper::harfbuzz::{hb_glyph_position_t}; use text::harfbuzz::shaper::harfbuzz::{hb_glyph_position_t};
use text::harfbuzz::shaper::harfbuzz::{hb_glyph_info_t, hb_var_int_t, hb_position_t}; use text::harfbuzz::shaper::harfbuzz::{hb_glyph_info_t, hb_position_t};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy}; use text::harfbuzz::shaper::harfbuzz::bindgen::hb_blob_create;
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_face_create, hb_face_destroy}; use text::harfbuzz::shaper::harfbuzz::bindgen::hb_face_destroy;
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_create, hb_font_destroy}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_create, hb_font_destroy};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_buffer_create}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_buffer_create};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_buffer_destroy}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_buffer_destroy};
@ -40,14 +36,13 @@ use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_destroy};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_set_funcs}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_set_funcs};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_set_glyph_h_advance_func}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_set_glyph_h_advance_func};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_set_glyph_func}; use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_set_glyph_func};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_font_funcs_set_glyph_h_kerning_func};
use text::harfbuzz::shaper::harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR}; use text::harfbuzz::shaper::harfbuzz::{HB_MEMORY_MODE_READONLY, HB_DIRECTION_LTR};
use text::harfbuzz::shaper::harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t}; use text::harfbuzz::shaper::harfbuzz::{hb_blob_t, hb_face_t, hb_font_t, hb_font_funcs_t};
use text::harfbuzz::shaper::harfbuzz::{hb_buffer_t, hb_codepoint_t, hb_bool_t}; use text::harfbuzz::shaper::harfbuzz::{hb_buffer_t, hb_codepoint_t, hb_bool_t};
use text::harfbuzz::shaper::harfbuzz::{hb_glyph_position_t, hb_glyph_info_t, hb_var_int_t}; use text::harfbuzz::shaper::harfbuzz::{hb_glyph_position_t, hb_glyph_info_t};
use text::harfbuzz::shaper::harfbuzz::{hb_position_t, hb_tag_t}; use text::harfbuzz::shaper::harfbuzz::{hb_position_t, hb_tag_t};
use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy, use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_blob_create,
hb_face_create_for_tables, hb_face_destroy, hb_face_create_for_tables, hb_face_destroy,
hb_font_create, hb_font_destroy, hb_font_create, hb_font_destroy,
hb_buffer_create, hb_buffer_destroy, hb_buffer_create, hb_buffer_destroy,
@ -59,8 +54,7 @@ use text::harfbuzz::shaper::harfbuzz::bindgen::{hb_blob_create, hb_blob_destroy,
hb_font_funcs_create, hb_font_funcs_destroy, hb_font_funcs_create, hb_font_funcs_destroy,
hb_font_set_funcs, hb_font_set_funcs,
hb_font_funcs_set_glyph_h_advance_func, hb_font_funcs_set_glyph_h_advance_func,
hb_font_funcs_set_glyph_func, hb_font_funcs_set_glyph_func};
hb_font_funcs_set_glyph_h_kerning_func};
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};
@ -78,16 +72,16 @@ pub struct ShapedGlyphEntry {
} }
pub impl ShapedGlyphData { pub impl ShapedGlyphData {
static pure fn new(buffer: *hb_buffer_t) -> ShapedGlyphData { fn new(buffer: *hb_buffer_t) -> ShapedGlyphData {
unsafe { unsafe {
let glyph_count = 0 as c_uint; let glyph_count = 0 as c_uint;
let glyph_infos = hb_buffer_get_glyph_infos(buffer, ptr::to_unsafe_ptr(&glyph_count)); let glyph_infos = hb_buffer_get_glyph_infos(buffer, ptr::to_unsafe_ptr(&glyph_count));
let glyph_count = glyph_count as uint; let glyph_count = glyph_count as uint;
fail_unless!(glyph_infos.is_not_null()); assert!(glyph_infos.is_not_null());
let pos_count = 0 as c_uint; let pos_count = 0 as c_uint;
let pos_infos = hb_buffer_get_glyph_positions(buffer, ptr::to_unsafe_ptr(&pos_count)); let pos_infos = hb_buffer_get_glyph_positions(buffer, ptr::to_unsafe_ptr(&pos_count));
fail_unless!(pos_infos.is_not_null()); assert!(pos_infos.is_not_null());
fail_unless!(glyph_count == pos_count as uint); assert!(glyph_count == pos_count as uint);
ShapedGlyphData { ShapedGlyphData {
count: glyph_count, count: glyph_count,
@ -98,8 +92,8 @@ pub impl ShapedGlyphData {
} }
#[inline(always)] #[inline(always)]
priv pure fn byte_offset_of_glyph(&const self, i: uint) -> uint { priv fn byte_offset_of_glyph(&self, i: uint) -> uint {
fail_unless!(i < self.count); assert!(i < self.count);
let glyph_info_i = ptr::offset(self.glyph_infos, i); let glyph_info_i = ptr::offset(self.glyph_infos, i);
unsafe { unsafe {
@ -107,11 +101,11 @@ pub impl ShapedGlyphData {
} }
} }
pure fn len(&self) -> uint { self.count } fn len(&self) -> uint { self.count }
// Returns shaped glyph data for one glyph, and updates the y-position of the pen. // Returns shaped glyph data for one glyph, and updates the y-position of the pen.
fn get_entry_for_glyph(&self, i: uint, y_pos: &mut Au) -> ShapedGlyphEntry { fn get_entry_for_glyph(&self, i: uint, y_pos: &mut Au) -> ShapedGlyphEntry {
fail_unless!(i < self.count); assert!(i < self.count);
let glyph_info_i = ptr::offset(self.glyph_infos, i); let glyph_info_i = ptr::offset(self.glyph_infos, i);
let pos_info_i = ptr::offset(self.pos_infos, i); let pos_info_i = ptr::offset(self.pos_infos, i);
@ -128,7 +122,7 @@ pub impl ShapedGlyphData {
*y_pos -= y_advance; *y_pos -= y_advance;
} }
Some(Point2D(x_offset, y_pos - y_offset)) Some(Point2D(x_offset, *y_pos - y_offset))
}; };
unsafe { unsafe {
@ -149,21 +143,22 @@ pub struct HarfbuzzShaper {
priv hb_funcs: *hb_font_funcs_t, priv hb_funcs: *hb_font_funcs_t,
} }
#[unsafe_destructor]
impl Drop for HarfbuzzShaper { impl Drop for HarfbuzzShaper {
fn finalize(&self) { fn finalize(&self) {
fail_unless!(self.hb_face.is_not_null()); assert!(self.hb_face.is_not_null());
hb_face_destroy(self.hb_face); hb_face_destroy(self.hb_face);
fail_unless!(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);
fail_unless!(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);
} }
} }
pub impl HarfbuzzShaper { pub impl HarfbuzzShaper {
static pub fn new(font: @mut Font) -> HarfbuzzShaper { pub fn new(font: @mut Font) -> HarfbuzzShaper {
let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func, ptr::to_unsafe_ptr(font) as *c_void, ptr::null()); let hb_face: *hb_face_t = hb_face_create_for_tables(get_font_table_func, ptr::to_unsafe_ptr(font) as *c_void, ptr::null());
let hb_font: *hb_font_t = hb_font_create(hb_face); 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.
@ -192,15 +187,15 @@ pub impl HarfbuzzShaper {
} }
} }
static priv fn float_to_fixed(f: float) -> i32 { priv fn float_to_fixed(f: float) -> i32 {
float_to_fixed(16, f) float_to_fixed(16, f)
} }
static priv fn fixed_to_float(i: hb_position_t) -> float { priv fn fixed_to_float(i: hb_position_t) -> float {
fixed_to_float(16, i) fixed_to_float(16, i)
} }
static priv fn fixed_to_rounded_int(f: hb_position_t) -> int { priv fn fixed_to_rounded_int(f: hb_position_t) -> int {
fixed_to_rounded_int(16, f) fixed_to_rounded_int(16, f)
} }
} }
@ -240,7 +235,7 @@ pub impl HarfbuzzShaper {
// so, we must be careful to increment this when saving glyph entries. // so, we must be careful to increment this when saving glyph entries.
let mut char_idx = 0; let mut char_idx = 0;
fail_unless!(glyph_count <= char_max); assert!(glyph_count <= char_max);
debug!("Shaped text[char count=%u], got back %u glyph info records.", char_max, glyph_count); debug!("Shaped text[char count=%u], got back %u glyph info records.", char_max, glyph_count);
if char_max != glyph_count { if char_max != glyph_count {
@ -248,8 +243,8 @@ pub impl HarfbuzzShaper {
} }
// make map of what chars have glyphs // make map of what chars have glyphs
const NO_GLYPH : i32 = -1; static NO_GLYPH : i32 = -1;
const CONTINUATION_BYTE : i32 = -2; static CONTINUATION_BYTE : i32 = -2;
let mut byteToGlyph : ~[i32]; let mut byteToGlyph : ~[i32];
// fast path: all chars are single-byte. // fast path: all chars are single-byte.
@ -271,7 +266,7 @@ pub impl HarfbuzzShaper {
// loc refers to a *byte* offset within the utf8 string. // loc refers to a *byte* offset within the utf8 string.
let loc = glyph_data.byte_offset_of_glyph(i); let loc = glyph_data.byte_offset_of_glyph(i);
if loc < byte_max { if loc < byte_max {
fail_unless!(byteToGlyph[loc] != CONTINUATION_BYTE); assert!(byteToGlyph[loc] != CONTINUATION_BYTE);
byteToGlyph[loc] = i as i32; byteToGlyph[loc] = i as i32;
} }
else { debug!("ERROR: tried to set out of range byteToGlyph: idx=%u, glyph idx=%u", loc, i); } else { debug!("ERROR: tried to set out of range byteToGlyph: idx=%u, glyph idx=%u", loc, i); }
@ -361,9 +356,9 @@ pub impl HarfbuzzShaper {
} }
// character/glyph clump must contain characters. // character/glyph clump must contain characters.
fail_unless!(char_byte_span.length() > 0); assert!(char_byte_span.length() > 0);
// character/glyph clump must contain glyphs. // character/glyph clump must contain glyphs.
fail_unless!(glyph_span.length() > 0); assert!(glyph_span.length() > 0);
// now char_span is a ligature clump, formed by the glyphs in glyph_span. // now char_span is a ligature clump, formed by the glyphs in glyph_span.
// we need to find the chars that correspond to actual glyphs (char_extended_span), // we need to find the chars that correspond to actual glyphs (char_extended_span),
@ -387,12 +382,15 @@ pub impl HarfbuzzShaper {
if covered_byte_span.begin() >= byte_max { if covered_byte_span.begin() >= byte_max {
// oops, out of range. clip and forget this clump. // oops, out of range. clip and forget this clump.
glyph_span.reset(glyph_span.end(), 0); let end = glyph_span.end(); // FIXME: borrow checker workaround
char_byte_span.reset(char_byte_span.end(), 0); glyph_span.reset(end, 0);
let end = char_byte_span.end(); // FIXME: borrow checker workaround
char_byte_span.reset(end, 0);
} }
// clamp to end of text. (I don't think this will be necessary, but..) // clamp to end of text. (I don't think this will be necessary, but..)
covered_byte_span.extend_to(uint::min(covered_byte_span.end(), byte_max)); let end = covered_byte_span.end(); // FIXME: borrow checker workaround
covered_byte_span.extend_to(uint::min(end, byte_max));
// fast path: 1-to-1 mapping of single char and single glyph. // fast path: 1-to-1 mapping of single char and single glyph.
if glyph_span.length() == 1 { if glyph_span.length() == 1 {
@ -416,7 +414,6 @@ pub impl HarfbuzzShaper {
false, // not missing false, // not missing
true, // treat as cluster start true, // treat as cluster start
glyph_i > glyph_span.begin())); // all but first are ligature continuations glyph_i > glyph_span.begin())); // all but first are ligature continuations
glyph_span.adjust_by(1,-1);
} }
// now add the detailed glyph entry. // now add the detailed glyph entry.
@ -435,8 +432,10 @@ pub impl HarfbuzzShaper {
} }
// shift up our working spans past things we just handled. // shift up our working spans past things we just handled.
glyph_span.reset(glyph_span.end(), 0); let end = glyph_span.end(); // FIXME: borrow checker workaround
char_byte_span.reset(char_byte_span.end(), 0); glyph_span.reset(end, 0);
let end = char_byte_span.end();; // FIXME: borrow checker workaround
char_byte_span.reset(end, 0);
char_idx += 1; char_idx += 1;
} }
@ -454,7 +453,7 @@ extern fn glyph_func(_font: *hb_font_t,
glyph: *mut hb_codepoint_t, glyph: *mut hb_codepoint_t,
_user_data: *c_void) -> hb_bool_t { _user_data: *c_void) -> hb_bool_t {
let font: *Font = font_data as *Font; let font: *Font = font_data as *Font;
fail_unless!(font.is_not_null()); assert!(font.is_not_null());
unsafe { unsafe {
return match (*font).glyph_index(unicode as char) { return match (*font).glyph_index(unicode as char) {
Some(g) => { *glyph = g as hb_codepoint_t; true }, Some(g) => { *glyph = g as hb_codepoint_t; true },
@ -468,7 +467,7 @@ extern fn glyph_h_advance_func(_font: *hb_font_t,
glyph: hb_codepoint_t, glyph: hb_codepoint_t,
_user_data: *c_void) -> hb_position_t { _user_data: *c_void) -> hb_position_t {
let font: *Font = font_data as *Font; let font: *Font = font_data as *Font;
fail_unless!(font.is_not_null()); assert!(font.is_not_null());
unsafe { unsafe {
let advance = (*font).glyph_h_advance(glyph as GlyphIndex); let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
@ -480,7 +479,7 @@ extern fn glyph_h_advance_func(_font: *hb_font_t,
extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t { extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_void) -> *hb_blob_t {
unsafe { unsafe {
let font: *Font = user_data as *Font; let font: *Font = user_data as *Font;
fail_unless!(font.is_not_null()); assert!(font.is_not_null());
// TODO(Issue #197): reuse font table data, which will change the unsound trickery here. // TODO(Issue #197): reuse font table data, which will change the unsound trickery here.
match (*font).get_table_for_tag(tag as FontTableTag) { match (*font).get_table_for_tag(tag as FontTableTag) {
@ -496,7 +495,7 @@ extern fn get_font_table_func(_face: *hb_face_t, tag: hb_tag_t, user_data: *c_vo
cast::transmute(skinny_font_table_ptr), // private context for below. cast::transmute(skinny_font_table_ptr), // private context for below.
destroy_blob_func); // HarfBuzz calls this when blob not needed. destroy_blob_func); // HarfBuzz calls this when blob not needed.
}); });
fail_unless!(blob.is_not_null()); assert!(blob.is_not_null());
return blob; return blob;
} }
} }

View file

@ -8,7 +8,7 @@ use gfx_font::Font;
use text::glyph::GlyphStore; use text::glyph::GlyphStore;
use text::harfbuzz; use text::harfbuzz;
pub type Shaper/& = harfbuzz::shaper::HarfbuzzShaper; pub type Shaper = harfbuzz::shaper::HarfbuzzShaper;
pub trait ShaperMethods { pub trait ShaperMethods {
fn shape_text(&self, text: &str, glyphs: &mut GlyphStore); fn shape_text(&self, text: &str, glyphs: &mut GlyphStore);
@ -17,7 +17,7 @@ pub trait ShaperMethods {
// TODO(Issue #163): this is a workaround for static methods and // TODO(Issue #163): this is a workaround for static methods and
// typedefs not working well together. It should be removed. // typedefs not working well together. It should be removed.
pub impl Shaper { pub impl Shaper {
static pub fn new(font: @mut Font) -> Shaper { pub fn new(font: @mut Font) -> Shaper {
harfbuzz::shaper::HarfbuzzShaper::new(font) harfbuzz::shaper::HarfbuzzShaper::new(font)
} }
} }

View file

@ -1,15 +1,9 @@
use font_context::FontContext; use font_context::FontContext;
use geometry::Au; use geometry::Au;
use text::glyph::{BreakTypeNormal, GlyphStore}; use text::glyph::{BreakTypeNormal, GlyphStore};
use servo_gfx_font::{Font, FontDescriptor, RunMetrics, FontHandleMethods}; use servo_gfx_font::{Font, FontDescriptor, RunMetrics};
use servo_gfx_util::range::Range; use servo_gfx_util::range::Range;
use core::libc::{c_void};
use geom::point::Point2D;
use geom::size::Size2D;
use std::arc;
use std::arc::ARC;
pub struct TextRun { pub struct TextRun {
text: ~str, text: ~str,
font: @mut Font, font: @mut Font,
@ -40,7 +34,7 @@ impl SendableTextRun {
} }
pub impl TextRun { pub impl TextRun {
static fn new(font: @mut Font, text: ~str) -> TextRun { fn new(font: @mut Font, text: ~str) -> TextRun {
let mut glyph_store = GlyphStore::new(str::char_len(text)); let mut glyph_store = GlyphStore::new(str::char_len(text));
TextRun::compute_potential_breaks(text, &mut glyph_store); TextRun::compute_potential_breaks(text, &mut glyph_store);
font.shape_text(text, &mut glyph_store); font.shape_text(text, &mut glyph_store);
@ -53,7 +47,7 @@ pub impl TextRun {
return run; return run;
} }
static fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) { 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;
@ -103,10 +97,10 @@ pub impl TextRun {
} }
} }
pure fn char_len(&self) -> uint { self.glyphs.entry_buffer.len() } fn char_len(&self) -> uint { self.glyphs.entry_buffer.len() }
pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs } fn glyphs(&self) -> &'self GlyphStore { &self.glyphs }
pure fn range_is_trimmable_whitespace(&self, range: &const Range) -> bool { 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) &&
@ -115,11 +109,11 @@ pub impl TextRun {
return true; return true;
} }
fn metrics_for_range(&self, range: &const Range) -> RunMetrics { 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: &const Range) -> Au { 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| {
@ -130,7 +124,7 @@ pub impl TextRun {
return max_piece_width; return max_piece_width;
} }
fn iter_natural_lines_for_range(&self, range: &const Range, f: &fn(&const Range) -> bool) { fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> 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;
@ -143,7 +137,7 @@ pub impl TextRun {
(true, true) => { (true, true) => {
in_clump = false; in_clump = false;
// don't include the linebreak character itself in the clump. // don't include the linebreak character itself in the clump.
if !f(&const clump) { break } if !f(&clump) { break }
} }
} }
} }
@ -151,11 +145,11 @@ pub impl TextRun {
// flush any remaining chars as a line // flush any remaining chars as a line
if in_clump { if in_clump {
clump.extend_to(range.end()); clump.extend_to(range.end());
f(&const clump); f(&clump);
} }
} }
fn iter_indivisible_pieces_for_range(&self, range: &const Range, f: &fn(&const Range) -> bool) { fn iter_indivisible_pieces_for_range(&self, range: &Range, f: &fn(&Range) -> bool) {
let mut clump = Range::new(range.begin(), 0); let mut clump = Range::new(range.begin(), 0);
loop { loop {
@ -167,10 +161,11 @@ pub impl TextRun {
} }
// now clump.end() is break-before or range.end() // now clump.end() is break-before or range.end()
if !f(&const clump) || clump.end() == range.end() { break; } if !f(&clump) || clump.end() == range.end() { break; }
// now clump includes one break-before character, or starts from range.end() // now clump includes one break-before character, or starts from range.end()
clump.reset(clump.end(), 1); let end = clump.end(); // FIXME: borrow checker workaround
clump.reset(end, 1);
} }
} }
} }

View file

@ -6,7 +6,7 @@ enum CompressionMode {
} }
impl Eq for CompressionMode { impl Eq for CompressionMode {
pure fn eq(&self, other: &CompressionMode) -> bool { fn eq(&self, other: &CompressionMode) -> bool {
match (*self, *other) { match (*self, *other) {
(CompressNone, CompressNone) => true, (CompressNone, CompressNone) => true,
(CompressWhitespace, CompressWhitespace) => true, (CompressWhitespace, CompressWhitespace) => true,
@ -15,7 +15,7 @@ impl Eq for CompressionMode {
_ => false _ => false
} }
} }
pure fn ne(&self, other: &CompressionMode) -> bool { fn ne(&self, other: &CompressionMode) -> bool {
!(*self).eq(other) !(*self).eq(other)
} }
} }

View file

@ -1,10 +1,8 @@
use core::cmp::*;
pub trait Cache<K: Copy + Eq, V: Copy> { pub trait Cache<K: Copy + Eq, V: Copy> {
static fn new(size: uint) -> Self; fn new(size: uint) -> Self;
fn insert(&mut self, key: &K, value: V); fn insert(&mut self, key: &K, value: V);
fn find(&self, key: &K) -> Option<V>; fn find(&self, key: &K) -> Option<V>;
fn find_or_create(&mut self, key: &K, blk: &pure fn(&K) -> V) -> V; fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V;
fn evict_all(&mut self); fn evict_all(&mut self);
} }
@ -13,7 +11,7 @@ pub struct MonoCache<K, V> {
} }
impl<K: Copy + Eq, V: Copy> Cache<K,V> for MonoCache<K,V> { impl<K: Copy + Eq, V: Copy> Cache<K,V> for MonoCache<K,V> {
static fn new(_size: uint) -> MonoCache<K,V> { fn new(_size: uint) -> MonoCache<K,V> {
MonoCache { entry: None } MonoCache { entry: None }
} }
@ -28,7 +26,7 @@ impl<K: Copy + Eq, V: Copy> Cache<K,V> for MonoCache<K,V> {
} }
} }
fn find_or_create(&mut self, key: &K, blk: &pure fn(&K) -> V) -> V { fn find_or_create(&mut self, key: &K, blk: &fn(&K) -> V) -> V {
return match self.find(key) { return match self.find(key) {
None => { None => {
let value = blk(key); let value = blk(key);
@ -51,9 +49,9 @@ fn test_monocache() {
let two = @"two"; let two = @"two";
cache.insert(&1, one); cache.insert(&1, one);
fail_unless!(cache.find(&1).is_some()); assert!(cache.find(&1).is_some());
fail_unless!(cache.find(&2).is_none()); assert!(cache.find(&2).is_none());
cache.find_or_create(&2, |_v| { two }); cache.find_or_create(&2, |_v| { two });
fail_unless!(cache.find(&2).is_some()); assert!(cache.find(&2).is_some());
fail_unless!(cache.find(&1).is_none()); assert!(cache.find(&1).is_none());
} }

View file

@ -14,28 +14,28 @@ pub struct Range {
} }
pub impl Range { pub impl Range {
static pub pure 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 }
} }
static pub pure fn empty() -> Range { pub fn empty() -> Range {
Range::new(0, 0) Range::new(0, 0)
} }
} }
pub impl Range { pub impl Range {
pure fn begin(&const self) -> uint { self.off } fn begin(&self) -> uint { self.off }
pure fn length(&const self) -> uint { self.len } fn length(&self) -> uint { self.len }
pure fn end(&const self) -> uint { self.off + self.len } fn end(&self) -> uint { self.off + self.len }
pure fn eachi(&const self, cb: &fn(uint) -> bool) { fn eachi(&self, cb: &fn(uint) -> bool) {
do uint::range(self.off, self.off + self.len) |i| { cb(i) } do uint::range(self.off, self.off + self.len) |i| { cb(i) }
} }
pure fn contains(&const self, i: uint) -> bool { fn contains(&self, i: uint) -> bool {
i >= self.begin() && i < self.end() i >= self.begin() && i < self.end()
} }
pure fn is_valid_for_string(&const self, s: &str) -> bool { 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()
} }
@ -64,7 +64,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.
pure fn relation_to_range(&const self, other: &const Range) -> RangeRelation { fn relation_to_range(&self, other: &Range) -> RangeRelation {
if other.begin() > self.end() { if other.begin() > self.end() {
return EntirelyBefore; return EntirelyBefore;
} }
@ -92,7 +92,7 @@ pub impl Range {
self, other)); self, other));
} }
fn repair_after_coalesced_range(&mut self, other: &const Range) { 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(%?): %?",

View file

@ -1,7 +1,6 @@
use core::path::Path;
use std::net::url; use std::net::url;
use std::net::url::Url; use std::net::url::Url;
use std::oldmap::HashMap; use core::hashmap::HashMap;
/** /**
Create a URL object from a string. Does various helpful browsery things like Create a URL object from a string. Does various helpful browsery things like
@ -26,7 +25,11 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
if current_url.path.is_empty() || current_url.path.ends_with("/") { if current_url.path.is_empty() || current_url.path.ends_with("/") {
current_url.scheme + "://" + current_url.host + "/" + str_url current_url.scheme + "://" + current_url.host + "/" + str_url
} else { } else {
let path = str::split_char(current_url.path, '/'); let mut path = ~[];
for str::each_split_char(current_url.path, '/') |p| {
path.push(p.to_str());
}
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 = str::connect(path.map(|x| copy *x) + ~[str_url], "/");
@ -98,10 +101,8 @@ mod make_url_tests {
} }
pub type UrlMap<T> = HashMap<Url, T>; pub type UrlMap<T> = @mut HashMap<Url, T>;
pub fn url_map<T: Copy>() -> UrlMap<T> { pub fn url_map<T: Copy>() -> UrlMap<T> {
use core::to_str::ToStr; @mut HashMap::new()
HashMap::<Url, T>()
} }

View file

@ -1,19 +1,19 @@
use core::cmp::{Ord, Eq}; use core::cmp::{Ord, Eq};
pub trait BinarySearchMethods<T: Ord + Eq> { pub trait BinarySearchMethods<T: Ord + Eq> {
pure fn binary_search(&self, key: &T) -> Option<&self/T>; fn binary_search(&self, key: &T) -> Option<&'self T>;
pure fn binary_search_index(&self, key: &T) -> Option<uint>; fn binary_search_index(&self, key: &T) -> Option<uint>;
} }
impl<'self, T: Ord + Eq> BinarySearchMethods<T> for &'self [T] { impl<'self, T: Ord + Eq> BinarySearchMethods<T> for &'self [T] {
pure fn binary_search(&self, key: &T) -> Option<&self/T> { fn binary_search(&self, key: &T) -> Option<&'self T> {
match self.binary_search_index(key) { match self.binary_search_index(key) {
None => None, None => None,
Some(i) => Some(&self[i]) Some(i) => Some(&self[i])
} }
} }
pure fn binary_search_index(&self, key: &T) -> Option<uint> { fn binary_search_index(&self, key: &T) -> Option<uint> {
if self.len() == 0 { if self.len() == 0 {
return None; return None;
} }
@ -41,7 +41,7 @@ impl<'self, T: Ord + Eq> BinarySearchMethods<T> for &'self [T] {
fn test_find_all_elems<T: Eq + Ord>(arr: &[T]) { fn test_find_all_elems<T: Eq + Ord>(arr: &[T]) {
let mut i = 0; let mut i = 0;
while i < arr.len() { while i < arr.len() {
fail_unless!(test_match(&arr[i], arr.binary_search(&arr[i]))); assert!(test_match(&arr[i], arr.binary_search(&arr[i])));
i += 1; i += 1;
} }
} }
@ -51,7 +51,7 @@ fn test_miss_all_elems<T: Eq + Ord>(arr: &[T], misses: &[T]) {
while i < misses.len() { while i < misses.len() {
let res = arr.binary_search(&misses[i]); let res = arr.binary_search(&misses[i]);
debug!("%? == %? ?", misses[i], res); debug!("%? == %? ?", misses[i], res);
fail_unless!(!test_match(&misses[i], arr.binary_search(&misses[i]))); assert!(!test_match(&misses[i], arr.binary_search(&misses[i])));
i += 1; i += 1;
} }
} }

View file

@ -3,8 +3,6 @@ The content task is the main task that runs JavaScript and spawns layout
tasks. tasks.
*/ */
use dom::bindings::utils::rust_box;
use dom::bindings::utils::CacheableWrapper;
use dom::bindings::utils::GlobalStaticData; use dom::bindings::utils::GlobalStaticData;
use dom::document::Document; use dom::document::Document;
use dom::node::define_bindings; use dom::node::define_bindings;
@ -13,29 +11,25 @@ use dom::window::Window;
use layout::layout_task; use layout::layout_task;
use layout::layout_task::{AddStylesheet, BuildData, BuildMsg, Damage, LayoutTask}; use layout::layout_task::{AddStylesheet, BuildData, BuildMsg, Damage, LayoutTask};
use layout::layout_task::{MatchSelectorsDamage, NoDamage, ReflowDamage}; use layout::layout_task::{MatchSelectorsDamage, NoDamage, ReflowDamage};
use util::task::spawn_listener;
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Port, Chan, SharedChan}; use core::comm::{Port, SharedChan};
use core::pipes::select2i; use core::pipes::select2i;
use core::either; use core::either;
use core::task::{SingleThreaded, spawn, task}; use core::task::{SingleThreaded, task};
use core::io::{println, read_whole_file}; use core::io::{println, read_whole_file};
use core::ptr::null; use core::ptr::null;
use core::util::replace; use core::util::replace;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::resource::image_cache_task::ImageCacheTask; use gfx::resource::image_cache_task::ImageCacheTask;
use gfx::resource::resource_task::ResourceTask; use gfx::resource::resource_task::ResourceTask;
use gfx::util::url::make_url;
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::bindgen::RUST_JSVAL_TO_OBJECT;
use js::jsapi::{JSContext, JSVal}; use js::jsapi::JSContext;
use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate}; use js::jsapi::bindgen::{JS_CallFunctionValue, JS_GetContextPrivate};
use js::rust::{Compartment, Cx}; use js::rust::{Compartment, Cx};
use jsrt = js::rust::rt; use jsrt = js::rust::rt;
use newcss::stylesheet::Stylesheet;
use std::arc::{ARC, clone};
use std::net::url::Url; use std::net::url::Url;
use url_to_str = std::net::url::to_str; use url_to_str = std::net::url::to_str;
use dom; use dom;
@ -223,7 +217,7 @@ pub impl Content {
self.window = Some(window); self.window = Some(window);
self.doc_url = Some(url); self.doc_url = Some(url);
let compartment = option::expect(self.compartment, ~"TODO error checking"); let compartment = self.compartment.expect(~"TODO error checking");
compartment.define_functions(debug_fns); compartment.define_functions(debug_fns);
define_bindings(compartment, document, window); define_bindings(compartment, document, window);
@ -235,7 +229,7 @@ pub impl Content {
} }
Timer(timerData) => { Timer(timerData) => {
let compartment = option::expect(self.compartment, ~"TODO error checking"); let compartment = self.compartment.expect(~"TODO error checking");
let thisValue = if timerData.args.len() > 0 { let thisValue = if timerData.args.len() > 0 {
RUST_JSVAL_TO_OBJECT(timerData.args[0]) RUST_JSVAL_TO_OBJECT(timerData.args[0])
} else { } else {
@ -258,7 +252,7 @@ pub impl Content {
println(fmt!("Error opening %s: %s", url_to_str(&url), msg)); println(fmt!("Error opening %s: %s", url_to_str(&url), msg));
} }
Ok(bytes) => { Ok(bytes) => {
let compartment = option::expect(self.compartment, ~"TODO error checking"); let compartment = self.compartment.expect(~"TODO error checking");
compartment.define_functions(debug_fns); compartment.define_functions(debug_fns);
self.cx.evaluate_script(compartment.global_obj, bytes, copy url.path, 1u); self.cx.evaluate_script(compartment.global_obj, bytes, copy url.path, 1u);
} }
@ -349,7 +343,7 @@ pub impl Content {
// Nothing to do. // Nothing to do.
} }
Some(document) => { Some(document) => {
fail_unless!(self.doc_url.is_some()); assert!(self.doc_url.is_some());
self.relayout(document, &(copy self.doc_url).get()); self.relayout(document, &(copy self.doc_url).get());
} }
} }
@ -364,7 +358,7 @@ pub impl Content {
// Nothing to do. // Nothing to do.
} }
Some(document) => { Some(document) => {
fail_unless!(self.doc_url.is_some()); assert!(self.doc_url.is_some());
self.relayout(document, &(copy self.doc_url).get()); self.relayout(document, &(copy self.doc_url).get());
} }
} }

View file

@ -3,12 +3,9 @@
use css::node_util::NodeUtil; use css::node_util::NodeUtil;
use css::select_handler::NodeSelectHandler; use css::select_handler::NodeSelectHandler;
use dom::node::AbstractNode; use dom::node::AbstractNode;
use layout::context::LayoutContext;
use newcss::complete::CompleteSelectResults; use newcss::complete::CompleteSelectResults;
use newcss::select::{SelectCtx, SelectResults}; use newcss::select::{SelectCtx, SelectResults};
use std::arc::{ARC, get, clone};
pub trait MatchMethods { pub trait MatchMethods {
fn restyle_subtree(&self, select_ctx: &SelectCtx); fn restyle_subtree(&self, select_ctx: &SelectCtx);
} }

View file

@ -6,12 +6,12 @@ use newcss::complete::CompleteStyle;
/// Node mixin providing `style` method that returns a `NodeStyle` /// Node mixin providing `style` method that returns a `NodeStyle`
pub trait StyledNode { pub trait StyledNode {
fn style(&self) -> CompleteStyle/&self; fn style(&self) -> CompleteStyle<'self>;
} }
impl StyledNode for AbstractNode { impl StyledNode for AbstractNode {
fn style(&self) -> CompleteStyle/&self { fn style(&self) -> CompleteStyle<'self> {
fail_unless!(self.is_element()); // Only elements can have styles assert!(self.is_element()); // Only elements can have styles
let results = self.get_css_select_results(); let results = self.get_css_select_results();
results.computed_style() results.computed_style()
} }

View file

@ -3,8 +3,8 @@ use newcss::complete::CompleteSelectResults;
use core::cast::transmute; use core::cast::transmute;
pub trait NodeUtil { pub trait NodeUtil<'self> {
fn get_css_select_results(self) -> &self/CompleteSelectResults; fn get_css_select_results(self) -> &'self CompleteSelectResults;
fn set_css_select_results(self, decl: CompleteSelectResults); fn set_css_select_results(self, decl: CompleteSelectResults);
} }
@ -16,7 +16,7 @@ impl<'self> NodeUtil<'self> for AbstractNode {
* FIXME: This isn't completely memory safe since the style is * FIXME: This isn't completely memory safe since the style is
* stored in a box that can be overwritten * stored in a box that can be overwritten
*/ */
fn get_css_select_results(self) -> &self/CompleteSelectResults { fn get_css_select_results(self) -> &'self CompleteSelectResults {
if !self.has_layout_data() { if !self.has_layout_data() {
fail!(~"style() called on a node without aux data!"); fail!(~"style() called on a node without aux data!");
} }

View file

@ -1,16 +1,16 @@
//! CSS library requires that DOM nodes be convertable to *c_void through this trait //! CSS library requires that DOM nodes be convertable to *c_void through this trait
extern mod netsurfcss;
use dom::node::AbstractNode; use dom::node::AbstractNode;
use core::cast; use core::cast;
// FIXME: Rust #3908. rust-css can't reexport VoidPtrLike // FIXME: Rust #3908. rust-css can't reexport VoidPtrLike
extern mod netsurfcss;
use css::node_void_ptr::netsurfcss::util::VoidPtrLike; use css::node_void_ptr::netsurfcss::util::VoidPtrLike;
impl VoidPtrLike for AbstractNode { impl VoidPtrLike for AbstractNode {
static fn from_void_ptr(node: *libc::c_void) -> AbstractNode { fn from_void_ptr(node: *libc::c_void) -> AbstractNode {
fail_unless!(node.is_not_null()); assert!(node.is_not_null());
unsafe { unsafe {
cast::transmute(node) cast::transmute(node)
} }

View file

@ -4,12 +4,12 @@ use dom::bindings::codegen::ClientRectBinding;
use js::jsapi::{JSObject, JSContext}; use js::jsapi::{JSObject, JSContext};
pub trait ClientRect { pub trait ClientRect {
fn Top() -> f32; fn Top(&self) -> f32;
fn Bottom() -> f32; fn Bottom(&self) -> f32;
fn Left() -> f32; fn Left(&self) -> f32;
fn Right() -> f32; fn Right(&self) -> f32;
fn Width() -> f32; fn Width(&self) -> f32;
fn Height() -> f32; fn Height(&self) -> f32;
} }
pub struct ClientRectImpl { pub struct ClientRectImpl {
@ -21,27 +21,27 @@ pub struct ClientRectImpl {
} }
impl ClientRect for ClientRectImpl { impl ClientRect for ClientRectImpl {
fn Top() -> f32 { fn Top(&self) -> f32 {
self.top self.top
} }
fn Bottom() -> f32 { fn Bottom(&self) -> f32 {
self.bottom self.bottom
} }
fn Left() -> f32 { fn Left(&self) -> f32 {
self.left self.left
} }
fn Right() -> f32 { fn Right(&self) -> f32 {
self.right self.right
} }
fn Width() -> f32 { fn Width(&self) -> f32 {
f32::abs(self.right - self.left) f32::abs(self.right - self.left)
} }
fn Height() -> f32 { fn Height(&self) -> f32 {
f32::abs(self.bottom - self.top) f32::abs(self.bottom - self.top)
} }
} }
@ -63,7 +63,7 @@ impl CacheableWrapper for ClientRectImpl {
ClientRectBinding::Wrap(cx, scope, self, &mut unused) ClientRectBinding::Wrap(cx, scope, self, &mut unused)
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"nyi") fail!(~"nyi")
} }
} }

View file

@ -2,8 +2,6 @@ use content::content_task::task_from_context;
use dom::bindings::clientrect::{ClientRect, ClientRectImpl}; use dom::bindings::clientrect::{ClientRect, ClientRectImpl};
use dom::bindings::codegen::ClientRectListBinding; use dom::bindings::codegen::ClientRectListBinding;
use dom::bindings::utils::{WrapperCache, CacheableWrapper, BindingObject, OpaqueBindingReference}; use dom::bindings::utils::{WrapperCache, CacheableWrapper, BindingObject, OpaqueBindingReference};
use dom::window::Window;
use dom::bindings::window::Window;
use js::jsapi::{JSObject, JSContext}; use js::jsapi::{JSObject, JSContext};
pub trait ClientRectList { pub trait ClientRectList {
@ -37,8 +35,8 @@ impl ClientRectList for ClientRectListImpl {
} }
} }
impl ClientRectListImpl { pub impl ClientRectListImpl {
static fn new() -> ClientRectListImpl { fn new() -> ClientRectListImpl {
ClientRectListImpl { ClientRectListImpl {
wrapper: WrapperCache::new(), wrapper: WrapperCache::new(),
rects: ~[(5.6, 80.2, 3.7, 4.8), (800.1, 8001.1, -50.000001, -45.01)] rects: ~[(5.6, 80.2, 3.7, 4.8), (800.1, 8001.1, -50.000001, -45.01)]
@ -56,7 +54,7 @@ impl CacheableWrapper for ClientRectListImpl {
ClientRectListBinding::Wrap(cx, scope, self, &mut unused) ClientRectListBinding::Wrap(cx, scope, self, &mut unused)
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"nyi") fail!(~"nyi")
} }
} }

View file

@ -1856,7 +1856,7 @@ class PropertyDefiner:
specs.append(specTerminator) specs.append(specTerminator)
prefableSpecs.append(" { false, NULL }"); prefableSpecs.append(" { false, NULL }");
arrays = (("const %s: [%s * %i] = [\n" + arrays = (("static %s: [%s, ..%i] = [\n" +
',\n'.join(specs) + "\n" + ',\n'.join(specs) + "\n" +
"];\n\n") % (name, specType, len(specs))) "];\n\n") % (name, specType, len(specs)))
#+ #+
@ -1864,7 +1864,7 @@ class PropertyDefiner:
#',\n'.join(prefableSpecs) + "\n" + #',\n'.join(prefableSpecs) + "\n" +
#"];\n\n") #"];\n\n")
if doIdArrays: if doIdArrays:
arrays += ("const %s_ids: [jsid * %i] = [" % (name, len(specs))) + ", ".join(["JSID_VOID"] * len(specs)) + "];\n\n" arrays += ("static %s_ids: [jsid, ..%i] = [" % (name, len(specs))) + ", ".join(["JSID_VOID"] * len(specs)) + "];\n\n"
return arrays return arrays
# The length of a method is the maximum of the lengths of the # The length of a method is the maximum of the lengths of the
@ -1945,7 +1945,7 @@ class MethodDefiner(PropertyDefiner):
return (m["name"], accessor, jitinfo, m["length"], m["flags"]) return (m["name"], accessor, jitinfo, m["length"], m["flags"])
def stringDecl(m): def stringDecl(m):
return "const %s_name: [u8 * %i] = %s;\n" % (m["name"], len(m["name"]) + 1, return "static %s_name: [u8, ..%i] = %s;\n" % (m["name"], len(m["name"]) + 1,
str_to_const_array(m["name"])) str_to_const_array(m["name"]))
decls = ''.join([stringDecl(m) for m in array]) decls = ''.join([stringDecl(m) for m in array])
@ -1992,7 +1992,7 @@ class AttrDefiner(PropertyDefiner):
def stringDecl(attr): def stringDecl(attr):
name = attr.identifier.name name = attr.identifier.name
return "const %s_name: [u8 * %i] = %s;\n" % (name, len(name) + 1, return "static %s_name: [u8, ..%i] = %s;\n" % (name, len(name) + 1,
str_to_const_array(name)) str_to_const_array(name))
decls = ''.join([stringDecl(m) for m in array]) decls = ''.join([stringDecl(m) for m in array])
@ -2024,7 +2024,7 @@ class ConstDefiner(PropertyDefiner):
def stringDecl(const): def stringDecl(const):
name = const.identifier.name name = const.identifier.name
return "const %s_name: [u8 * %i] = %s;\n" % (name, len(name) + 1, return "static %s_name: [u8, ..%i] = %s;\n" % (name, len(name) + 1,
str_to_const_array(name)) str_to_const_array(name))
decls = ''.join([stringDecl(m) for m in array]) decls = ''.join([stringDecl(m) for m in array])
@ -2060,7 +2060,7 @@ class CGNativePropertyHooks(CGThing):
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks" parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks"
if parent else '0 as *NativePropertyHooks') if parent else '0 as *NativePropertyHooks')
return """ return """
const NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: %s }; static NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: %s };
""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks) """ % (resolveOwnProperty, enumerateOwnProperties, parentHooks)
# We'll want to insert the indent at the beginnings of lines, but we # We'll want to insert the indent at the beginnings of lines, but we
@ -2142,9 +2142,9 @@ class CGImports(CGWrapper):
# TODO imports to cover descriptors, etc. # TODO imports to cover descriptors, etc.
def _useString(imports): def _useString(imports):
return ''.join(['use %s;\n' % i for i in imports]) + '\n' return '#[allow(unused_imports)];' + ''.join(['use %s;\n' % i for i in imports]) + '\n'
CGWrapper.__init__(self, child, CGWrapper.__init__(self, child,
definePre=_useString(sorted(defineImports))) declarePre=_useString(sorted(declareImports)))
class CGIfWrapper(CGWrapper): class CGIfWrapper(CGWrapper):
def __init__(self, child, condition): def __init__(self, child, condition):
@ -2197,8 +2197,8 @@ class CGDOMJSClass(CGThing):
def define(self): def define(self):
traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else '0 as *u8' traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else '0 as *u8'
return """ return """
const Class_name: [u8 * %i] = %s; static Class_name: [u8, ..%i] = %s;
const Class: DOMJSClass = DOMJSClass { static Class: DOMJSClass = DOMJSClass {
base: JSClass { name: &Class_name as *u8 as *libc::c_char, base: JSClass { name: &Class_name as *u8 as *libc::c_char,
flags: JSCLASS_IS_DOMJSCLASS | ((1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(1), flags: JSCLASS_IS_DOMJSCLASS | ((1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT), //JSCLASS_HAS_RESERVED_SLOTS(1),
addProperty: %s, /* addProperty */ addProperty: %s, /* addProperty */
@ -2243,8 +2243,9 @@ class CGPrototypeJSClass(CGThing):
# We're purely for internal consumption # We're purely for internal consumption
return "" return ""
def define(self): def define(self):
return """const PrototypeClassName__: [u8 * %s] = %s; return """
const PrototypeClass: JSClass = JSClass { static PrototypeClassName__: [u8, ..%s] = %s;
static PrototypeClass: JSClass = JSClass {
name: &PrototypeClassName__ as *u8 as *libc::c_char, name: &PrototypeClassName__ as *u8 as *libc::c_char,
flags: (1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT, //JSCLASS_HAS_RESERVED_SLOTS(1) flags: (1 & JSCLASS_RESERVED_SLOTS_MASK) << JSCLASS_RESERVED_SLOTS_SHIFT, //JSCLASS_HAS_RESERVED_SLOTS(1)
addProperty: crust::JS_PropertyStub, /* addProperty */ addProperty: crust::JS_PropertyStub, /* addProperty */
@ -2285,7 +2286,7 @@ class CGInterfaceObjectJSClass(CGThing):
ctorname = "0 as *u8" if not self.descriptor.interface.ctor() else CONSTRUCT_HOOK_NAME ctorname = "0 as *u8" if not self.descriptor.interface.ctor() else CONSTRUCT_HOOK_NAME
hasinstance = HASINSTANCE_HOOK_NAME hasinstance = HASINSTANCE_HOOK_NAME
return """ return """
const InterfaceObjectClass: JSClass = { static InterfaceObjectClass: JSClass = {
%s, 0, %s, 0,
crust::JS_PropertyStub, /* addProperty */ crust::JS_PropertyStub, /* addProperty */
crust::JS_PropertyStub, /* delProperty */ crust::JS_PropertyStub, /* delProperty */
@ -3149,7 +3150,7 @@ class CGSpecializedMethod(CGAbstractExternMethod):
def __init__(self, descriptor, method): def __init__(self, descriptor, method):
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('*%s' % descriptor.nativeType, 'self'), Argument('*%s' % descriptor.nativeType, 'self'),
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)
@ -3194,7 +3195,7 @@ class CGSpecializedGetter(CGAbstractExternMethod):
self.attr = attr self.attr = attr
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, 'self'),
Argument('*mut JSVal', 'vp') ] Argument('*mut JSVal', 'vp') ]
CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args) CGAbstractExternMethod.__init__(self, descriptor, name, "JSBool", args)
@ -3245,7 +3246,7 @@ class CGMemberJITInfo(CGThing):
depth = self.descriptor.interface.inheritanceDepth() depth = self.descriptor.interface.inheritanceDepth()
failstr = "true" if infallible else "false" failstr = "true" if infallible else "false"
return ("\n" return ("\n"
"const %s: JSJitInfo = JSJitInfo {\n" "static %s: JSJitInfo = JSJitInfo {\n"
" op: %s,\n" " op: %s,\n"
" protoID: %s,\n" " protoID: %s,\n"
" depth: %s,\n" " depth: %s,\n"
@ -3690,7 +3691,7 @@ class CGDOMJSProxyHandlerDOMClass(CGThing):
return "" return ""
def define(self): def define(self):
return """ return """
const Class: DOMClass = """ + DOMClass(self.descriptor) + """; static Class: DOMClass = """ + DOMClass(self.descriptor) + """;
""" """
@ -3847,7 +3848,6 @@ class CGBindingRoot(CGThing):
# Add imports # Add imports
curr = CGImports(descriptors, curr = CGImports(descriptors,
dictionaries, dictionaries,
[],
['js::*', ['js::*',
'js::jsapi::*', 'js::jsapi::*',
'js::jsapi::bindgen::*', 'js::jsapi::bindgen::*',
@ -3863,6 +3863,7 @@ class CGBindingRoot(CGThing):
'dom::bindings::proxyhandler::*', 'dom::bindings::proxyhandler::*',
'content::content_task::task_from_context' 'content::content_task::task_from_context'
], ],
[],
curr) curr)
# Add the auto-generated comment. # Add the auto-generated comment.

View file

@ -3,7 +3,7 @@ use js::glue::bindgen::{RUST_INT_TO_JSVAL, RUST_JSVAL_TO_INT};
pub trait JSValConvertible<T> { pub trait JSValConvertible<T> {
fn to_jsval(&self) -> JSVal; fn to_jsval(&self) -> JSVal;
static fn from_jsval(val: JSVal) -> Option<T>; fn from_jsval(val: JSVal) -> Option<T>;
} }
impl JSValConvertible<u32> for u32 { impl JSValConvertible<u32> for u32 {
@ -11,7 +11,7 @@ impl JSValConvertible<u32> for u32 {
RUST_INT_TO_JSVAL(*self as i32) RUST_INT_TO_JSVAL(*self as i32)
} }
static fn from_jsval(val: JSVal) -> Option<u32> { fn from_jsval(val: JSVal) -> Option<u32> {
Some(RUST_JSVAL_TO_INT(val) as u32) Some(RUST_JSVAL_TO_INT(val) as u32)
} }
} }

View file

@ -1,27 +1,23 @@
use js::rust::{Compartment, jsobj}; use js::rust::{Compartment, jsobj};
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, use js::{JS_ARGV, JSPROP_ENUMERATE, JSPROP_SHARED,
JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS}; JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp,
JSPropertySpec, JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSPropertySpec, JSPropertyOpWrapper, JSStrictPropertyOpWrapper,
JSNativeWrapper, JSFunctionSpec}; JSNativeWrapper, JSFunctionSpec};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError, use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN, JS_DefineFunctions, JS_DefineProperties};
JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties};
use js::glue::bindgen::*; use js::glue::bindgen::*;
use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB}; use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB};
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub};
use core::ptr::null; use core::ptr::null;
use core::libc::c_uint; use core::libc::c_uint;
use dom::bindings::utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str}; use dom::bindings::utils::{DOMString, rust_box, squirrel_away, str};
use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper}; use dom::bindings::utils::{jsval_to_str, WrapNewBindingObject, CacheableWrapper};
use dom::bindings::utils::WrapperCache; use dom::bindings::utils::WrapperCache;
use dom::bindings::node::create;
use dom::document::Document; use dom::document::Document;
use dom::bindings::htmlcollection::HTMLCollection; use dom::bindings::htmlcollection::HTMLCollection;
use dom::bindings::node; use dom::bindings::node;
use dom::bindings::utils; use dom::bindings::utils;
use dom::node::Node;
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 {
@ -36,7 +32,7 @@ extern fn getDocumentElement(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> J
} }
} }
extern fn getElementsByTagName(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn getElementsByTagName(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {
let obj = JS_THIS_OBJECT(cx, vp); let obj = JS_THIS_OBJECT(cx, vp);
@ -56,7 +52,7 @@ extern fn getElementsByTagName(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBo
JS_SET_RVAL(cx, vp, JSVAL_NULL); JS_SET_RVAL(cx, vp, JSVAL_NULL);
} else { } else {
let cache = doc.get_wrappercache(); let cache = doc.get_wrappercache();
fail_unless!(WrapNewBindingObject(cx, cache.get_wrapper(), assert!(WrapNewBindingObject(cx, cache.get_wrapper(),
rval.get(), rval.get(),
cast::transmute(vp))); cast::transmute(vp)));
} }
@ -96,7 +92,7 @@ pub fn init(compartment: @mut Compartment, doc: @mut Document) {
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| {
fail_unless!(JS_DefineProperties(compartment.cx.ptr, obj.ptr, specs) == 1); 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"),
@ -136,11 +132,11 @@ impl CacheableWrapper for Document {
unsafe { cast::transmute(&self.wrapper) } unsafe { cast::transmute(&self.wrapper) }
} }
fn wrap_object_unique(~self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_unique(~self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"need to implement wrapping"); fail!(~"need to implement wrapping");
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"need to implement wrapping"); fail!(~"need to implement wrapping");
} }
} }

View file

@ -1,23 +1,20 @@
use content::content_task::{Content, task_from_context}; use content::content_task::task_from_context;
use dom::bindings::utils::{rust_box, squirrel_away_unique, get_compartment};
use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject}; use dom::bindings::utils::{domstring_to_jsval, WrapNewBindingObject};
use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT}; use dom::bindings::utils::{str, CacheableWrapper, DOM_OBJECT_SLOT};
use dom::bindings::clientrectlist::ClientRectListImpl;
use dom::element::*; use dom::element::*;
use dom::node::{AbstractNode, Node, Element, ElementNodeTypeId}; use dom::node::{AbstractNode, Element, ElementNodeTypeId};
use layout::layout_task; use layout::layout_task;
use super::utils; use super::utils;
use core::libc::c_uint; use core::libc::c_uint;
use core::ptr::null; use core::ptr::null;
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub};
use js::glue::bindgen::*; use js::glue::bindgen::*;
use js::jsapi::bindgen::*; use js::jsapi::bindgen::*;
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSFunctionSpec}; use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper, JSFunctionSpec};
use js::jsapi::JSNativeWrapper; use js::jsapi::JSNativeWrapper;
use js::rust::{Compartment, jsobj}; use js::rust::{Compartment, jsobj};
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL}; use js::{JS_ARGV, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS}; use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
@ -25,7 +22,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
unsafe { unsafe {
let val = JS_GetReservedSlot(obj, DOM_OBJECT_SLOT as u32); let val = JS_GetReservedSlot(obj, DOM_OBJECT_SLOT as u32);
let node: AbstractNode = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val)); let node: AbstractNode = cast::reinterpret_cast(&RUST_JSVAL_TO_PRIVATE(val));
let elem: ~Element = cast::transmute(node.raw_object()); let _elem: ~Element = cast::transmute(node.raw_object());
} }
} }
@ -89,7 +86,7 @@ pub fn init(compartment: @mut Compartment) {
}); });
} }
extern fn getClientRects(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn getClientRects(cx: *JSContext, _argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {
let obj = JS_THIS_OBJECT(cx, vp); let obj = JS_THIS_OBJECT(cx, vp);
let mut box = utils::unwrap::<*mut AbstractNode>(obj); let mut box = utils::unwrap::<*mut AbstractNode>(obj);
@ -101,7 +98,7 @@ extern fn getClientRects(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
JS_SET_RVAL(cx, vp, JSVAL_NULL); JS_SET_RVAL(cx, vp, JSVAL_NULL);
} else { } else {
let cache = node.get_wrappercache(); let cache = node.get_wrappercache();
fail_unless!(WrapNewBindingObject(cx, cache.get_wrapper(), assert!(WrapNewBindingObject(cx, cache.get_wrapper(),
rval.get(), rval.get(),
cast::transmute(vp))); cast::transmute(vp)));
} }

View file

@ -1,5 +1,4 @@
use content::content_task::task_from_context; use content::content_task::task_from_context;
use dom::element::Element;
use dom::node::AbstractNode; use dom::node::AbstractNode;
use dom::bindings::codegen::HTMLCollectionBinding; use dom::bindings::codegen::HTMLCollectionBinding;
use dom::bindings::utils::{DOMString, ErrorResult, OpaqueBindingReference}; use dom::bindings::utils::{DOMString, ErrorResult, OpaqueBindingReference};
@ -12,7 +11,7 @@ pub struct HTMLCollection {
} }
pub impl HTMLCollection { pub impl HTMLCollection {
static fn new(elements: ~[AbstractNode]) -> HTMLCollection { fn new(elements: ~[AbstractNode]) -> HTMLCollection {
HTMLCollection { HTMLCollection {
elements: elements, elements: elements,
wrapper: WrapperCache::new() wrapper: WrapperCache::new()
@ -31,7 +30,7 @@ pub impl HTMLCollection {
} }
} }
fn NamedItem(&self, cx: *JSContext, name: DOMString, rv: &mut ErrorResult) -> *JSObject { fn NamedItem(&self, _cx: *JSContext, _name: DOMString, rv: &mut ErrorResult) -> *JSObject {
*rv = Ok(()); *rv = Ok(());
ptr::null() ptr::null()
} }
@ -59,7 +58,7 @@ impl CacheableWrapper for HTMLCollection {
HTMLCollectionBinding::Wrap(cx, scope, self, &mut unused) HTMLCollectionBinding::Wrap(cx, scope, self, &mut unused)
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"nyi") fail!(~"nyi")
} }
} }

View file

@ -1,25 +1,20 @@
use dom::bindings::utils::{rust_box, squirrel_away_unique, get_compartment}; use dom::bindings::utils::{CacheableWrapper, WrapperCache};
use dom::bindings::utils::{str, domstring_to_jsval, CacheableWrapper, WrapperCache};
use dom::bindings::utils::{DOM_OBJECT_SLOT}; use dom::bindings::utils::{DOM_OBJECT_SLOT};
use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId}; use dom::node::{AbstractNode, Node, ElementNodeTypeId, TextNodeTypeId, CommentNodeTypeId};
use dom::node::{DoctypeNodeTypeId}; use dom::node::{DoctypeNodeTypeId};
use super::element; use super::element;
use super::utils; use super::utils;
use core::cast::transmute;
use core::libc::c_uint; use core::libc::c_uint;
use core::ptr::null; use core::ptr::null;
use js::glue::bindgen::*; use js::glue::bindgen::*;
use js::jsapi::bindgen::*; use js::jsapi::bindgen::*;
use js::jsapi::bindgen::{JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSPropertySpec};
use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSPropertySpec};
use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper}; use js::jsapi::{JSPropertyOpWrapper, JSStrictPropertyOpWrapper};
use js::jsval::{INT_TO_JSVAL, JSVAL_TO_PRIVATE}; use js::jsval::{INT_TO_JSVAL, JSVAL_TO_PRIVATE};
use js::rust::{Compartment, jsobj}; use js::rust::{Compartment, jsobj};
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL}; use js::{JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS}; use js::{JS_THIS_OBJECT, JSPROP_NATIVE_ACCESSORS};
use js; use js;
pub fn init(compartment: @mut Compartment) { pub fn init(compartment: @mut Compartment) {
@ -172,11 +167,11 @@ impl CacheableWrapper for AbstractNode {
} }
} }
fn wrap_object_unique(~self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_unique(~self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"need to implement wrapping"); fail!(~"need to implement wrapping");
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"need to implement wrapping"); fail!(~"need to implement wrapping");
} }
} }

View file

@ -1,6 +1,5 @@
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_GetPrototype}; use js::jsapi::bindgen::{JS_GetPropertyDescriptorById, JS_NewUCString, JS_malloc, JS_free};
use js::jsapi::bindgen::{JS_NewUCString, JS_malloc, JS_free};
use js::glue::bindgen::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra}; use js::glue::bindgen::{RUST_JSVAL_IS_VOID, RUST_JSVAL_TO_OBJECT, GetProxyExtra};
use js::glue::bindgen::{GetObjectProto}; use js::glue::bindgen::{GetObjectProto};
@ -31,7 +30,7 @@ pub extern fn getPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
} }
fn _getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid, fn _getOwnPropertyDescriptor(cx: *JSContext, proxy: *JSObject, id: jsid,
set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool { _set: c_bool, desc: *mut JSPropertyDescriptor) -> c_bool {
unsafe { unsafe {
let v = GetProxyExtra(proxy, 0 /*JSPROXYSLOT_EXPANDO*/); let v = GetProxyExtra(proxy, 0 /*JSPROXYSLOT_EXPANDO*/);
if RUST_JSVAL_IS_VOID(v) == 0 { if RUST_JSVAL_IS_VOID(v) == 0 {
@ -77,6 +76,6 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
} }
} }
pub fn GetExpandoObject(proxy: *JSObject) -> *JSObject { pub fn GetExpandoObject(_proxy: *JSObject) -> *JSObject {
ptr::null() ptr::null()
} }

View file

@ -1,18 +1,18 @@
use js; use js;
use js::rust::Compartment; use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, use js::{JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSVAL_NULL,
JS_THIS_OBJECT, JS_SET_RVAL, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY, JS_THIS_OBJECT, JSFUN_CONSTRUCTOR, JS_CALLEE, JSPROP_READONLY,
JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER, JSPROP_SETTER}; JSPROP_PERMANENT, JSID_VOID, JSPROP_NATIVE_ACCESSORS, JSPROP_GETTER, JSPROP_SETTER};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSNative, use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSNative,
JSFunctionSpec, JSPropertySpec, JSVal, JSString, JSPropertyDescriptor}; JSFunctionSpec, JSPropertySpec, JSVal, JSPropertyDescriptor};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError, use js::jsapi::bindgen::{JS_ValueToString,
JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN, JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN,
JS_DefineFunctions, JS_DefineProperty, JS_GetContextPrivate, JS_DefineFunctions, JS_DefineProperty,
JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype, JS_GetClass, JS_GetPrototype, JS_LinkConstructorAndPrototype,
JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction, JS_AlreadyHasOwnProperty, JS_NewObject, JS_NewFunction,
JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject, JS_GetFunctionPrototype, JS_InternString, JS_GetFunctionObject,
JS_GetInternedStringCharsAndLength, JS_DefineProperties, JS_DefineProperties,
JS_WrapValue, JS_GetObjectPrototype, JS_ForwardGetPropertyTo, JS_WrapValue, JS_ForwardGetPropertyTo,
JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject, JS_HasPropertyById, JS_GetPrototype, JS_GetGlobalForObject,
JS_EncodeString, JS_free}; JS_EncodeString, JS_free};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
@ -22,33 +22,33 @@ use js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_STUB
use js::glue::bindgen::*; use js::glue::bindgen::*;
use core::ptr::null; use core::ptr::null;
use core::cast; use core::cast;
use content::content_task::{Content, task_from_context}; use content::content_task::task_from_context;
use core::hashmap::linear; use core::hashmap::HashMap;
use dom::bindings::node; use dom::bindings::node;
use dom::node::AbstractNode; use dom::node::AbstractNode;
const TOSTRING_CLASS_RESERVED_SLOT: u64 = 0; static TOSTRING_CLASS_RESERVED_SLOT: u64 = 0;
const TOSTRING_NAME_RESERVED_SLOT: u64 = 1; static TOSTRING_NAME_RESERVED_SLOT: u64 = 1;
struct GlobalStaticData { struct GlobalStaticData {
proxy_handlers: linear::LinearMap<uint, *libc::c_void>, proxy_handlers: HashMap<uint, *libc::c_void>,
attribute_ids: linear::LinearMap<uint, ~[jsid]>, attribute_ids: HashMap<uint, ~[jsid]>,
method_ids: linear::LinearMap<uint, ~[jsid]>, method_ids: HashMap<uint, ~[jsid]>,
constant_ids: linear::LinearMap<uint, ~[jsid]> constant_ids: HashMap<uint, ~[jsid]>
} }
pub fn GlobalStaticData() -> GlobalStaticData { pub fn GlobalStaticData() -> GlobalStaticData {
GlobalStaticData { GlobalStaticData {
proxy_handlers: linear::LinearMap::new(), proxy_handlers: HashMap::new(),
attribute_ids: linear::LinearMap::new(), attribute_ids: HashMap::new(),
method_ids: linear::LinearMap::new(), method_ids: HashMap::new(),
constant_ids: linear::LinearMap::new() constant_ids: HashMap::new()
} }
} }
extern fn InterfaceObjectToString(cx: *JSContext, argc: uint, vp: *mut JSVal) -> JSBool { extern fn InterfaceObjectToString(cx: *JSContext, _argc: uint, vp: *mut JSVal) -> JSBool {
unsafe { unsafe {
let callee = RUST_JSVAL_TO_OBJECT(*JS_CALLEE(cx, cast::transmute(&vp))); let callee = RUST_JSVAL_TO_OBJECT(*JS_CALLEE(cx, cast::transmute(&vp)));
let obj = JS_THIS_OBJECT(cx, cast::transmute(&vp)); let obj = JS_THIS_OBJECT(cx, cast::transmute(&vp));
@ -160,10 +160,9 @@ pub unsafe fn domstring_to_jsval(cx: *JSContext, string: &DOMString) -> JSVal {
pub fn get_compartment(cx: *JSContext) -> @mut Compartment { pub fn get_compartment(cx: *JSContext) -> @mut Compartment {
unsafe { unsafe {
let content = task_from_context(cx); let content = task_from_context(cx);
let compartment = option::expect((*content).compartment, let compartment = (*content).compartment.expect(~"Should always have compartment when \
~"Should always have compartment when \ executing JS code");
executing JS code"); assert!(cx == compartment.cx.ptr);
fail_unless!(cx == compartment.cx.ptr);
compartment compartment
} }
} }
@ -270,23 +269,23 @@ pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut
// 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
// globals and non-globals. // globals and non-globals.
pub const DOM_OBJECT_SLOT: uint = 0; pub static DOM_OBJECT_SLOT: uint = 0;
const DOM_PROXY_OBJECT_SLOT: uint = js::JSSLOT_PROXY_PRIVATE as uint; static DOM_PROXY_OBJECT_SLOT: uint = js::JSSLOT_PROXY_PRIVATE as uint;
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and // NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value // LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes. // changes.
const DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0; static DOM_PROTO_INSTANCE_CLASS_SLOT: u32 = 0;
// All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to // All DOM globals must have a slot at DOM_PROTOTYPE_SLOT. We have to
// start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses // start at 1 past JSCLASS_GLOBAL_SLOT_COUNT because XPConnect uses
// that one. // that one.
pub const DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1; pub static DOM_PROTOTYPE_SLOT: u32 = js::JSCLASS_GLOBAL_SLOT_COUNT + 1;
// NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and // NOTE: This is baked into the Ion JIT as 0 in codegen for LGetDOMProperty and
// LSetDOMProperty. Those constants need to be changed accordingly if this value // LSetDOMProperty. Those constants need to be changed accordingly if this value
// changes. // changes.
const JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1; static JSCLASS_DOM_GLOBAL: u32 = js::JSCLASS_USERBIT1;
pub struct NativeProperties { pub struct NativeProperties {
staticMethods: *JSFunctionSpec, staticMethods: *JSFunctionSpec,
@ -330,7 +329,7 @@ pub struct ConstantSpec {
pub struct DOMClass { pub struct DOMClass {
// A list of interfaces that this object implements, in order of decreasing // A list of interfaces that this object implements, in order of decreasing
// derivedness. // derivedness.
interface_chain: [prototypes::id::Prototype * 2 /*max prototype chain length*/], interface_chain: [prototypes::id::Prototype, ..2 /*max prototype chain length*/],
unused: bool, // DOMObjectIsISupports (always false) unused: bool, // DOMObjectIsISupports (always false)
native_hooks: *NativePropertyHooks native_hooks: *NativePropertyHooks
@ -418,7 +417,7 @@ fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject,
JS_NewObject(cx, constructorClass, functionProto, global) JS_NewObject(cx, constructorClass, functionProto, global)
} }
} else { } else {
fail_unless!(constructorNative.is_not_null()); assert!(constructorNative.is_not_null());
let fun = JS_NewFunction(cx, constructorNative, ctorNargs, let fun = JS_NewFunction(cx, constructorNative, ctorNargs,
JSFUN_CONSTRUCTOR, global, name); JSFUN_CONSTRUCTOR, global, name);
if fun.is_null() { if fun.is_null() {
@ -535,13 +534,13 @@ fn CreateInterfacePrototypeObject(cx: *JSContext, global: *JSObject,
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 {
//XXX should trigger exception here //XXX should trigger exception here
return 0; return 0;
} }
pub fn initialize_global(global: *JSObject) { pub fn initialize_global(global: *JSObject) {
let protoArray = @mut [0 as *JSObject, ..3]; //XXXjdm prototypes::_ID_COUNT let protoArray = @mut ~[0 as *JSObject, ..3]; //XXXjdm prototypes::_ID_COUNT
unsafe { unsafe {
//XXXjdm we should be storing the box pointer instead of the inner //XXXjdm we should be storing the box pointer instead of the inner
let box = squirrel_away(protoArray); let box = squirrel_away(protoArray);
@ -571,7 +570,7 @@ pub impl WrapperCache {
unsafe { self.wrapper = wrapper; } unsafe { self.wrapper = wrapper; }
} }
static fn new() -> WrapperCache { fn new() -> WrapperCache {
WrapperCache { WrapperCache {
wrapper: ptr::null() wrapper: ptr::null()
} }
@ -642,7 +641,7 @@ pub impl<T: BindingObject + CacheableWrapper> BindingReference<T> {
} }
} }
fn get_wrappercache(&mut self) -> &self/mut WrapperCache { fn get_wrappercache(&mut self) -> &mut WrapperCache {
match **self { match **self {
Left(ref mut obj) => obj.get_wrappercache(), Left(ref mut obj) => obj.get_wrappercache(),
Right(ref mut obj) => obj.get_wrappercache() Right(ref mut obj) => obj.get_wrappercache()
@ -684,7 +683,7 @@ 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 { if RUST_JSID_IS_INT(id) != 0 {
return Some(RUST_JSID_TO_INT(id) as u32); return Some(RUST_JSID_TO_INT(id) as u32);
} }
@ -709,9 +708,9 @@ pub fn XrayResolveProperty(cx: *JSContext,
wrapper: *JSObject, wrapper: *JSObject,
id: jsid, id: jsid,
desc: *mut JSPropertyDescriptor, desc: *mut JSPropertyDescriptor,
methods: Option<~[(JSFunctionSpec, jsid)]>, _methods: Option<~[(JSFunctionSpec, jsid)]>,
attributes: Option<~[(JSPropertySpec, jsid)]>, attributes: Option<~[(JSPropertySpec, jsid)]>,
constants: Option<~[(ConstantSpec, jsid)]>) -> bool _constants: Option<~[(ConstantSpec, jsid)]>) -> bool
{ {
unsafe { unsafe {
match attributes { match attributes {
@ -785,7 +784,7 @@ pub trait DerivedWrapper {
} }
impl DerivedWrapper for AbstractNode { impl DerivedWrapper for AbstractNode {
fn wrap(&mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 { fn wrap(&mut self, cx: *JSContext, _scope: *JSObject, vp: *mut JSVal) -> i32 {
let cache = self.get_wrappercache(); let cache = self.get_wrappercache();
let wrapper = cache.get_wrapper(); let wrapper = cache.get_wrapper();
if wrapper.is_not_null() { if wrapper.is_not_null() {

View file

@ -1,34 +1,30 @@
// DOM bindings for the Window object. // DOM bindings for the Window object.
use dom::bindings::node::create; use dom::bindings::utils::{rust_box, squirrel_away, CacheableWrapper};
use dom::bindings::utils::{rust_box, squirrel_away, jsval_to_str, CacheableWrapper};
use dom::bindings::utils::{WrapperCache}; use dom::bindings::utils::{WrapperCache};
use dom::node::Node; use dom::window::Window;
use dom::window::{Window, TimerMessage_Fire};
use super::utils; use super::utils;
use core::libc::c_uint; use core::libc::c_uint;
use core::ptr::null; use core::ptr::null;
use core::ptr; use core::ptr;
use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub}; use js::crust::{JS_PropertyStub, JS_StrictPropertyStub};
use js::crust::{JS_ResolveStub};
use js::global::jsval_to_rust_str; use js::global::jsval_to_rust_str;
use js::glue::bindgen::*; use js::glue::bindgen::*;
use js::glue::bindgen::RUST_JSVAL_TO_INT; use js::glue::bindgen::RUST_JSVAL_TO_INT;
use js::jsapi::bindgen::{JS_DefineFunctions, JS_DefineProperty, JS_DefineProperties}; use js::jsapi::bindgen::{JS_DefineFunctions};
use js::jsapi::bindgen::{JS_EncodeString, JS_free}; use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsapi::bindgen::{JS_GetReservedSlot, JS_SetReservedSlot, JS_NewStringCopyN}; use js::jsapi::bindgen::{JS_ValueToString};
use js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_ReportError}; use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSFunctionSpec};
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, jsid, JSClass, JSFreeOp, JSFunctionSpec};
use js::jsapi::{JSNativeWrapper}; use js::jsapi::{JSNativeWrapper};
use js::rust::Compartment; use js::rust::Compartment;
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL}; use js::{JS_ARGV, JSPROP_ENUMERATE, JSVAL_NULL};
use js::{JS_THIS_OBJECT, JS_SET_RVAL}; use js::{JS_THIS_OBJECT, JS_SET_RVAL};
extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {
let argv = JS_ARGV(cx, vp); let argv = JS_ARGV(cx, vp);
fail_unless!(argc == 1); assert!(argc == 1);
// Abstract this pattern and use it in debug, too? // Abstract this pattern and use it in debug, too?
let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0)); let jsstr = JS_ValueToString(cx, *ptr::offset(argv, 0));
@ -42,7 +38,7 @@ extern fn alert(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool { extern fn setTimeout(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
unsafe { unsafe {
let argv = JS_ARGV(cx, vp); let argv = JS_ARGV(cx, vp);
fail_unless!(argc >= 2); assert!(argc >= 2);
//TODO: don't crash when passed a non-integer value for the timeout //TODO: don't crash when passed a non-integer value for the timeout
@ -137,11 +133,11 @@ impl CacheableWrapper for Window {
unsafe { cast::transmute(&self.wrapper) } unsafe { cast::transmute(&self.wrapper) }
} }
fn wrap_object_unique(~self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_unique(~self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"should this be called?"); fail!(~"should this be called?");
} }
fn wrap_object_shared(@self, cx: *JSContext, scope: *JSObject) -> *JSObject { fn wrap_object_shared(@self, _cx: *JSContext, _scope: *JSObject) -> *JSObject {
fail!(~"should this be called?"); fail!(~"should this be called?");
} }
} }

View file

@ -1,9 +1,7 @@
use dom::bindings::htmlcollection::HTMLCollection; use dom::bindings::htmlcollection::HTMLCollection;
use dom::bindings::utils::{DOMString, WrapperCache, str}; use dom::bindings::utils::{DOMString, WrapperCache, str};
use dom::node::AbstractNode; use dom::node::AbstractNode;
use newcss::stylesheet::Stylesheet;
use std::arc::ARC;
pub struct Document { pub struct Document {
root: AbstractNode, root: AbstractNode,

View file

@ -15,7 +15,7 @@ pub struct Element {
attrs: ~[Attr], attrs: ~[Attr],
} }
#[deriving_eq] #[deriving(Eq)]
pub enum ElementTypeId { pub enum ElementTypeId {
HTMLAnchorElementTypeId, HTMLAnchorElementTypeId,
HTMLAsideElementTypeId, HTMLAsideElementTypeId,
@ -109,7 +109,7 @@ pub struct HTMLImageElement {
// //
pub impl Element { pub impl Element {
static 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)),
tag_name: tag_name, tag_name: tag_name,
@ -117,7 +117,7 @@ pub impl Element {
} }
} }
fn get_attr(&self, name: &str) -> Option<&self/str> { fn get_attr(&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) {
@ -151,7 +151,7 @@ pub struct Attr {
} }
impl Attr { impl Attr {
static pub fn new(name: ~str, value: ~str) -> Attr { pub fn new(name: ~str, value: ~str) -> Attr {
Attr { Attr {
name: name, name: name,
value: value value: value

View file

@ -12,16 +12,9 @@ use dom::window::Window;
use layout::debug::DebugMethods; use layout::debug::DebugMethods;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use newcss::complete::CompleteSelectResults; use newcss::complete::CompleteSelectResults;
use js::rust::Compartment;
use core::cast::transmute; use core::cast::transmute;
use core::ptr::null;
use geom::size::Size2D;
use js::crust::*;
use js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
use js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, JSVal, JSBool};
use js::jsapi::bindgen::JS_SetReservedSlot;
use js::rust::Compartment;
use std::arc::ARC;
// //
// The basic Node structure // The basic Node structure
@ -36,8 +29,8 @@ pub struct AbstractNode {
} }
impl Eq for AbstractNode { impl Eq for AbstractNode {
pure fn eq(&self, other: &AbstractNode) -> bool { self.obj == other.obj } fn eq(&self, other: &AbstractNode) -> bool { self.obj == other.obj }
pure fn ne(&self, other: &AbstractNode) -> bool { self.obj != other.obj } fn ne(&self, other: &AbstractNode) -> bool { self.obj != other.obj }
} }
pub struct Node { pub struct Node {
@ -54,7 +47,7 @@ pub struct Node {
priv layout_data: Option<@mut LayoutData> priv layout_data: Option<@mut LayoutData>
} }
#[deriving_eq] #[deriving(Eq)]
pub enum NodeTypeId { pub enum NodeTypeId {
DoctypeNodeTypeId, DoctypeNodeTypeId,
CommentNodeTypeId, CommentNodeTypeId,
@ -72,7 +65,7 @@ pub struct LayoutData {
} }
impl LayoutData { impl LayoutData {
static pub fn new() -> LayoutData { pub fn new() -> LayoutData {
LayoutData { LayoutData {
style: None, style: None,
flow: None, flow: None,
@ -93,11 +86,11 @@ pub struct Doctype {
} }
impl Doctype { impl Doctype {
static pub fn new(name: ~str, pub fn new(name: ~str,
public_id: Option<~str>, public_id: Option<~str>,
system_id: Option<~str>, system_id: Option<~str>,
force_quirks: bool) force_quirks: bool)
-> Doctype { -> Doctype {
Doctype { Doctype {
parent: Node::new(DoctypeNodeTypeId), parent: Node::new(DoctypeNodeTypeId),
name: name, name: name,
@ -114,7 +107,7 @@ pub struct Comment {
} }
impl Comment { impl Comment {
static pub fn new(text: ~str) -> Comment { pub fn new(text: ~str) -> Comment {
Comment { Comment {
parent: Node::new(CommentNodeTypeId), parent: Node::new(CommentNodeTypeId),
text: text text: text
@ -128,7 +121,7 @@ pub struct Text {
} }
impl Text { impl Text {
static pub fn new(text: ~str) -> Text { pub fn new(text: ~str) -> Text {
Text { Text {
parent: Node::new(TextNodeTypeId), parent: Node::new(TextNodeTypeId),
text: text text: text
@ -171,13 +164,13 @@ pub impl AbstractNode {
// Invariant: `child` is disconnected from the document. // Invariant: `child` is disconnected from the document.
fn append_child(self, child: AbstractNode) { fn append_child(self, child: AbstractNode) {
fail_unless!(self != child); assert!(self != child);
do self.with_mut_node |parent_n| { do self.with_mut_node |parent_n| {
do child.with_mut_node |child_n| { do child.with_mut_node |child_n| {
fail_unless!(child_n.parent_node.is_none()); assert!(child_n.parent_node.is_none());
fail_unless!(child_n.prev_sibling.is_none()); assert!(child_n.prev_sibling.is_none());
fail_unless!(child_n.next_sibling.is_none()); assert!(child_n.next_sibling.is_none());
child_n.parent_node = Some(self); child_n.parent_node = Some(self);
@ -185,7 +178,7 @@ pub impl AbstractNode {
None => parent_n.first_child = Some(child), None => parent_n.first_child = Some(child),
Some(last_child) => { Some(last_child) => {
do last_child.with_mut_node |last_child_n| { do last_child.with_mut_node |last_child_n| {
fail_unless!(last_child_n.next_sibling.is_none()); assert!(last_child_n.next_sibling.is_none());
last_child_n.next_sibling = Some(child); last_child_n.next_sibling = Some(child);
} }
} }
@ -323,12 +316,12 @@ pub impl AbstractNode {
impl DebugMethods for AbstractNode { impl DebugMethods for AbstractNode {
// Dumps the subtree rooted at this node, for debugging. // Dumps the subtree rooted at this node, for debugging.
pure fn dump(&self) { fn dump(&self) {
self.dump_indent(0); self.dump_indent(0);
} }
// Dumps the node tree, for debugging, with indentation. // Dumps the node tree, for debugging, with indentation.
pure fn dump_indent(&self, indent: uint) { fn dump_indent(&self, indent: uint) {
let mut s = ~""; let mut s = ~"";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~" "; s += ~" ";
@ -345,7 +338,7 @@ impl DebugMethods for AbstractNode {
} }
} }
pure fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
// Unsafe due to the call to type_id(). // Unsafe due to the call to type_id().
unsafe { unsafe {
fmt!("%?", self.type_id()) fmt!("%?", self.type_id())
@ -354,14 +347,14 @@ impl DebugMethods for AbstractNode {
} }
impl Node { impl Node {
static pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode { pub unsafe fn as_abstract_node<N>(node: ~N) -> AbstractNode {
// This surrenders memory management of the node! // This surrenders memory management of the node!
AbstractNode { AbstractNode {
obj: transmute(node), obj: transmute(node),
} }
} }
static pub fn new(type_id: NodeTypeId) -> Node { pub fn new(type_id: NodeTypeId) -> Node {
Node { Node {
wrapper: WrapperCache::new(), wrapper: WrapperCache::new(),
type_id: type_id, type_id: type_id,
@ -384,13 +377,13 @@ pub fn define_bindings(compartment: @mut Compartment, doc: @mut Document, win: @
bindings::element::init(compartment); bindings::element::init(compartment);
bindings::utils::initialize_global(compartment.global_obj.ptr); bindings::utils::initialize_global(compartment.global_obj.ptr);
let mut unused = false; let mut unused = false;
fail_unless!(codegen::ClientRectBinding::DefineDOMInterface(compartment.cx.ptr, assert!(codegen::ClientRectBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr, compartment.global_obj.ptr,
&mut unused)); &mut unused));
fail_unless!(codegen::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr, assert!(codegen::ClientRectListBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr, compartment.global_obj.ptr,
&mut unused)); &mut unused));
fail_unless!(codegen::HTMLCollectionBinding::DefineDOMInterface(compartment.cx.ptr, assert!(codegen::HTMLCollectionBinding::DefineDOMInterface(compartment.cx.ptr,
compartment.global_obj.ptr, compartment.global_obj.ptr,
&mut unused)); &mut unused));
} }

View file

@ -1,6 +1,6 @@
use content::content_task::{ControlMsg, Timer, ExitMsg}; use content::content_task::{ControlMsg, Timer, ExitMsg};
use dom::bindings::utils::WrapperCache; use dom::bindings::utils::WrapperCache;
use js::jsapi::{JSVal, JSObject}; use js::jsapi::JSVal;
use util::task::spawn_listener; use util::task::spawn_listener;
use core::comm::{Port, Chan}; use core::comm::{Port, Chan};

View file

@ -1,4 +1,4 @@
use content::content_task::{ContentTask, ExecuteMsg, ParseMsg, ExitMsg}; use content::content_task::{ContentTask, ExecuteMsg, ParseMsg};
use content::content_task; use content::content_task;
use dom::event::Event; use dom::event::Event;
use layout::layout_task; use layout::layout_task;

View file

@ -5,13 +5,11 @@ Some little helpers for hooking up the HTML parser with the CSS parser
use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done}; use resource::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Port, Chan}; use core::comm::Port;
use core::pipes;
use core::str; use core::str;
use newcss::stylesheet::Stylesheet; use newcss::stylesheet::Stylesheet;
use newcss::util::DataStream; use newcss::util::DataStream;
use std::net::url::Url; use std::net::url::Url;
use std::net::url;
/// Where a style sheet comes from. /// Where a style sheet comes from.
pub enum StylesheetProvenance { pub enum StylesheetProvenance {

View file

@ -1,19 +1,16 @@
use content::content_task::ContentTask;
use dom::element::*; use dom::element::*;
use dom::event::{Event, ReflowEvent};
use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, Node, Text}; use dom::node::{AbstractNode, Comment, Doctype, Element, ElementNodeTypeId, 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 resource::image_cache_task::ImageCacheTask; use resource::image_cache_task::ImageCacheTask;
use resource::image_cache_task; use resource::image_cache_task;
use resource::resource_task::{Done, Load, Payload, ResourceTask}; use resource::resource_task::{Done, Load, Payload, ResourceTask};
use util::task::{spawn_listener, spawn_conversation}; use util::task::spawn_conversation;
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan}; use core::comm::{Chan, Port, SharedChan};
use core::str::eq_slice; use core::str::eq_slice;
use gfx::util::url::make_url; use gfx::util::url::make_url;
use hubbub::hubbub::Attribute;
use hubbub::hubbub; use hubbub::hubbub;
use std::net::url::Url; use std::net::url::Url;
use std::net::url; use std::net::url;
@ -21,11 +18,11 @@ use std::net::url;
macro_rules! handle_element( macro_rules! handle_element(
($tag:expr, $string:expr, $ctor:ident, $type_id:expr) => ( ($tag:expr, $string:expr, $ctor:ident, $type_id:expr) => (
if eq_slice($tag, $string) { if eq_slice($tag, $string) {
let element = ~$ctor { let _element = ~$ctor {
parent: Element::new($type_id, ($tag).to_str()) parent: Element::new($type_id, ($tag).to_str())
}; };
unsafe { unsafe {
return Node::as_abstract_node(element); return Node::as_abstract_node(_element);
} }
} }
) )
@ -34,12 +31,12 @@ macro_rules! handle_element(
macro_rules! handle_heading_element( macro_rules! handle_heading_element(
($tag:expr, $string:expr, $ctor:ident, $type_id:expr, $level:expr) => ( ($tag:expr, $string:expr, $ctor:ident, $type_id:expr, $level:expr) => (
if eq_slice($tag, $string) { if eq_slice($tag, $string) {
let element = ~HTMLHeadingElement { let _element = ~HTMLHeadingElement {
parent: Element::new($type_id, ($tag).to_str()), parent: Element::new($type_id, ($tag).to_str()),
level: $level level: $level
}; };
unsafe { unsafe {
return Node::as_abstract_node(element); return Node::as_abstract_node(_element);
} }
} }
) )
@ -65,14 +62,14 @@ struct HtmlParserResult {
trait NodeWrapping { trait NodeWrapping {
unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr; unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr;
static unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> Self; unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> Self;
} }
impl NodeWrapping for AbstractNode { impl NodeWrapping for AbstractNode {
unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr { unsafe fn to_hubbub_node(self) -> hubbub::NodeDataPtr {
cast::transmute(self) cast::transmute(self)
} }
static unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> AbstractNode { unsafe fn from_hubbub_node(n: hubbub::NodeDataPtr) -> AbstractNode {
cast::transmute(n) cast::transmute(n)
} }
} }
@ -221,7 +218,6 @@ pub fn parse_html(url: Url,
}; };
let css_chan = SharedChan(css_chan); let css_chan = SharedChan(css_chan);
let resource_task2 = resource_task.clone();
// 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_port, js_chan): (Port<JSResult>, Chan<JSMessage>) = let (js_port, js_chan): (Port<JSResult>, Chan<JSMessage>) =
@ -231,7 +227,7 @@ pub fn parse_html(url: Url,
}; };
let js_chan = SharedChan(js_chan); let js_chan = SharedChan(js_chan);
let url = @url; let url2 = url.clone(), url3 = url.clone();
unsafe { unsafe {
// Build the root node. // Build the root node.
@ -247,7 +243,7 @@ pub fn parse_html(url: Url,
// consists of processing inline stylesheets, but in the future it might perform // consists of processing inline stylesheets, but in the future it might perform
// prefetching, etc. // prefetching, etc.
let css_chan2 = css_chan.clone(); let css_chan2 = css_chan.clone();
let append_hook: @fn(AbstractNode, AbstractNode) = |parent_node, child_node| { let append_hook: ~fn(AbstractNode, AbstractNode) = |parent_node, child_node| {
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
@ -261,7 +257,7 @@ pub fn parse_html(url: Url,
}; };
let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone()); let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
parser.set_tree_handler(@hubbub::TreeHandler { parser.set_tree_handler(~hubbub::TreeHandler {
create_comment: |data: ~str| { create_comment: |data: ~str| {
debug!("create comment"); debug!("create comment");
unsafe { unsafe {
@ -310,7 +306,7 @@ pub fn parse_html(url: Url,
(Some(rel), Some(href)) => { (Some(rel), Some(href)) => {
if rel == ~"stylesheet" { if rel == ~"stylesheet" {
debug!("found CSS stylesheet: %s", href); debug!("found CSS stylesheet: %s", href);
let url = make_url(href.to_str(), Some(copy *url)); let url = make_url(href.to_str(), Some(url2.clone()));
css_chan2.send(CSSTaskNewFile(UrlProvenance(url))); css_chan2.send(CSSTaskNewFile(UrlProvenance(url)));
} }
} }
@ -324,7 +320,7 @@ pub fn parse_html(url: Url,
match src_opt { match src_opt {
None => {} None => {}
Some(src) => { Some(src) => {
let img_url = make_url(src, Some(copy *url)); let img_url = make_url(src, Some(url2.clone()));
image_element.image = Some(copy img_url); image_element.image = Some(copy img_url);
// inform the image cache to load this, but don't store a handle. // inform the image cache to load this, but don't store a handle.
// TODO (Issue #84): don't prefetch if we are within a <noscript> // TODO (Issue #84): don't prefetch if we are within a <noscript>
@ -368,7 +364,7 @@ pub fn parse_html(url: Url,
debug!("remove child"); debug!("remove child");
0u 0u
}, },
clone_node: |node, deep| { clone_node: |_node, deep| {
debug!("clone node"); debug!("clone node");
unsafe { unsafe {
if deep { error!("-- deep clone unimplemented"); } if deep { error!("-- deep clone unimplemented"); }
@ -403,7 +399,7 @@ pub fn parse_html(url: Url,
// A little function for holding this lint attr // A little function for holding this lint attr
#[allow(non_implicitly_copyable_typarams)] #[allow(non_implicitly_copyable_typarams)]
fn complete_script(script: hubbub::NodeDataPtr, fn complete_script(script: hubbub::NodeDataPtr,
url: &Url, url: Url,
js_chan: SharedChan<JSMessage>) { js_chan: SharedChan<JSMessage>) {
unsafe { unsafe {
let script: AbstractNode = NodeWrapping::from_hubbub_node(script); let script: AbstractNode = NodeWrapping::from_hubbub_node(script);
@ -411,7 +407,7 @@ pub fn parse_html(url: Url,
match script.get_attr(~"src") { match script.get_attr(~"src") {
Some(src) => { Some(src) => {
debug!("found script: %s", src); debug!("found script: %s", src);
let new_url = make_url(src.to_str(), Some(copy *url)); let new_url = make_url(src.to_str(), Some(url.clone()));
js_chan.send(JSTaskNewFile(new_url)); js_chan.send(JSTaskNewFile(new_url));
} }
None => {} None => {}
@ -419,14 +415,14 @@ pub fn parse_html(url: Url,
} }
} }
} }
complete_script(script, url, js_chan2.clone()); complete_script(script, url3.clone(), js_chan2.clone());
debug!("complete script"); debug!("complete script");
} }
}); });
debug!("set tree handler"); debug!("set tree handler");
let (input_port, input_chan) = comm::stream(); let (input_port, input_chan) = comm::stream();
resource_task.send(Load(copy *url, input_chan)); resource_task.send(Load(url.clone(), input_chan));
debug!("loaded page"); debug!("loaded page");
loop { loop {
match input_port.recv() { match input_port.recv() {

View file

@ -1,18 +1,16 @@
// Block layout. // Block layout.
use core::cell::Cell;
use layout::box::{RenderBox}; use layout::box::{RenderBox};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods}; use layout::display_list_builder::{DisplayListBuilder, FlowDisplayListBuilderMethods};
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow};
use layout::inline::InlineLayout; use layout::inline::InlineLayout;
use newcss::values::*;
use util::tree;
use au = gfx::geometry; use au = gfx::geometry;
use core::mutable::Mut;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::geometry::Au; use gfx::geometry::Au;
@ -27,8 +25,8 @@ pub fn BlockFlowData() -> BlockFlowData {
} }
pub trait BlockLayout { pub trait BlockLayout {
pure fn starts_block_flow() -> bool; fn starts_block_flow(&self) -> bool;
pure fn with_block_box(@mut self, &fn(box: &@mut RenderBox) -> ()) -> (); fn with_block_box(@mut self, &fn(box: &@mut RenderBox) -> ()) -> ();
fn bubble_widths_block(@mut self, ctx: &LayoutContext); fn bubble_widths_block(@mut self, ctx: &LayoutContext);
fn assign_widths_block(@mut self, ctx: &LayoutContext); fn assign_widths_block(@mut self, ctx: &LayoutContext);
@ -37,12 +35,12 @@ pub trait BlockLayout {
a: &DisplayListBuilder, a: &DisplayListBuilder,
b: &Rect<Au>, b: &Rect<Au>,
c: &Point2D<Au>, c: &Point2D<Au>,
d: &Mut<DisplayList>); d: &Cell<DisplayList>);
} }
impl BlockLayout for FlowContext { impl BlockLayout for FlowContext {
pure fn starts_block_flow() -> bool { fn starts_block_flow(&self) -> bool {
match self { match *self {
RootFlow(*) | BlockFlow(*) | InlineBlockFlow(*) => true, RootFlow(*) | BlockFlow(*) | InlineBlockFlow(*) => true,
_ => false _ => false
} }
@ -50,7 +48,7 @@ impl BlockLayout for FlowContext {
/* Get the current flow's corresponding block box, if it exists, and do something with it. /* Get the current flow's corresponding block box, if it exists, and do something with it.
This works on both BlockFlow and RootFlow, since they are mostly the same. */ This works on both BlockFlow and RootFlow, since they are mostly the same. */
pure fn with_block_box(@mut self, cb: &fn(box: &@mut RenderBox) -> ()) -> () { fn with_block_box(@mut self, cb: &fn(box: &@mut RenderBox) -> ()) -> () {
match *self { match *self {
BlockFlow(*) => { BlockFlow(*) => {
let box = self.block().box; let box = self.block().box;
@ -74,14 +72,14 @@ impl BlockLayout for FlowContext {
/* TODO: absolute contexts */ /* TODO: absolute contexts */
/* TODO: inline-blocks */ /* TODO: inline-blocks */
fn bubble_widths_block(@mut self, ctx: &LayoutContext) { fn bubble_widths_block(@mut self, ctx: &LayoutContext) {
fail_unless!(self.starts_block_flow()); assert!(self.starts_block_flow());
let mut min_width = Au(0); let mut min_width = Au(0);
let mut pref_width = Au(0); let mut pref_width = Au(0);
/* find max width from child block contexts */ /* find max width from child block contexts */
for FlowTree.each_child(self) |child_ctx| { for FlowTree.each_child(self) |child_ctx| {
fail_unless!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow()); assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
min_width = au::max(min_width, child_ctx.d().min_width); min_width = au::max(min_width, child_ctx.d().min_width);
pref_width = au::max(pref_width, child_ctx.d().pref_width); pref_width = au::max(pref_width, child_ctx.d().pref_width);
@ -106,7 +104,7 @@ impl BlockLayout for FlowContext {
all child (block) contexts. */ all child (block) contexts. */
fn assign_widths_block(@mut self, _ctx: &LayoutContext) { fn assign_widths_block(@mut self, _ctx: &LayoutContext) {
fail_unless!(self.starts_block_flow()); assert!(self.starts_block_flow());
let mut remaining_width = self.d().position.size.width; let mut remaining_width = self.d().position.size.width;
let mut _right_used = Au(0); let mut _right_used = Au(0);
@ -121,14 +119,14 @@ impl BlockLayout for FlowContext {
} }
for FlowTree.each_child(self) |child_ctx| { for FlowTree.each_child(self) |child_ctx| {
fail_unless!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow()); assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
child_ctx.d().position.origin.x = left_used; child_ctx.d().position.origin.x = left_used;
child_ctx.d().position.size.width = remaining_width; child_ctx.d().position.size.width = remaining_width;
} }
} }
fn assign_height_block(@mut self, _ctx: &LayoutContext) { fn assign_height_block(@mut self, _ctx: &LayoutContext) {
fail_unless!(self.starts_block_flow()); assert!(self.starts_block_flow());
let mut cur_y = Au(0); let mut cur_y = Au(0);
@ -150,9 +148,9 @@ impl BlockLayout for FlowContext {
} }
fn build_display_list_block(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_block(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Mut<DisplayList>) { offset: &Point2D<Au>, list: &Cell<DisplayList>) {
fail_unless!(self.starts_block_flow()); assert!(self.starts_block_flow());
// add box that starts block context // add box that starts block context
do self.with_block_box |box| { do self.with_block_box |box| {

View file

@ -8,33 +8,24 @@ use layout::display_list_builder::DisplayListBuilder;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use layout; use layout;
use newcss::color::{Color, rgba, rgb}; use newcss::color::{Color, rgb};
use newcss::complete::CompleteStyle; use newcss::complete::CompleteStyle;
use newcss::units::{BoxSizing, Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif}; use newcss::units::{Cursive, Em, Fantasy, Length, Monospace, Pt, Px, SansSerif, Serif};
use newcss::values::{CSSBackgroundColorColor, CSSBackgroundColorTransparent, CSSBorderColor}; use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSBorderWidthLength, CSSBorderWidthMedium, CSSDisplay}; use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily};
use newcss::values::{CSSFontFamilyFamilyName, CSSFontFamilyGenericFamily, CSSPositionAbsolute};
use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal}; use newcss::values::{CSSFontSizeLength, CSSFontStyleItalic, CSSFontStyleNormal};
use newcss::values::{CSSFontStyleOblique, CSSTextAlign, Specified}; use newcss::values::{CSSFontStyleOblique, CSSTextAlign};
use util::tree::ReadMethods;
use core::managed; use core::managed;
use core::mutable::Mut; use core::cell::Cell;
use core::rand;
use core::task::spawn;
use core::to_str::ToStr;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx::display_list::{DisplayItem, DisplayList}; use gfx::display_list::{DisplayItem, DisplayList};
use gfx::font::{FontStyle, FontWeight300}; use gfx::font::{FontStyle, FontWeight300};
use gfx::geometry::Au; use gfx::geometry::Au;
use gfx::image::base::Image;
use gfx::image::holder::ImageHolder; use gfx::image::holder::ImageHolder;
use gfx::text::text_run::TextRun;
use gfx::util::range::*; use gfx::util::range::*;
use gfx; use gfx;
use std::arc::ARC;
use std::arc; use std::arc;
use std::net::url::Url;
/** /**
Render boxes (`struct RenderBox`) are the leafs of the layout Render boxes (`struct RenderBox`) are the leafs of the layout
@ -118,8 +109,8 @@ pub fn RenderBoxData(node: AbstractNode, ctx: @mut FlowContext, id: int) -> Rend
} }
} }
impl RenderBox { impl RenderBox {
pure fn d(&mut self) -> &self/mut RenderBoxData { fn d(&mut self) -> &'self mut RenderBoxData {
unsafe { unsafe {
//Rust #5074 - we can't take mutable references to the //Rust #5074 - we can't take mutable references to the
// data that needs to be returned right now. // data that needs to be returned right now.
@ -132,35 +123,35 @@ impl RenderBox {
} }
} }
pure fn is_replaced(self) -> bool { fn is_replaced(self) -> bool {
match self { match self {
ImageBox(*) => true, // TODO: form elements, etc ImageBox(*) => true, // TODO: form elements, etc
_ => false _ => false
} }
} }
pure fn can_split() -> bool { fn can_split(&self) -> bool {
match self { match *self {
TextBox(*) => true, TextBox(*) => true,
_ => false _ => false
} }
} }
pure fn is_whitespace_only() -> bool { fn is_whitespace_only(&self) -> bool {
match &self { match *self {
&UnscannedTextBox(_, ref raw_text) => raw_text.is_whitespace(), UnscannedTextBox(_, ref raw_text) => raw_text.is_whitespace(),
_ => false _ => false
} }
} }
fn can_merge_with_box(@mut self, other: @mut RenderBox) -> bool { fn can_merge_with_box(@mut self, other: @mut RenderBox) -> bool {
fail_unless!(!managed::mut_ptr_eq(self, other)); assert!(!managed::mut_ptr_eq(self, other));
match (self, other) { match (self, other) {
(@UnscannedTextBox(*), @UnscannedTextBox(*)) => { (@UnscannedTextBox(*), @UnscannedTextBox(*)) => {
self.font_style() == other.font_style() self.font_style() == other.font_style()
}, },
(@TextBox(_, ref d1), @TextBox(_, ref d2)) => managed::ptr_eq(d1.run, d2.run), (@TextBox(_, d1), @TextBox(_, d2)) => managed::ptr_eq(d1.run, d2.run),
(_, _) => false (_, _) => false
} }
} }
@ -178,7 +169,7 @@ impl RenderBox {
let mut right_range : Option<Range> = None; let mut right_range : Option<Range> = None;
debug!("split_to_width: splitting text box (strlen=%u, range=%?, avail_width=%?)", debug!("split_to_width: splitting text box (strlen=%u, range=%?, avail_width=%?)",
data.run.text.len(), data.range, max_width); data.run.text.len(), data.range, max_width);
do data.run.iter_indivisible_pieces_for_range(&const data.range) |piece_range| { do data.run.iter_indivisible_pieces_for_range(&data.range) |piece_range| {
debug!("split_to_width: considering piece (range=%?, remain_width=%?)", debug!("split_to_width: considering piece (range=%?, remain_width=%?)",
piece_range, remaining_width); piece_range, remaining_width);
let metrics = data.run.metrics_for_range(piece_range); let metrics = data.run.metrics_for_range(piece_range);
@ -221,10 +212,10 @@ impl RenderBox {
} }
let left_box = if left_range.length() > 0 { let left_box = if left_range.length() > 0 {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, &const left_range)) Some(layout::text::adapt_textbox_with_range(self.d(), data.run, &left_range))
} else { None }; } else { None };
let right_box = option::map_default(&right_range, None, |range: &const Range| { let right_box = right_range.map_default(None, |range: &Range| {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, range)) Some(layout::text::adapt_textbox_with_range(self.d(), data.run, range))
}); });
@ -252,7 +243,7 @@ impl RenderBox {
// TODO: consult CSS 'width', margin, border. // TODO: consult CSS 'width', margin, border.
// TODO: If image isn't available, consult 'width'. // TODO: If image isn't available, consult 'width'.
ImageBox(_, ref mut i) => Au::from_px(i.get_size().get_or_default(Size2D(0,0)).width), ImageBox(_, ref mut i) => Au::from_px(i.get_size().get_or_default(Size2D(0,0)).width),
TextBox(_,d) => d.run.min_width_for_range(&const d.range), TextBox(_,d) => d.run.min_width_for_range(&d.range),
UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here.") UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here.")
} }
} }
@ -275,7 +266,7 @@ impl RenderBox {
// factor in min/pref widths of any text runs that it owns. // factor in min/pref widths of any text runs that it owns.
&TextBox(_,d) => { &TextBox(_,d) => {
let mut max_line_width: Au = Au(0); let mut max_line_width: Au = Au(0);
for d.run.iter_natural_lines_for_range(&const d.range) |line_range| { for d.run.iter_natural_lines_for_range(&d.range) |line_range| {
let mut line_width: Au = Au(0); let mut line_width: Au = Au(0);
for d.run.glyphs.iter_glyphs_for_char_range(line_range) |_char_i, glyph| { for d.run.glyphs.iter_glyphs_for_char_range(line_range) |_char_i, glyph| {
line_width += glyph.advance() line_width += glyph.advance()
@ -309,7 +300,7 @@ impl RenderBox {
/* The box formed by the content edge, as defined in CSS 2.1 Section 8.1. /* The box formed by the content edge, as defined in CSS 2.1 Section 8.1.
Coordinates are relative to the owning flow. */ Coordinates are relative to the owning flow. */
pure fn content_box(&mut self) -> Rect<Au> { fn content_box(&mut self) -> Rect<Au> {
let origin = {copy self.d().position.origin}; let origin = {copy self.d().position.origin};
match self { match self {
&ImageBox(_, ref mut i) => { &ImageBox(_, ref mut i) => {
@ -344,20 +335,20 @@ impl RenderBox {
/* The box formed by the border edge, as defined in CSS 2.1 Section 8.1. /* The box formed by the border edge, as defined in CSS 2.1 Section 8.1.
Coordinates are relative to the owning flow. */ Coordinates are relative to the owning flow. */
pure fn border_box(&mut self) -> Rect<Au> { fn border_box(&mut self) -> Rect<Au> {
// TODO: actually compute content_box + padding + border // TODO: actually compute content_box + padding + border
self.content_box() self.content_box()
} }
/* The box fromed by the margin edge, as defined in CSS 2.1 Section 8.1. /* The box fromed by the margin edge, as defined in CSS 2.1 Section 8.1.
Coordinates are relative to the owning flow. */ Coordinates are relative to the owning flow. */
pure fn margin_box(&mut self) -> Rect<Au> { fn margin_box(&mut self) -> Rect<Au> {
// TODO: actually compute content_box + padding + border + margin // TODO: actually compute content_box + padding + border + margin
self.content_box() self.content_box()
} }
fn style(&mut self) -> CompleteStyle/&self { fn style(&mut self) -> CompleteStyle<'self> {
let d: &self/mut RenderBoxData = self.d(); let d: &'self mut RenderBoxData = self.d();
d.node.style() d.node.style()
} }
@ -388,7 +379,7 @@ impl RenderBox {
* `list` - List to which items should be appended * `list` - List to which items should be appended
*/ */
fn build_display_list(@mut self, _builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list(@mut self, _builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Mut<DisplayList>) { offset: &Point2D<Au>, list: &Cell<DisplayList>) {
let box_bounds = self.d().position; let box_bounds = self.d().position;
@ -409,30 +400,32 @@ impl RenderBox {
match m { match m {
&UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here."), &UnscannedTextBox(*) => fail!(~"Shouldn't see unscanned boxes here."),
&TextBox(_,data) => { &TextBox(_,data) => {
do list.borrow_mut |list| { let nearest_ancestor_element = self.nearest_ancestor_element();
let nearest_ancestor_element = self.nearest_ancestor_element(); let color = nearest_ancestor_element.style().color().to_gfx_color();
let color = nearest_ancestor_element.style().color().to_gfx_color(); let mut l = list.take(); // FIXME: this should use with_mut_ref when that appears
list.append_item(~DisplayItem::new_Text(&abs_box_bounds, l.append_item(~DisplayItem::new_Text(&abs_box_bounds,
~data.run.serialize(), ~data.run.serialize(),
data.range, data.range,
color)); color));
// debug frames for text box bounds
debug!("%?", { // debug frames for text box bounds
// text box bounds debug!("%?", {
list.append_item(~DisplayItem::new_Border(&abs_box_bounds, // text box bounds
Au::from_px(1), let mut l = list.take(); // FIXME: use with_mut_ref when that appears
rgb(0, 0, 200).to_gfx_color())); l.append_item(~DisplayItem::new_Border(&abs_box_bounds,
// baseline "rect" Au::from_px(1),
// TODO(Issue #221): create and use a Line display item for baseline. rgb(0, 0, 200).to_gfx_color()));
let ascent = data.run.metrics_for_range(&data.range).ascent; // baseline "rect"
let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent), // TODO(Issue #221): create and use a Line display item for baseline.
Size2D(abs_box_bounds.size.width, Au(0))); let ascent = data.run.metrics_for_range(&data.range).ascent;
let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent),
list.append_item(~DisplayItem::new_Border(&baseline, Size2D(abs_box_bounds.size.width, Au(0)));
Au::from_px(1),
rgb(0, 200, 0).to_gfx_color())); l.append_item(~DisplayItem::new_Border(&baseline,
; ()}); Au::from_px(1),
} rgb(0, 200, 0).to_gfx_color()));
list.put_back(l);
; ()});
}, },
// TODO: items for background, border, outline // TODO: items for background, border, outline
&GenericBox(_) => {} &GenericBox(_) => {}
@ -440,11 +433,11 @@ impl RenderBox {
//let i: &mut ImageHolder = unsafe { cast::transmute(i) }; // Rust #5074 //let i: &mut ImageHolder = unsafe { cast::transmute(i) }; // Rust #5074
match i.get_image() { match i.get_image() {
Some(image) => { Some(image) => {
do list.borrow_mut |list| { debug!("(building display list) building image box");
debug!("(building display list) building image box"); let mut l = list.take(); // FIXME: use with_mut_ref when available
list.append_item(~DisplayItem::new_Image(&abs_box_bounds, l.append_item(~DisplayItem::new_Image(&abs_box_bounds,
arc::clone(&image))); arc::clone(&image)));
} list.put_back(l);
} }
None => { None => {
/* No image data at all? Okay, add some fallback content instead. */ /* No image data at all? Okay, add some fallback content instead. */
@ -457,7 +450,7 @@ impl RenderBox {
self.add_border_to_list(list, &abs_box_bounds); self.add_border_to_list(list, &abs_box_bounds);
} }
fn add_bgcolor_to_list(&mut self, list: &Mut<DisplayList>, abs_bounds: &Rect<Au>) { fn add_bgcolor_to_list(&mut self, list: &Cell<DisplayList>, abs_bounds: &Rect<Au>) {
use std::cmp::FuzzyEq; use std::cmp::FuzzyEq;
// FIXME: This causes a lot of background colors to be displayed when they are clearly not // FIXME: This causes a lot of background colors to be displayed when they are clearly not
@ -468,13 +461,13 @@ impl RenderBox {
let bgcolor = nearest_ancestor_element.style().background_color(); let bgcolor = nearest_ancestor_element.style().background_color();
if !bgcolor.alpha.fuzzy_eq(&0.0) { if !bgcolor.alpha.fuzzy_eq(&0.0) {
do list.borrow_mut |list| { let mut l = list.take(); // FIXME: use with_mut_ref when available
list.append_item(~DisplayItem::new_SolidColor(abs_bounds, bgcolor.to_gfx_color())); l.append_item(~DisplayItem::new_SolidColor(abs_bounds, bgcolor.to_gfx_color()));
} list.put_back(l);
} }
} }
fn add_border_to_list(&mut self, list: &Mut<DisplayList>, abs_bounds: &Rect<Au>) { fn add_border_to_list(&mut self, list: &Cell<DisplayList>, abs_bounds: &Rect<Au>) {
if !self.d().node.is_element() { return } if !self.d().node.is_element() { return }
let top_width = self.style().border_top_width(); let top_width = self.style().border_top_width();
@ -509,10 +502,9 @@ impl RenderBox {
let top_color = self.style().border_top_color(); let top_color = self.style().border_top_color();
let color = top_color.to_gfx_color(); // FIXME let color = top_color.to_gfx_color(); // FIXME
do list.borrow_mut |list| { let mut l = list.take(); // FIXME: use with_mut_ref when available
list.append_item(~DisplayItem::new_Border(&bounds, border_width, color)); l.append_item(~DisplayItem::new_Border(&bounds, border_width, color));
} list.put_back(l);
} else { } else {
warn!("ignoring unimplemented border widths"); warn!("ignoring unimplemented border widths");
} }
@ -578,12 +570,12 @@ impl RenderBox {
} }
impl BoxedMutDebugMethods for RenderBox { impl BoxedMutDebugMethods for RenderBox {
pure fn dump(@mut self) { fn dump(@mut self) {
self.dump_indent(0u); self.dump_indent(0u);
} }
/* Dumps the node tree, for debugging, with indentation. */ /* Dumps the node tree, for debugging, with indentation. */
pure fn dump_indent(@mut self, indent: uint) { fn dump_indent(@mut self, indent: uint) {
let mut s = ~""; let mut s = ~"";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~" "; s += ~" ";
@ -593,15 +585,21 @@ impl BoxedMutDebugMethods for RenderBox {
debug!("%s", s); debug!("%s", s);
} }
pure fn debug_str(@mut self) -> ~str { fn debug_str(@mut self) -> ~str {
let repr = match self { let borrowed_self : &mut RenderBox = self; // FIXME: borrow checker workaround
@GenericBox(*) => ~"GenericBox", let repr = match borrowed_self {
@ImageBox(*) => ~"ImageBox", &GenericBox(*) => ~"GenericBox",
@TextBox(_,d) => fmt!("TextBox(text=%s)", str::substr(d.run.text, d.range.begin(), d.range.length())), &ImageBox(*) => ~"ImageBox",
@UnscannedTextBox(_, ref s) => fmt!("UnscannedTextBox(%s)", *s) &TextBox(_,d) => fmt!("TextBox(text=%s)", str::substr(d.run.text, d.range.begin(), d.range.length())),
&UnscannedTextBox(_, ref s) => {
let s = s;
fmt!("UnscannedTextBox(%s)", *s)
}
}; };
fmt!("box b%?: %?", self.d().id, repr) let borrowed_self : &mut RenderBox = self; // FIXME: borrow checker workaround
let id = borrowed_self.d().id;
fmt!("box b%?: %?", id, repr)
} }
} }

View file

@ -1,9 +1,8 @@
/** Creates CSS boxes from a DOM. */ /** Creates CSS boxes from a DOM. */
use dom::element::*; use dom::element::*;
use dom::node::{AbstractNode, Comment, CommentNodeTypeId, Doctype, DoctypeNodeTypeId, Element}; use dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
use dom::node::{ElementNodeTypeId, Node, Text, TextNodeTypeId}; use dom::node::{ElementNodeTypeId, TextNodeTypeId};
use dom;
use layout::block::BlockFlowData; use layout::block::BlockFlowData;
use layout::box::*; use layout::box::*;
use layout::context::LayoutContext; use layout::context::LayoutContext;
@ -16,7 +15,7 @@ use util::tree;
use gfx::image::holder::ImageHolder; use gfx::image::holder::ImageHolder;
use gfx::util::range::Range; use gfx::util::range::Range;
use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock}; use newcss::values::{CSSDisplay, CSSDisplayBlock, CSSDisplayInline, CSSDisplayInlineBlock};
use newcss::values::{CSSDisplayNone, Inherit, Specified}; use newcss::values::{CSSDisplayNone};
pub struct LayoutTreeBuilder { pub struct LayoutTreeBuilder {
root_flow: Option<@mut FlowContext>, root_flow: Option<@mut FlowContext>,
@ -25,7 +24,7 @@ pub struct LayoutTreeBuilder {
} }
pub impl LayoutTreeBuilder { pub impl LayoutTreeBuilder {
static pure fn new() -> LayoutTreeBuilder { fn new() -> LayoutTreeBuilder {
LayoutTreeBuilder { LayoutTreeBuilder {
root_flow: None, root_flow: None,
next_bid: -1, next_bid: -1,
@ -79,7 +78,7 @@ priv fn simulate_UA_display_rules(node: AbstractNode) -> CSSDisplay {
} }
impl BoxGenerator { impl BoxGenerator {
static pure fn new(flow: @mut FlowContext) -> BoxGenerator { fn new(flow: @mut FlowContext) -> BoxGenerator {
unsafe { debug!("Creating box generator for flow: %s", flow.debug_str()); } unsafe { debug!("Creating box generator for flow: %s", flow.debug_str()); }
BoxGenerator { BoxGenerator {
flow: flow, flow: flow,
@ -88,7 +87,7 @@ impl BoxGenerator {
} }
/* Whether "spacer" boxes are needed to stand in for this DOM node */ /* Whether "spacer" boxes are needed to stand in for this DOM node */
pure fn inline_spacers_needed_for_node(&self, _: AbstractNode) -> bool { fn inline_spacers_needed_for_node(&self, _: AbstractNode) -> bool {
return false; return false;
} }
@ -115,7 +114,10 @@ impl BoxGenerator {
match self.flow { match self.flow {
@InlineFlow(*) => { @InlineFlow(*) => {
let node_range_start = match self.flow { let node_range_start = match self.flow {
@InlineFlow(*) => self.flow.inline().boxes.len(), @InlineFlow(*) => {
let inline_flow = self.flow.inline();
inline_flow.boxes.len()
}
_ => 0 _ => 0
}; };
self.range_stack.push(node_range_start); self.range_stack.push(node_range_start);
@ -141,7 +143,7 @@ impl BoxGenerator {
debug!("BoxGenerator[f%d]: attaching box[b%d] to block flow (node: %s)", debug!("BoxGenerator[f%d]: attaching box[b%d] to block flow (node: %s)",
self.flow.d().id, new_box.d().id, node.debug_str()); self.flow.d().id, new_box.d().id, node.debug_str());
fail_unless!(self.flow.block().box.is_none()); assert!(self.flow.block().box.is_none());
//XXXjdm We segfault when returning without this temporary. //XXXjdm We segfault when returning without this temporary.
let block = self.flow.block(); let block = self.flow.block();
block.box = Some(new_box); block.box = Some(new_box);
@ -153,7 +155,7 @@ impl BoxGenerator {
debug!("BoxGenerator[f%d]: attaching box[b%d] to root flow (node: %s)", debug!("BoxGenerator[f%d]: attaching box[b%d] to root flow (node: %s)",
self.flow.d().id, new_box.d().id, node.debug_str()); self.flow.d().id, new_box.d().id, node.debug_str());
fail_unless!(self.flow.root().box.is_none()); assert!(self.flow.root().box.is_none());
//XXXjdm We segfault when returning without this temporary. //XXXjdm We segfault when returning without this temporary.
let root = self.flow.root(); let root = self.flow.root();
root.box = Some(new_box); root.box = Some(new_box);
@ -176,17 +178,21 @@ impl BoxGenerator {
} }
} }
let mut node_range: Range = Range::new(self.range_stack.pop(), 0); let mut node_range: Range = Range::new(self.range_stack.pop(), 0);
node_range.extend_to(self.flow.inline().boxes.len()); let inline_flow = self.flow.inline(); // FIXME: borrow checker workaround
fail_unless!(node_range.length() > 0); node_range.extend_to(inline_flow.boxes.len());
assert!(node_range.length() > 0);
debug!("BoxGenerator: adding element range=%?", node_range); debug!("BoxGenerator: adding element range=%?", node_range);
let elems = &mut self.flow.inline().elems; let elems = &mut inline_flow.elems;
elems.add_mapping(node, &const node_range); elems.add_mapping(node, &node_range);
}, },
@BlockFlow(*) | @RootFlow(*) => { @BlockFlow(*) | @RootFlow(*) => {
fail_unless!(self.range_stack.len() == 0); assert!(self.range_stack.len() == 0);
}, },
_ => { warn!("pop_node() not implemented for flow %?", self.flow.d().id) } _ => {
let d = self.flow.d(); // FIXME: borrow checker workaround
warn!("pop_node() not implemented for flow %?", d.id)
}
} }
} }
} }
@ -197,7 +203,7 @@ struct BuilderContext {
} }
impl BuilderContext { impl BuilderContext {
static pure fn new(collector: @mut BoxGenerator) -> BuilderContext { fn new(collector: @mut BoxGenerator) -> BuilderContext {
unsafe { debug!("Creating new BuilderContext for flow: %s", collector.flow.debug_str()); } unsafe { debug!("Creating new BuilderContext for flow: %s", collector.flow.debug_str()); }
BuilderContext { BuilderContext {
default_collector: collector, default_collector: collector,
@ -211,8 +217,10 @@ impl BuilderContext {
} }
priv fn attach_child_flow(&self, child: @mut FlowContext) { priv fn attach_child_flow(&self, child: @mut FlowContext) {
let d = self.default_collector.flow.d(); // FIXME: borrow checker workaround
let cd = child.d(); // FIXME: borrow checker workaround
debug!("BuilderContext: Adding child flow f%? of f%?", debug!("BuilderContext: Adding child flow f%? of f%?",
self.default_collector.flow.d().id, child.d().id); d.id, cd.id);
tree::add_child(&FlowTree, self.default_collector.flow, child); tree::add_child(&FlowTree, self.default_collector.flow, child);
} }
@ -321,7 +329,7 @@ pub impl LayoutTreeBuilder {
let flow = &mut this_ctx.default_collector.flow; let flow = &mut this_ctx.default_collector.flow;
for tree::each_child(&FlowTree, flow) |child_flow: &@mut FlowContext| { for tree::each_child(&FlowTree, flow) |child_flow: &@mut FlowContext| {
for (copy child_flow.d().node).each |node| { for (copy child_flow.d().node).each |node| {
fail_unless!(node.has_layout_data()); assert!(node.has_layout_data());
node.layout_data().flow = Some(*child_flow); node.layout_data().flow = Some(*child_flow);
} }
} }
@ -482,7 +490,7 @@ pub impl LayoutTreeBuilder {
} }
} }
fn decide_box_type(&self, node: AbstractNode, display: CSSDisplay) -> RenderBoxType { fn decide_box_type(&self, node: AbstractNode, _display: CSSDisplay) -> RenderBoxType {
if node.is_text() { if node.is_text() {
RenderBox_Text RenderBox_Text
} else if node.is_image_element() { } else if node.is_image_element() {

View file

@ -1,17 +1,17 @@
pub trait BoxedMutDebugMethods { pub trait BoxedMutDebugMethods {
pure fn dump(@mut self); fn dump(@mut self);
pure fn dump_indent(@mut self, ident: uint); fn dump_indent(@mut self, ident: uint);
pure fn debug_str(@mut self) -> ~str; fn debug_str(@mut self) -> ~str;
} }
pub trait BoxedDebugMethods { pub trait BoxedDebugMethods {
pure fn dump(@self); fn dump(@self);
pure fn dump_indent(@self, ident: uint); fn dump_indent(@self, ident: uint);
pure fn debug_str(@self) -> ~str; fn debug_str(@self) -> ~str;
} }
pub trait DebugMethods { pub trait DebugMethods {
pure fn dump(&self); fn dump(&self);
pure fn dump_indent(&self, ident: uint); fn dump_indent(&self, ident: uint);
pure fn debug_str(&self) -> ~str; fn debug_str(&self) -> ~str;
} }

View file

@ -2,20 +2,13 @@
/// Constructs display lists from render boxes. /// Constructs display lists from render boxes.
/// ///
use layout::box::{RenderBox, TextBox}; use core::cell::Cell;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use layout::text::TextBoxData;
use newcss::values::Specified;
use newcss::values::{CSSBackgroundColorColor, CSSBackgroundColorTransparent};
use util::tree;
use core::either::{Left, Right};
use core::mutable::Mut;
use core::vec::push;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::geometry::Au; use gfx::geometry::Au;
use gfx; use gfx;
@ -27,25 +20,25 @@ use gfx;
Right now, the builder isn't used for much, but it establishes the Right now, the builder isn't used for much, but it establishes the
pattern we'll need once we support DL-based hit testing &c. */ pattern we'll need once we support DL-based hit testing &c. */
pub struct DisplayListBuilder { pub struct DisplayListBuilder<'self> {
ctx: &'self LayoutContext, ctx: &'self LayoutContext,
} }
pub trait FlowDisplayListBuilderMethods { pub trait FlowDisplayListBuilderMethods {
fn build_display_list(@mut self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Mut<DisplayList>); fn build_display_list(@mut self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Cell<DisplayList>);
fn build_display_list_for_child(@mut self, fn build_display_list_for_child(@mut self,
a: &DisplayListBuilder, a: &DisplayListBuilder,
b: @mut FlowContext, b: @mut FlowContext,
c: &Rect<Au>, c: &Rect<Au>,
d: &Point2D<Au>, d: &Point2D<Au>,
e: &Mut<DisplayList>); e: &Cell<DisplayList>);
} }
impl FlowDisplayListBuilderMethods for FlowContext { impl FlowDisplayListBuilderMethods for FlowContext {
fn build_display_list(@mut self, fn build_display_list(@mut self,
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
dirty: &Rect<Au>, dirty: &Rect<Au>,
list: &Mut<DisplayList>) { list: &Cell<DisplayList>) {
let zero = gfx::geometry::zero_point(); let zero = gfx::geometry::zero_point();
self.build_display_list_recurse(builder, dirty, &zero, list); self.build_display_list_recurse(builder, dirty, &zero, list);
} }
@ -54,14 +47,15 @@ impl FlowDisplayListBuilderMethods for FlowContext {
builder: &DisplayListBuilder, builder: &DisplayListBuilder,
child_flow: @mut FlowContext, child_flow: @mut FlowContext,
dirty: &Rect<Au>, offset: &Point2D<Au>, dirty: &Rect<Au>, offset: &Point2D<Au>,
list: &Mut<DisplayList>) { list: &Cell<DisplayList>) {
// adjust the dirty rect to child flow context coordinates // adjust the dirty rect to child flow context coordinates
let abs_flow_bounds = child_flow.d().position.translate(offset); let d = child_flow.d(); // FIXME: borrow checker workaround
let adj_offset = offset.add(&child_flow.d().position.origin); let abs_flow_bounds = d.position.translate(offset);
let adj_offset = offset.add(&d.position.origin);
debug!("build_display_list_for_child: rel=%?, abs=%?", debug!("build_display_list_for_child: rel=%?, abs=%?",
child_flow.d().position, abs_flow_bounds); d.position, abs_flow_bounds);
debug!("build_display_list_for_child: dirty=%?, offset=%?", debug!("build_display_list_for_child: dirty=%?, offset=%?",
dirty, offset); dirty, offset);

View file

@ -1,14 +1,14 @@
use core; use core;
use core::cell::Cell;
use dom::node::AbstractNode; use dom::node::AbstractNode;
use layout::block::{BlockFlowData, BlockLayout}; use layout::block::{BlockFlowData, BlockLayout};
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::BoxedMutDebugMethods; use layout::debug::BoxedMutDebugMethods;
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use layout::inline::{InlineFlowData, InlineLayout, NodeRange}; use layout::inline::{InlineFlowData, InlineLayout};
use layout::root::{RootFlowData, RootLayout}; use layout::root::{RootFlowData, RootLayout};
use util::tree; use util::tree;
use core::mutable::Mut;
use geom::rect::Rect; use geom::rect::Rect;
use geom::point::Point2D; use geom::point::Point2D;
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
@ -92,8 +92,8 @@ pub fn FlowData(id: int) -> FlowData {
} }
} }
pub impl FlowContext { pub impl FlowContext {
pure fn d(&mut self) -> &self/mut FlowData { fn d(&mut self) -> &'self mut FlowData {
unsafe { unsafe {
match *self { match *self {
AbsoluteFlow(ref d) => cast::transmute(d), AbsoluteFlow(ref d) => cast::transmute(d),
@ -107,21 +107,21 @@ pub impl FlowContext {
} }
} }
pure fn inline(&mut self) -> &self/mut InlineFlowData { fn inline(&mut self) -> &'self mut InlineFlowData {
match self { match self {
&InlineFlow(_, ref i) => unsafe { cast::transmute(i) }, &InlineFlow(_, ref i) => unsafe { cast::transmute(i) },
_ => fail!(fmt!("Tried to access inline data of non-inline: f%d", self.d().id)) _ => fail!(fmt!("Tried to access inline data of non-inline: f%d", self.d().id))
} }
} }
pure fn block(&mut self) -> &self/mut BlockFlowData { fn block(&mut self) -> &'self mut BlockFlowData {
match self { match self {
&BlockFlow(_, ref mut b) => unsafe { cast::transmute(b) }, &BlockFlow(_, ref mut b) => unsafe { cast::transmute(b) },
_ => fail!(fmt!("Tried to access block data of non-block: f%d", self.d().id)) _ => fail!(fmt!("Tried to access block data of non-block: f%d", self.d().id))
} }
} }
pure fn root(&mut self) -> &self/mut RootFlowData { fn root(&mut self) -> &'self mut RootFlowData {
match self { match self {
&RootFlow(_, ref r) => unsafe { cast::transmute(r) }, &RootFlow(_, ref r) => unsafe { cast::transmute(r) },
_ => fail!(fmt!("Tried to access root data of non-root: f%d", self.d().id)) _ => fail!(fmt!("Tried to access root data of non-root: f%d", self.d().id))
@ -156,8 +156,9 @@ pub impl FlowContext {
} }
fn build_display_list_recurse(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_recurse(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Mut<DisplayList>) { offset: &Point2D<Au>, list: &Cell<DisplayList>) {
debug!("FlowContext::build_display_list at %?: %s", self.d().position, self.debug_str()); let d = self.d(); // FIXME: borrow checker workaround
debug!("FlowContext::build_display_list at %?: %s", d.position, self.debug_str());
match self { match self {
@RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list), @RootFlow(*) => self.build_display_list_root(builder, dirty, offset, list),
@ -168,40 +169,58 @@ pub impl FlowContext {
} }
// Actual methods that do not require much flow-specific logic // Actual methods that do not require much flow-specific logic
pure fn foldl_all_boxes<B: Copy>(&mut self, fn foldl_all_boxes<B: Copy>(&mut self,
seed: B, seed: B,
cb: &pure fn(a: B,@mut RenderBox) -> B) -> B { cb: &fn(a: B, b: @mut RenderBox) -> B) -> B {
match self { match self {
&RootFlow(*) => option::map_default(&self.root().box, seed, |box| { cb(seed, *box) }), &RootFlow(*) => {
&BlockFlow(*) => option::map_default(&self.block().box, seed, |box| { cb(seed, *box) }), let root = self.root(); // FIXME: borrow checker workaround
&InlineFlow(*) => do self.inline().boxes.foldl(seed) |acc, box| { cb(*acc, *box) }, root.box.map_default(seed, |box| { cb(seed, *box) })
}
&BlockFlow(*) => {
let block = self.block(); // FIXME: borrow checker workaround
block.box.map_default(seed, |box| { cb(seed, *box) })
}
&InlineFlow(*) => {
let inline = self.inline(); // FIXME: borrow checker workaround
inline.boxes.foldl(seed, |acc, box| { cb(*acc, *box) })
}
_ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self)) _ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
} }
} }
pure fn foldl_boxes_for_node<B: Copy>(&mut self, fn foldl_boxes_for_node<B: Copy>(&mut self,
node: AbstractNode, node: AbstractNode,
seed: B, seed: B,
cb: &pure fn(a: B,@mut RenderBox) -> B) cb: &fn(a: B,@mut RenderBox) -> B)
-> B { -> B {
do self.foldl_all_boxes(seed) |acc, box| { do self.foldl_all_boxes(seed) |acc, box| {
if box.d().node == node { cb(acc, box) } if box.d().node == node { cb(acc, box) }
else { acc } else { acc }
} }
} }
pure fn iter_all_boxes<T>(&mut self, cb: &pure fn(@mut RenderBox) -> T) { fn iter_all_boxes<T>(&mut self, cb: &fn(@mut RenderBox) -> T) {
match self { match self {
&RootFlow(*) => for self.root().box.each |box| { cb(*box); }, &RootFlow(*) => {
&BlockFlow(*) => for self.block().box.each |box| { cb(*box); }, let root = self.root(); // FIXME: borrow checker workaround
&InlineFlow(*) => for self.inline().boxes.each |box| { cb(*box); }, for root.box.each |box| { cb(*box); }
}
&BlockFlow(*) => {
let block = self.block(); // FIXME: borrow checker workaround
for block.box.each |box| { cb(*box); }
}
&InlineFlow(*) => {
let inline = self.inline(); // FIXME: borrow checker workaround
for inline.boxes.each |box| { cb(*box); }
}
_ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self)) _ => fail!(fmt!("Don't know how to iterate node's RenderBoxes for %?", self))
} }
} }
pure fn iter_boxes_for_node<T>(&mut self, fn iter_boxes_for_node<T>(&mut self,
node: AbstractNode, node: AbstractNode,
cb: &pure fn(@mut RenderBox) -> T) { cb: &fn(@mut RenderBox) -> T) {
do self.iter_all_boxes |box| { do self.iter_all_boxes |box| {
if box.d().node == node { cb(box); } if box.d().node == node { cb(box); }
} }
@ -212,13 +231,13 @@ pub impl FlowContext {
pub enum FlowTree { FlowTree } pub enum FlowTree { FlowTree }
impl FlowTree { impl FlowTree {
fn each_child(ctx: @mut FlowContext, f: &fn(box: @mut FlowContext) -> bool) { fn each_child(&self, ctx: @mut FlowContext, f: &fn(box: @mut FlowContext) -> bool) {
tree::each_child(&self, &ctx, |box| f(*box) ) tree::each_child(self, &ctx, |box| f(*box) )
} }
} }
impl tree::ReadMethods<@mut FlowContext> for FlowTree { impl tree::ReadMethods<@mut FlowContext> for FlowTree {
fn with_tree_fields<R>(box: &@mut FlowContext, f: &fn(&mut tree::Tree<@mut FlowContext>) -> R) -> R { fn with_tree_fields<R>(&self, box: &@mut FlowContext, f: &fn(&mut tree::Tree<@mut FlowContext>) -> R) -> R {
let tree = &mut box.d().tree; let tree = &mut box.d().tree;
f(tree) f(tree)
} }
@ -231,9 +250,9 @@ impl FlowTree {
} }
impl tree::WriteMethods<@mut FlowContext> for FlowTree { impl tree::WriteMethods<@mut FlowContext> for FlowTree {
pure fn tree_eq(a: &@mut FlowContext, b: &@mut FlowContext) -> bool { core::managed::mut_ptr_eq(*a, *b) } fn tree_eq(&self, a: &@mut FlowContext, b: &@mut FlowContext) -> bool { core::managed::mut_ptr_eq(*a, *b) }
fn with_tree_fields<R>(box: &@mut FlowContext, f: &fn(&mut tree::Tree<@mut FlowContext>) -> R) -> R { fn with_tree_fields<R>(&self, box: &@mut FlowContext, f: &fn(&mut tree::Tree<@mut FlowContext>) -> R) -> R {
let tree = &mut box.d().tree; let tree = &mut box.d().tree;
f(tree) f(tree)
} }
@ -241,12 +260,12 @@ impl tree::WriteMethods<@mut FlowContext> for FlowTree {
impl BoxedMutDebugMethods for FlowContext { impl BoxedMutDebugMethods for FlowContext {
pure fn dump(@mut self) { fn dump(@mut self) {
self.dump_indent(0u); self.dump_indent(0u);
} }
/** Dumps the flow tree, for debugging, with indentation. */ /** Dumps the flow tree, for debugging, with indentation. */
pure fn dump_indent(@mut self, indent: uint) { fn dump_indent(@mut self, indent: uint) {
let mut s = ~"|"; let mut s = ~"|";
for uint::range(0u, indent) |_i| { for uint::range(0u, indent) |_i| {
s += ~"---- "; s += ~"---- ";
@ -263,10 +282,11 @@ impl BoxedMutDebugMethods for FlowContext {
} }
} }
pure fn debug_str(@mut self) -> ~str { fn debug_str(@mut self) -> ~str {
let repr = match *self { let repr = match *self {
InlineFlow(*) => { InlineFlow(*) => {
let mut s = self.inline().boxes.foldl(~"InlineFlow(children=", |s, box| { let inline = self.inline(); // FIXME: borrow checker workaround
let mut s = inline.boxes.foldl(~"InlineFlow(children=", |s, box| {
fmt!("%s b%d", *s, box.d().id) fmt!("%s b%d", *s, box.d().id)
}); });
s += ~")"; s += ~")";
@ -286,7 +306,8 @@ impl BoxedMutDebugMethods for FlowContext {
}, },
_ => ~"(Unknown flow)" _ => ~"(Unknown flow)"
}; };
fmt!("f%? %?", self.d().id, repr) let d = self.d(); // FIXME: borrow checker workaround
fmt!("f%? %?", d.id, repr)
} }
} }

View file

@ -1,26 +1,22 @@
use core; use core;
use core::cell::Cell;
use dom::node::AbstractNode; use dom::node::AbstractNode;
use layout::box::*; use layout::box::*;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::{BoxedDebugMethods, BoxedMutDebugMethods, DebugMethods}; use layout::debug::{BoxedDebugMethods, BoxedMutDebugMethods, DebugMethods};
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use layout::flow::{FlowContext, InlineFlow}; use layout::flow::{FlowContext, InlineFlow};
use layout::text::{TextBoxData, UnscannedMethods, adapt_textbox_with_range}; use layout::text::{UnscannedMethods, adapt_textbox_with_range};
use util::tree;
use core::dlist::DList;
use geom::{Point2D, Rect, Size2D}; use geom::{Point2D, Rect, Size2D};
use gfx::display_list::DisplayList; use gfx::display_list::DisplayList;
use gfx::font::FontStyle;
use gfx::geometry::Au; use gfx::geometry::Au;
use gfx::image::holder; use gfx::image::holder;
use gfx::text::text_run::TextRun; use gfx::text::text_run::TextRun;
use gfx::text::util::*; use gfx::text::util::*;
use gfx::util::range::Range; use gfx::util::range::Range;
use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft, CSSTextAlignRight}; use newcss::values::{CSSTextAlignCenter, CSSTextAlignJustify, CSSTextAlignLeft, CSSTextAlignRight};
use newcss::units::{BoxAuto, BoxLength, Px}; use std::deque::Deque;
use std::arc;
use core::mutable::Mut;
use core::util; use core::util;
/* /*
@ -51,7 +47,7 @@ pub struct NodeRange {
} }
pub impl NodeRange { pub impl NodeRange {
static pure fn new(node: AbstractNode, range: &const Range) -> NodeRange { fn new(node: AbstractNode, range: &Range) -> NodeRange {
NodeRange { node: node, range: copy *range } NodeRange { node: node, range: copy *range }
} }
} }
@ -61,19 +57,19 @@ struct ElementMapping {
} }
pub impl ElementMapping { pub impl ElementMapping {
static pure fn new() -> ElementMapping { fn new() -> ElementMapping {
ElementMapping { entries: ~[] } ElementMapping { entries: ~[] }
} }
fn add_mapping(&mut self, node: AbstractNode, range: &const Range) { fn add_mapping(&mut self, node: AbstractNode, range: &Range) {
self.entries.push(NodeRange::new(node, range)) self.entries.push(NodeRange::new(node, range))
} }
fn each(&self, cb: &pure fn(nr: &NodeRange) -> bool) { fn each(&self, cb: &fn(nr: &NodeRange) -> bool) {
do self.entries.each |nr| { cb(nr) } do self.entries.each |nr| { cb(nr) }
} }
fn eachi(&self, cb: &pure fn(i: uint, nr: &NodeRange) -> bool) { fn eachi(&self, cb: &fn(i: uint, nr: &NodeRange) -> bool) {
do self.entries.eachi |i, nr| { cb(i, nr) } do self.entries.eachi |i, nr| { cb(i, nr) }
} }
@ -158,7 +154,7 @@ priv struct TextRunScanner {
} }
priv impl TextRunScanner { priv impl TextRunScanner {
static fn new() -> TextRunScanner { fn new() -> TextRunScanner {
TextRunScanner { TextRunScanner {
clump: Range::empty(), clump: Range::empty(),
} }
@ -167,7 +163,8 @@ priv impl TextRunScanner {
priv impl TextRunScanner { priv impl TextRunScanner {
fn scan_for_runs(&mut self, ctx: &mut LayoutContext, flow: @mut FlowContext) { fn scan_for_runs(&mut self, ctx: &mut LayoutContext, flow: @mut FlowContext) {
fail_unless!(flow.inline().boxes.len() > 0); let inline = flow.inline();
assert!(inline.boxes.len() > 0);
let in_boxes = &mut flow.inline().boxes; let in_boxes = &mut flow.inline().boxes;
//do boxes.swap |in_boxes| { //do boxes.swap |in_boxes| {
@ -194,9 +191,9 @@ priv impl TextRunScanner {
// helper functions // helper functions
fn can_coalesce_text_nodes(boxes: &[@mut RenderBox], left_i: uint, right_i: uint) -> bool { fn can_coalesce_text_nodes(boxes: &[@mut RenderBox], left_i: uint, right_i: uint) -> bool {
fail_unless!(left_i < boxes.len()); assert!(left_i < boxes.len());
fail_unless!(right_i > 0 && right_i < boxes.len()); assert!(right_i > 0 && right_i < boxes.len());
fail_unless!(left_i != right_i); assert!(left_i != right_i);
let (left, right) = (boxes[left_i], boxes[right_i]); let (left, right) = (boxes[left_i], boxes[right_i]);
match (left, right) { match (left, right) {
@ -223,7 +220,7 @@ priv impl TextRunScanner {
flow: @mut FlowContext, flow: @mut FlowContext,
in_boxes: &[@mut RenderBox], in_boxes: &[@mut RenderBox],
out_boxes: &mut ~[@mut RenderBox]) { out_boxes: &mut ~[@mut RenderBox]) {
fail_unless!(self.clump.length() > 0); assert!(self.clump.length() > 0);
debug!("TextRunScanner: flushing boxes in range=%?", self.clump); debug!("TextRunScanner: flushing boxes in range=%?", self.clump);
let is_singleton = self.clump.length() == 1; let is_singleton = self.clump.length() == 1;
@ -255,7 +252,7 @@ priv impl TextRunScanner {
debug!("TextRunScanner: pushing single text box in range: %?", self.clump); debug!("TextRunScanner: pushing single text box in range: %?", self.clump);
let new_box = adapt_textbox_with_range(old_box.d(), let new_box = adapt_textbox_with_range(old_box.d(),
run, run,
&const Range::new(0, run.char_len())); &Range::new(0, run.char_len()));
out_boxes.push(new_box); out_boxes.push(new_box);
}, },
(false, true) => { (false, true) => {
@ -294,7 +291,7 @@ priv impl TextRunScanner {
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump); debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
let clump = self.clump; let clump = self.clump;
for clump.eachi |i| { for clump.eachi |i| {
let range = &const new_ranges[i - self.clump.begin()]; let range = &new_ranges[i - self.clump.begin()];
if range.length() == 0 { if range.length() == 0 {
error!("Elided an UnscannedTextbox because it was zero-length after compression; %s", error!("Elided an UnscannedTextbox because it was zero-length after compression; %s",
in_boxes[i].debug_str()); in_boxes[i].debug_str());
@ -325,7 +322,8 @@ priv impl TextRunScanner {
} }
debug!("--------------------"); debug!("--------------------");
self.clump.reset(self.clump.end(), 0); let end = self.clump.end(); // FIXME: borrow checker workaround
self.clump.reset(end, 0);
} /* /fn flush_clump_to_list */ } /* /fn flush_clump_to_list */
} }
@ -337,18 +335,18 @@ struct PendingLine {
struct LineboxScanner { struct LineboxScanner {
flow: @mut FlowContext, flow: @mut FlowContext,
new_boxes: ~[@mut RenderBox], new_boxes: ~[@mut RenderBox],
work_list: @mut DList<@mut RenderBox>, work_list: @mut Deque<@mut RenderBox>,
pending_line: PendingLine, pending_line: PendingLine,
line_spans: ~[Range], line_spans: ~[Range],
} }
fn LineboxScanner(inline: @mut FlowContext) -> LineboxScanner { fn LineboxScanner(inline: @mut FlowContext) -> LineboxScanner {
fail_unless!(inline.starts_inline_flow()); assert!(inline.starts_inline_flow());
LineboxScanner { LineboxScanner {
flow: inline, flow: inline,
new_boxes: ~[], new_boxes: ~[],
work_list: DList(), work_list: @mut Deque::new(),
pending_line: PendingLine {mut range: Range::empty(), mut width: Au(0)}, pending_line: PendingLine {mut range: Range::empty(), mut width: Au(0)},
line_spans: ~[] line_spans: ~[]
} }
@ -375,17 +373,15 @@ impl LineboxScanner {
loop { loop {
// acquire the next box to lay out from work list or box list // acquire the next box to lay out from work list or box list
let cur_box = match self.work_list.pop() { let cur_box = if self.work_list.is_empty() {
Some(box) => { if i == boxes.len() { break; }
debug!("LineboxScanner: Working with box from work list: b%d", box.d().id); let box = boxes[i]; i += 1;
box debug!("LineboxScanner: Working with box from box list: b%d", box.d().id);
}, box
None => { } else {
if i == boxes.len() { break; } let box = self.work_list.pop_front();
let box = boxes[i]; i += 1; debug!("LineboxScanner: Working with box from work list: b%d", box.d().id);
debug!("LineboxScanner: Working with box from box list: b%d", box.d().id); box
box
}
}; };
let box_was_appended = self.try_append_to_line(ctx, cur_box); let box_was_appended = self.try_append_to_line(ctx, cur_box);
@ -524,7 +520,7 @@ impl LineboxScanner {
match (left, right) { match (left, right) {
(Some(left_box), Some(right_box)) => { (Some(left_box), Some(right_box)) => {
self.push_box_to_line(left_box); self.push_box_to_line(left_box);
self.work_list.push_head(right_box); self.work_list.add_front(right_box);
}, },
(Some(left_box), None) => { self.push_box_to_line(left_box); } (Some(left_box), None) => { self.push_box_to_line(left_box); }
(None, Some(right_box)) => { self.push_box_to_line(right_box); } (None, Some(right_box)) => { self.push_box_to_line(right_box); }
@ -542,7 +538,7 @@ impl LineboxScanner {
match (left, right) { match (left, right) {
(Some(left_box), Some(right_box)) => { (Some(left_box), Some(right_box)) => {
self.push_box_to_line(left_box); self.push_box_to_line(left_box);
self.work_list.push_head(right_box); self.work_list.add_front(right_box);
}, },
(Some(left_box), None) => { (Some(left_box), None) => {
self.push_box_to_line(left_box); self.push_box_to_line(left_box);
@ -557,7 +553,7 @@ impl LineboxScanner {
return true; return true;
} else { } else {
debug!("LineboxScanner: case=split box didn't fit, not appending and deferring original box."); debug!("LineboxScanner: case=split box didn't fit, not appending and deferring original box.");
self.work_list.push_head(in_box); self.work_list.add_front(in_box);
return false; return false;
} }
} }
@ -569,7 +565,7 @@ impl LineboxScanner {
debug!("LineboxScanner: Pushing box b%d to line %u", box.d().id, self.line_spans.len()); debug!("LineboxScanner: Pushing box b%d to line %u", box.d().id, self.line_spans.len());
if self.pending_line.range.length() == 0 { if self.pending_line.range.length() == 0 {
fail_unless!(self.new_boxes.len() <= (core::u16::max_value as uint)); assert!(self.new_boxes.len() <= (core::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);
@ -600,20 +596,20 @@ pub fn InlineFlowData() -> InlineFlowData {
} }
pub trait InlineLayout { pub trait InlineLayout {
pure fn starts_inline_flow() -> bool; fn starts_inline_flow(&self) -> bool;
fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext); fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext);
fn assign_widths_inline(@mut self, ctx: &mut LayoutContext); fn assign_widths_inline(@mut self, ctx: &mut LayoutContext);
fn assign_height_inline(@mut self, ctx: &mut LayoutContext); fn assign_height_inline(@mut self, ctx: &mut LayoutContext);
fn build_display_list_inline(@mut self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>, fn build_display_list_inline(@mut self, a: &DisplayListBuilder, b: &Rect<Au>, c: &Point2D<Au>,
d: &Mut<DisplayList>); d: &Cell<DisplayList>);
} }
impl InlineLayout for FlowContext { impl InlineLayout for FlowContext {
pure fn starts_inline_flow() -> bool { match self { InlineFlow(*) => true, _ => false } } fn starts_inline_flow(&self) -> bool { match *self { InlineFlow(*) => true, _ => false } }
fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) { fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) {
fail_unless!(self.starts_inline_flow()); assert!(self.starts_inline_flow());
let mut scanner = TextRunScanner::new(); let mut scanner = TextRunScanner::new();
scanner.scan_for_runs(ctx, self); scanner.scan_for_runs(ctx, self);
@ -636,7 +632,7 @@ impl InlineLayout for FlowContext {
contexts and boxes. When called on this context, the context has contexts and boxes. When called on this context, the context has
had its width set by the parent context. */ had its width set by the parent context. */
fn assign_widths_inline(@mut self, ctx: &mut LayoutContext) { fn assign_widths_inline(@mut self, ctx: &mut LayoutContext) {
fail_unless!(self.starts_inline_flow()); assert!(self.starts_inline_flow());
// initialize (content) box widths, if they haven't been // initialize (content) box widths, if they haven't been
// already. This could be combined with LineboxScanner's walk // already. This could be combined with LineboxScanner's walk
@ -685,17 +681,22 @@ impl InlineLayout for FlowContext {
let mut linebox_bounding_box = Au::zero_rect(); let mut linebox_bounding_box = Au::zero_rect();
let boxes = &mut self.inline().boxes; let boxes = &mut self.inline().boxes;
for line_span.eachi |box_i| { for line_span.eachi |box_i| {
let mut cur_box = boxes[box_i]; let cur_box : &mut RenderBox = boxes[box_i]; // FIXME: borrow checker workaround
// compute box height. // compute box height.
cur_box.d().position.size.height = match cur_box { let d = cur_box.d(); // FIXME: borrow checker workaround
@ImageBox(_, ref img) => Au::from_px(img.size().height), let cur_box : &mut RenderBox = boxes[box_i]; // FIXME: borrow checker workaround
@TextBox(*) => { /* text boxes are initialized with dimensions */ d.position.size.height = match *cur_box {
cur_box.d().position.size.height ImageBox(_, ref img) => {
Au::from_px(img.size().height)
}
TextBox(*) => { /* text boxes are initialized with dimensions */
d.position.size.height
}, },
// TODO(Issue #225): different cases for 'inline-block', other replaced content // TODO(Issue #225): different cases for 'inline-block', other replaced content
@GenericBox(*) => Au::from_px(30), GenericBox(*) => Au::from_px(30),
_ => { _ => {
let cur_box = boxes[box_i]; // FIXME: borrow checker workaround
fail!(fmt!("Tried to assign height to unknown Box variant: %s", fail!(fmt!("Tried to assign height to unknown Box variant: %s",
cur_box.debug_str())) cur_box.debug_str()))
} }
@ -704,22 +705,23 @@ impl InlineLayout for FlowContext {
// compute bounding rect, with left baseline as origin. // compute bounding rect, with left baseline as origin.
// so, linebox height is a matter of lining up ideal baselines, // so, linebox height is a matter of lining up ideal baselines,
// and then using the union of all these rects. // and then using the union of all these rects.
let bounding_box = match cur_box { let bounding_box = match *cur_box {
// adjust to baseline coords // adjust to baseline coords
// TODO(Issue #227): use left/right margins, border, padding for nonreplaced content, // TODO(Issue #227): use left/right margins, border, padding for nonreplaced content,
// and also use top/bottom margins, border, padding for replaced or inline-block content. // and also use top/bottom margins, border, padding for replaced or inline-block content.
// TODO(Issue #225): use height, width for 'inline-block', other replaced content // TODO(Issue #225): use height, width for 'inline-block', other replaced content
@ImageBox(*) | @GenericBox(*) => { ImageBox(*) | GenericBox(*) => {
let box_bounds = cur_box.d().position; let box_bounds = d.position;
box_bounds.translate(&Point2D(Au(0), -cur_box.d().position.size.height)) box_bounds.translate(&Point2D(Au(0), -d.position.size.height))
}, },
// adjust bounding box metric to box's horizontal offset // adjust bounding box metric to box's horizontal offset
// TODO: we can use font metrics directly instead of re-measuring for the bounding box. // TODO: we can use font metrics directly instead of re-measuring for the bounding box.
@TextBox(_, data) => { TextBox(_, data) => {
let text_bounds = data.run.metrics_for_range(&const data.range).bounding_box; let text_bounds = data.run.metrics_for_range(&data.range).bounding_box;
text_bounds.translate(&Point2D(cur_box.d().position.origin.x, Au(0))) text_bounds.translate(&Point2D(d.position.origin.x, Au(0)))
}, },
_ => { _ => {
let cur_box = boxes[box_i]; // FIXME: borrow checker workaround
fail!(fmt!("Tried to compute bounding box of unknown Box variant: %s", fail!(fmt!("Tried to compute bounding box of unknown Box variant: %s",
cur_box.debug_str())) cur_box.debug_str()))
} }
@ -750,14 +752,15 @@ impl InlineLayout for FlowContext {
} }
fn build_display_list_inline(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_inline(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Mut<DisplayList>) { offset: &Point2D<Au>, list: &Cell<DisplayList>) {
fail_unless!(self.starts_inline_flow()); assert!(self.starts_inline_flow());
// TODO(Issue #228): once we form line boxes and have their cached bounds, we can be // TODO(Issue #228): once we form line boxes and have their cached bounds, we can be
// smarter and not recurse on a line if nothing in it can intersect dirty // smarter and not recurse on a line if nothing in it can intersect dirty
let inline = self.inline(); // FIXME: borrow checker workaround
debug!("FlowContext[%d]: building display list for %u inline boxes", debug!("FlowContext[%d]: building display list for %u inline boxes",
self.d().id, self.inline().boxes.len()); self.d().id, inline.boxes.len());
let boxes = &mut self.inline().boxes; let boxes = &mut self.inline().boxes;
for boxes.each |box| { for boxes.each |box| {
box.build_display_list(builder, dirty, offset, list) box.build_display_list(builder, dirty, offset, list)

View file

@ -1,13 +1,11 @@
/// The layout task. Performs layout on the DOM, builds display lists and sends them to be /// The layout task. Performs layout on the DOM, builds display lists and sends them to be
/// rendered. /// rendered.
use content::content_task;
use css::matching::MatchMethods; use css::matching::MatchMethods;
use css::select::new_css_select_ctx; use css::select::new_css_select_ctx;
use dom::event::{Event, ReflowEvent}; use dom::event::{Event, ReflowEvent};
use dom::node::{AbstractNode, LayoutData}; use dom::node::{AbstractNode, LayoutData};
use layout::aux::LayoutAuxMethods; use layout::aux::LayoutAuxMethods;
use layout::box::RenderBox;
use layout::box_builder::LayoutTreeBuilder; use layout::box_builder::LayoutTreeBuilder;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::debug::{BoxedMutDebugMethods, DebugMethods}; use layout::debug::{BoxedMutDebugMethods, DebugMethods};
@ -21,9 +19,6 @@ use util::time::time;
use core::cell::Cell; use core::cell::Cell;
use core::comm::{Chan, Port, SharedChan}; use core::comm::{Chan, Port, SharedChan};
use core::mutable::Mut;
use core::task::*;
use core::util::replace;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
@ -36,7 +31,6 @@ use gfx::render_task::{RenderMsg, RenderTask};
use newcss::select::SelectCtx; use newcss::select::SelectCtx;
use newcss::stylesheet::Stylesheet; use newcss::stylesheet::Stylesheet;
use newcss::types::OriginAuthor; use newcss::types::OriginAuthor;
use std::arc::ARC;
use std::net::url::Url; use std::net::url::Url;
pub type LayoutTask = SharedChan<Msg>; pub type LayoutTask = SharedChan<Msg>;
@ -102,7 +96,7 @@ struct Layout {
font_ctx: @mut FontContext, font_ctx: @mut FontContext,
// This is used to root reader data // This is used to root reader data
layout_refs: ~[@mut LayoutData], layout_refs: ~[@mut LayoutData],
css_select_ctx: Mut<SelectCtx>, css_select_ctx: @mut SelectCtx,
} }
fn Layout(render_task: RenderTask, fn Layout(render_task: RenderTask,
@ -119,7 +113,7 @@ fn Layout(render_task: RenderTask,
from_content: from_content, from_content: from_content,
font_ctx: fctx, font_ctx: fctx,
layout_refs: ~[], layout_refs: ~[],
css_select_ctx: Mut(new_css_select_ctx()) css_select_ctx: @mut new_css_select_ctx()
} }
} }
@ -162,9 +156,7 @@ impl Layout {
fn handle_add_stylesheet(&self, sheet: Stylesheet) { fn handle_add_stylesheet(&self, sheet: Stylesheet) {
let sheet = Cell(sheet); let sheet = Cell(sheet);
do self.css_select_ctx.borrow_mut |ctx| { self.css_select_ctx.append_sheet(sheet.take(), OriginAuthor);
ctx.append_sheet(sheet.take(), OriginAuthor);
}
} }
fn handle_build(&mut self, data: &BuildData) { fn handle_build(&mut self, data: &BuildData) {
@ -202,9 +194,7 @@ impl Layout {
NoDamage | ReflowDamage => {} NoDamage | ReflowDamage => {}
MatchSelectorsDamage => { MatchSelectorsDamage => {
do time("layout: selector matching") { do time("layout: selector matching") {
do self.css_select_ctx.borrow_imm |ctx| { node.restyle_subtree(self.css_select_ctx);
node.restyle_subtree(ctx);
}
} }
} }
} }
@ -235,16 +225,16 @@ impl Layout {
ctx: &layout_ctx, ctx: &layout_ctx,
}; };
let display_list = Mut(DisplayList::new()); let display_list = @Cell(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
layout_root.build_display_list(&builder, layout_root.build_display_list(&builder,
&copy layout_root.d().position, &copy layout_root.d().position,
&display_list); display_list);
let render_layer = RenderLayer { let render_layer = RenderLayer {
display_list: display_list.unwrap(), display_list: display_list.take(),
size: Size2D(screen_size.width.to_px() as uint, size: Size2D(screen_size.width.to_px() as uint,
screen_size.height.to_px() as uint) screen_size.height.to_px() as uint)
}; };
@ -257,7 +247,7 @@ impl Layout {
} }
fn handle_query(query: LayoutQuery, fn handle_query(&self, query: LayoutQuery,
reply_chan: Chan<LayoutQueryResponse>) { reply_chan: Chan<LayoutQueryResponse>) {
match query { match query {
ContentBox(node) => { ContentBox(node) => {

View file

@ -1,5 +1,4 @@
use au = gfx::geometry; use core::cell::Cell;
use newcss::values::*;
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;
@ -7,10 +6,8 @@ use gfx::geometry::Au;
use layout::block::BlockLayout; use layout::block::BlockLayout;
use layout::box::RenderBox; use layout::box::RenderBox;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use layout::flow::{FlowContext, FlowTree, InlineBlockFlow, BlockFlow, RootFlow}; use layout::flow::{FlowContext, FlowTree, RootFlow};
use layout::display_list_builder::DisplayListBuilder; use layout::display_list_builder::DisplayListBuilder;
use util::tree;
use core::mutable::Mut;
pub struct RootFlowData { pub struct RootFlowData {
box: Option<@mut RenderBox> box: Option<@mut RenderBox>
@ -23,18 +20,18 @@ pub fn RootFlowData() -> RootFlowData {
} }
pub trait RootLayout { pub trait RootLayout {
pure fn starts_root_flow() -> bool; fn starts_root_flow(&self) -> bool;
fn bubble_widths_root(@mut self, ctx: &LayoutContext); fn bubble_widths_root(@mut self, ctx: &LayoutContext);
fn assign_widths_root(@mut self, ctx: &LayoutContext); fn assign_widths_root(@mut self, ctx: &LayoutContext);
fn assign_height_root(@mut self, ctx: &LayoutContext); fn assign_height_root(@mut self, ctx: &LayoutContext);
fn build_display_list_root(@mut self, a: &DisplayListBuilder, b: &Rect<Au>, fn build_display_list_root(@mut self, a: &DisplayListBuilder, b: &Rect<Au>,
c: &Point2D<Au>, d: &Mut<DisplayList>); c: &Point2D<Au>, d: &Cell<DisplayList>);
} }
impl RootLayout for FlowContext { impl RootLayout for FlowContext {
pure fn starts_root_flow() -> bool { fn starts_root_flow(&self) -> bool {
match self { match *self {
RootFlow(*) => true, RootFlow(*) => true,
_ => false _ => false
} }
@ -42,12 +39,12 @@ impl RootLayout for FlowContext {
/* defer to the block algorithm */ /* defer to the block algorithm */
fn bubble_widths_root(@mut self, ctx: &LayoutContext) { fn bubble_widths_root(@mut self, ctx: &LayoutContext) {
fail_unless!(self.starts_root_flow()); assert!(self.starts_root_flow());
self.bubble_widths_block(ctx) self.bubble_widths_block(ctx)
} }
fn assign_widths_root(@mut self, ctx: &LayoutContext) { fn assign_widths_root(@mut self, ctx: &LayoutContext) {
fail_unless!(self.starts_root_flow()); assert!(self.starts_root_flow());
self.d().position.origin = Au::zero_point(); self.d().position.origin = Au::zero_point();
self.d().position.size.width = ctx.screen_size.size.width; self.d().position.size.width = ctx.screen_size.size.width;
@ -56,7 +53,7 @@ impl RootLayout for FlowContext {
} }
fn assign_height_root(@mut self, ctx: &LayoutContext) { fn assign_height_root(@mut self, ctx: &LayoutContext) {
fail_unless!(self.starts_root_flow()); assert!(self.starts_root_flow());
// this is essentially the same as assign_height_block(), except // this is essentially the same as assign_height_block(), except
// the root adjusts self height to at least cover the viewport. // the root adjusts self height to at least cover the viewport.
@ -77,8 +74,8 @@ impl RootLayout for FlowContext {
} }
fn build_display_list_root(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>, fn build_display_list_root(@mut self, builder: &DisplayListBuilder, dirty: &Rect<Au>,
offset: &Point2D<Au>, list: &Mut<DisplayList>) { offset: &Point2D<Au>, list: &Cell<DisplayList>) {
fail_unless!(self.starts_root_flow()); assert!(self.starts_root_flow());
self.build_display_list_block(builder, dirty, offset, list); self.build_display_list_block(builder, dirty, offset, list);
} }

View file

@ -10,7 +10,7 @@ pub struct TextBoxData {
range: Range, range: Range,
} }
pub fn TextBoxData(run: @TextRun, range: &const Range) -> TextBoxData { pub fn TextBoxData(run: @TextRun, range: &Range) -> TextBoxData {
TextBoxData { TextBoxData {
run: run, run: run,
range: copy *range, range: copy *range,
@ -18,10 +18,10 @@ pub fn TextBoxData(run: @TextRun, range: &const Range) -> TextBoxData {
} }
pub fn adapt_textbox_with_range(box_data: &mut RenderBoxData, run: @TextRun, pub fn adapt_textbox_with_range(box_data: &mut RenderBoxData, run: @TextRun,
range: &const Range) -> @mut RenderBox { range: &Range) -> @mut RenderBox {
fail_unless!(range.begin() < run.char_len()); assert!(range.begin() < run.char_len());
fail_unless!(range.end() <= run.char_len()); assert!(range.end() <= run.char_len());
fail_unless!(range.length() > 0); assert!(range.length() > 0);
debug!("Creating textbox with span: (strlen=%u, off=%u, len=%u) of textrun: %s", debug!("Creating textbox with span: (strlen=%u, off=%u, len=%u) of textrun: %s",
run.char_len(), range.begin(), range.length(), run.text); run.char_len(), range.begin(), range.length(), run.text);
@ -33,11 +33,11 @@ pub fn adapt_textbox_with_range(box_data: &mut RenderBoxData, run: @TextRun,
} }
pub trait UnscannedMethods { pub trait UnscannedMethods {
pure fn raw_text(&mut self) -> ~str; fn raw_text(&mut self) -> ~str;
} }
impl UnscannedMethods for RenderBox { impl UnscannedMethods for RenderBox {
pure fn raw_text(&mut self) -> ~str { fn raw_text(&mut self) -> ~str {
match self { match self {
&UnscannedTextBox(_, ref s) => copy *s, &UnscannedTextBox(_, ref s) => copy *s,
_ => fail!(~"unsupported operation: box.raw_text() on non-unscanned text box.") _ => fail!(~"unsupported operation: box.raw_text() on non-unscanned text box.")

View file

@ -1,21 +1,18 @@
use ShareGlContext = sharegl::platform::Context; use ShareGlContext = sharegl::platform::Context;
use dom::event::{Event, ResizeEvent}; use dom::event::Event;
use platform::resize_rate_limiter::ResizeRateLimiter; use platform::resize_rate_limiter::ResizeRateLimiter;
use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods}; use azure::azure_hl::{BackendType, B8G8R8A8, DataSourceSurface, DrawTarget, SourceSurfaceMethods};
use core::comm::{Chan, SharedChan, Port}; use core::comm::{Chan, SharedChan, Port};
use core::task::TaskBuilder;
use core::util; use core::util;
use geom::matrix::{Matrix4, identity}; use geom::matrix::identity;
use geom::point::Point2D; use geom::point::Point2D;
use geom::rect::Rect; use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet}; use gfx::compositor::{Compositor, LayerBuffer, LayerBufferSet};
use gfx::opts::Opts; use gfx::opts::Opts;
use gfx::util::time; use gfx::util::time;
use layers::layers::ImageLayer;
use core::cell::Cell; use core::cell::Cell;
use std::cmp::FuzzyEq;
use glut::glut; use glut::glut;
use layers; use layers;
use sharegl; use sharegl;
@ -290,7 +287,7 @@ struct SurfaceSet {
fn lend_surface(surfaces: &mut SurfaceSet, receiver: comm::Chan<LayerBufferSet>) { fn lend_surface(surfaces: &mut SurfaceSet, receiver: comm::Chan<LayerBufferSet>) {
// We are in a position to lend out the surface? // We are in a position to lend out the surface?
fail_unless!(surfaces.front.have); assert!(surfaces.front.have);
// Ok then take it // Ok then take it
let old_layer_buffers = util::replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]); let old_layer_buffers = util::replace(&mut surfaces.front.layer_buffer_set.buffers, ~[]);
let new_layer_buffers = do old_layer_buffers.map |layer_buffer| { let new_layer_buffers = do old_layer_buffers.map |layer_buffer| {
@ -312,14 +309,14 @@ fn lend_surface(surfaces: &mut SurfaceSet, receiver: comm::Chan<LayerBufferSet>)
// But we (hopefully) have another! // But we (hopefully) have another!
surfaces.front <-> surfaces.back; surfaces.front <-> surfaces.back;
// Let's look // Let's look
fail_unless!(surfaces.front.have); assert!(surfaces.front.have);
} }
fn return_surface(surfaces: &mut SurfaceSet, layer_buffer_set: LayerBufferSet) { fn return_surface(surfaces: &mut SurfaceSet, layer_buffer_set: LayerBufferSet) {
//#debug("osmain: returning surface %?", layer_buffer_set); //#debug("osmain: returning surface %?", layer_buffer_set);
// We have room for a return // We have room for a return
fail_unless!(surfaces.front.have); assert!(surfaces.front.have);
fail_unless!(!surfaces.back.have); assert!(!surfaces.back.have);
surfaces.back.layer_buffer_set = layer_buffer_set; surfaces.back.layer_buffer_set = layer_buffer_set;

View file

@ -28,7 +28,7 @@ pub impl ResizeRateLimiter {
fn window_resized(&mut self, width: uint, height: uint) { fn window_resized(&mut self, width: uint, height: uint) {
match self.last_response_port { match self.last_response_port {
None => { None => {
fail_unless!(self.next_resize_event.is_none()); assert!(self.next_resize_event.is_none());
self.send_event(width, height); self.send_event(width, height);
} }
Some(*) => { Some(*) => {
@ -48,7 +48,7 @@ pub impl ResizeRateLimiter {
fn check_resize_response(&mut self) { fn check_resize_response(&mut self) {
match self.next_resize_event { match self.next_resize_event {
Some((copy width, copy height)) => { Some((copy width, copy height)) => {
fail_unless!(self.last_response_port.is_some()); assert!(self.last_response_port.is_some());
if self.last_response_port.get_ref().peek() { if self.last_response_port.get_ref().peek() {
self.send_event(width, height); self.send_event(width, height);
self.next_resize_event = None; self.next_resize_event = None;

View file

@ -24,6 +24,21 @@ extern mod sharegl;
extern mod stb_image; extern mod stb_image;
extern mod std; extern mod std;
#[cfg(target_os="macos")]
extern mod core_graphics;
#[cfg(target_os="macos")]
extern mod core_text;
use engine::{Engine, LoadURLMsg};
use platform::osmain::{AddKeyHandler, OSMain};
pub use gfx::opts::{Opts, Png, Screen}; // FIXME: Do we really want "Screen" and "Png" visible?
pub use gfx::resource;
pub use gfx::resource::image_cache_task::ImageCacheTask;
pub use gfx::resource::resource_task::ResourceTask;
pub use gfx::text;
pub use gfx::util::url::make_url;
pub mod content { pub mod content {
pub mod content_task; pub mod content_task;
} }
@ -95,26 +110,6 @@ pub mod platform {
#[path = "util/mod.rs"] #[path = "util/mod.rs"]
pub mod util; pub mod util;
use servo_util = util;
#[cfg(target_os="macos")]
extern mod core_graphics;
#[cfg(target_os="macos")]
extern mod core_text;
use engine::{Engine, ExitMsg, LoadURLMsg}; // FIXME: "ExitMsg" is pollution.
use platform::osmain::{AddKeyHandler, OSMain};
use core::option::swap_unwrap;
use core::comm::{Port, Chan};
pub use gfx::opts::{Opts, Png, Screen}; // FIXME: Do we really want "Screen" and "Png" visible?
pub use gfx::resource;
pub use gfx::resource::image_cache_task::ImageCacheTask;
pub use gfx::resource::resource_task::ResourceTask;
pub use gfx::text;
pub use gfx::util::url::make_url;
fn main() { fn main() {
let args = os::args(); let args = os::args();
run(&gfx::opts::from_cmdline_args(args)) run(&gfx::opts::from_cmdline_args(args))
@ -125,7 +120,7 @@ fn run(opts: &Opts) {
match &opts.render_mode { match &opts.render_mode {
&Screen => run_pipeline_screen(opts), &Screen => run_pipeline_screen(opts),
&Png(ref outfile) => { &Png(ref outfile) => {
fail_unless!(!opts.urls.is_empty()); assert!(!opts.urls.is_empty());
if opts.urls.len() > 1u { if opts.urls.len() > 1u {
fail!(~"servo asks that you stick to a single URL in PNG output mode") fail!(~"servo asks that you stick to a single URL in PNG output mode")
} }

View file

@ -1,5 +1,3 @@
use core::vec;
// A generic tree datatype. // A generic tree datatype.
// //
// TODO: Use traits. // TODO: Use traits.
@ -13,12 +11,12 @@ pub struct Tree<T> {
} }
pub trait ReadMethods<T> { pub trait ReadMethods<T> {
fn with_tree_fields<R>(&T, f: &fn(&mut Tree<T>) -> R) -> R; fn with_tree_fields<R>(&self, &T, f: &fn(&mut Tree<T>) -> R) -> R;
} }
pub trait WriteMethods<T> { pub trait WriteMethods<T> {
fn with_tree_fields<R>(&T, f: &fn(&mut Tree<T>) -> R) -> R; fn with_tree_fields<R>(&self, &T, f: &fn(&mut Tree<T>) -> R) -> R;
pure fn tree_eq(&T, &T) -> bool; fn tree_eq(&self, &T, &T) -> bool;
} }
pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: &fn(&T) -> bool) { pub fn each_child<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T, f: &fn(&T) -> bool) {
@ -69,7 +67,7 @@ pub fn empty<T>() -> Tree<T> {
} }
pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) { pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
fail_unless!(!ops.tree_eq(&parent, &child)); assert!(!ops.tree_eq(&parent, &child));
ops.with_tree_fields(&child, |child_tf| { ops.with_tree_fields(&child, |child_tf| {
match child_tf.parent { match child_tf.parent {
@ -77,8 +75,8 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
None => { child_tf.parent = Some(parent); } None => { child_tf.parent = Some(parent); }
} }
fail_unless!(child_tf.prev_sibling.is_none()); assert!(child_tf.prev_sibling.is_none());
fail_unless!(child_tf.next_sibling.is_none()); assert!(child_tf.next_sibling.is_none());
ops.with_tree_fields(&parent, |parent_tf| { ops.with_tree_fields(&parent, |parent_tf| {
match copy parent_tf.last_child { match copy parent_tf.last_child {
@ -87,7 +85,7 @@ pub fn add_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
} }
Some(lc) => { Some(lc) => {
ops.with_tree_fields(&lc, |lc_tf| { ops.with_tree_fields(&lc, |lc_tf| {
fail_unless!(lc_tf.next_sibling.is_none()); assert!(lc_tf.next_sibling.is_none());
lc_tf.next_sibling = Some(child); lc_tf.next_sibling = Some(child);
}); });
child_tf.prev_sibling = Some(lc); child_tf.prev_sibling = Some(lc);
@ -104,7 +102,7 @@ pub fn remove_child<T:Copy,O:WriteMethods<T>>(ops: &O, parent: T, child: T) {
match copy child_tf.parent { match copy child_tf.parent {
None => { fail!(~"Not a child"); } None => { fail!(~"Not a child"); }
Some(parent_n) => { Some(parent_n) => {
fail_unless!(ops.tree_eq(&parent, &parent_n)); assert!(ops.tree_eq(&parent, &parent_n));
// adjust parent fields // adjust parent fields
do ops.with_tree_fields(&parent) |parent_tf| { do ops.with_tree_fields(&parent) |parent_tf| {
@ -159,33 +157,33 @@ pub fn get_parent<T:Copy,O:ReadMethods<T>>(ops: &O, node: &T) -> Option<T> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use core::managed::ptr_eq; use core::managed::mut_ptr_eq;
struct dummy { struct dummy {
fields: Tree<@dummy>, fields: Tree<@mut dummy>,
value: uint value: uint
} }
enum dtree { dtree } enum dtree { dtree }
impl ReadMethods<@dummy> for dtree { impl ReadMethods<@mut dummy> for dtree {
fn with_tree_fields<R>(d: &@dummy, f: &fn(&Tree<@dummy>) -> R) -> R { fn with_tree_fields<R>(&self, d: &@mut dummy, f: &fn(&mut Tree<@mut dummy>) -> R) -> R {
f(&d.fields) f(&mut d.fields)
} }
} }
impl WriteMethods<@dummy> for dtree { impl WriteMethods<@mut dummy> for dtree {
fn with_tree_fields<R>(d: &@dummy, f: &fn(&Tree<@dummy>) -> R) -> R { fn with_tree_fields<R>(&self, d: &@mut dummy, f: &fn(&mut Tree<@mut dummy>) -> R) -> R {
f(&d.fields) f(&mut d.fields)
} }
pure fn tree_eq(a: &@dummy, b: &@dummy) -> bool { ptr_eq(*a, *b) } fn tree_eq(&self, a: &@mut dummy, b: &@mut dummy) -> bool { mut_ptr_eq(*a, *b) }
} }
fn new_dummy(v: uint) -> @dummy { fn new_dummy(v: uint) -> @mut dummy {
@dummy {fields: empty(), value: v} @mut dummy {fields: empty(), value: v}
} }
fn parent_with_3_children() -> (@dummy, ~[@dummy]) { fn parent_with_3_children() -> (@mut dummy, ~[@mut dummy]) {
let children = ~[new_dummy(0u), let children = ~[new_dummy(0u),
new_dummy(1u), new_dummy(1u),
new_dummy(2u)]; new_dummy(2u)];
@ -203,10 +201,10 @@ mod test {
let (p, children) = parent_with_3_children(); let (p, children) = parent_with_3_children();
let mut i = 0u; let mut i = 0u;
for each_child(&dtree, &p) |c| { for each_child(&dtree, &p) |c| {
fail_unless!(c.value == i); assert!(c.value == i);
i += 1u; i += 1u;
} }
fail_unless!(i == children.len()); assert!(i == children.len());
} }
#[test] #[test]
@ -217,7 +215,7 @@ mod test {
i += 1u; i += 1u;
break; break;
} }
fail_unless!(i == 1u); assert!(i == 1u);
} }
#[test] #[test]
@ -229,7 +227,7 @@ mod test {
for each_child(&dtree, &p) |_c| { for each_child(&dtree, &p) |_c| {
i += 1; i += 1;
} }
fail_unless!(i == 2); assert!(i == 2);
} }
#[test] #[test]
@ -241,7 +239,7 @@ mod test {
for each_child(&dtree, &p) |_c| { for each_child(&dtree, &p) |_c| {
i += 1; i += 1;
} }
fail_unless!(i == 2); assert!(i == 2);
} }
#[test] #[test]
@ -253,7 +251,7 @@ mod test {
for each_child(&dtree, &p) |_c| { for each_child(&dtree, &p) |_c| {
i += 1; i += 1;
} }
fail_unless!(i == 2); assert!(i == 2);
} }
#[test] #[test]
@ -267,6 +265,6 @@ mod test {
for each_child(&dtree, &p) |_c| { for each_child(&dtree, &p) |_c| {
i += 1; i += 1;
} }
fail_unless!(i == 0); assert!(i == 0);
} }
} }

@ -1 +1 @@
Subproject commit 08f3a25f9465e7bf5638ddea384cfb2d17272e36 Subproject commit 4fc8d3f311a9c11078c574f5d82221c65367c70d