mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
Update to Rust 0.6.
This commit is contained in:
parent
b9f82b8d05
commit
c850b59680
97 changed files with 1049 additions and 1135 deletions
|
@ -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
|
2
src/rust
2
src/rust
|
@ -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
|
|
@ -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,15 +67,15 @@ 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 {
|
||||||
|
@ -84,7 +83,7 @@ impl DisplayItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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: ~[] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,7 +52,7 @@ 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, ()> {
|
||||||
|
@ -61,7 +60,7 @@ pub impl FontHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[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, ()> {
|
||||||
|
@ -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,7 +242,7 @@ 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)
|
||||||
|
@ -268,7 +267,7 @@ 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();
|
||||||
|
|
||||||
|
@ -282,7 +281,7 @@ 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?
|
||||||
|
@ -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(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,7 +110,7 @@ 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,7 +149,7 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,7 +22,7 @@ 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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,26 +31,24 @@ 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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,23 +3,18 @@ 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>);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
||||||
|
|
|
@ -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,7 +21,7 @@ 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,
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(%?): %?",
|
||||||
|
|
|
@ -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>()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
|
@ -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");
|
||||||
fail_unless!(cx == compartment.cx.ptr);
|
assert!(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() {
|
||||||
|
|
|
@ -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?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,7 +86,7 @@ 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)
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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| {
|
||||||
|
|
|
@ -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
|
||||||
|
@ -119,7 +110,7 @@ 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,17 +400,19 @@ 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();
|
||||||
list.append_item(~DisplayItem::new_Text(&abs_box_bounds,
|
let mut l = list.take(); // FIXME: this should use with_mut_ref when that appears
|
||||||
|
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 frames for text box bounds
|
||||||
debug!("%?", {
|
debug!("%?", {
|
||||||
// text box bounds
|
// text box bounds
|
||||||
list.append_item(~DisplayItem::new_Border(&abs_box_bounds,
|
let mut l = list.take(); // FIXME: use with_mut_ref when that appears
|
||||||
|
l.append_item(~DisplayItem::new_Border(&abs_box_bounds,
|
||||||
Au::from_px(1),
|
Au::from_px(1),
|
||||||
rgb(0, 0, 200).to_gfx_color()));
|
rgb(0, 0, 200).to_gfx_color()));
|
||||||
// baseline "rect"
|
// baseline "rect"
|
||||||
|
@ -428,11 +421,11 @@ impl RenderBox {
|
||||||
let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent),
|
let baseline = Rect(abs_box_bounds.origin + Point2D(Au(0),ascent),
|
||||||
Size2D(abs_box_bounds.size.width, Au(0)));
|
Size2D(abs_box_bounds.size.width, Au(0)));
|
||||||
|
|
||||||
list.append_item(~DisplayItem::new_Border(&baseline,
|
l.append_item(~DisplayItem::new_Border(&baseline,
|
||||||
Au::from_px(1),
|
Au::from_px(1),
|
||||||
rgb(0, 200, 0).to_gfx_color()));
|
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");
|
||||||
list.append_item(~DisplayItem::new_Image(&abs_box_bounds,
|
let mut l = list.take(); // FIXME: use with_mut_ref when available
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -93,7 +93,7 @@ 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,21 +169,30 @@ 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) }
|
||||||
|
@ -190,18 +200,27 @@ pub impl FlowContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 += ~")";
|
||||||
|
@ -287,6 +307,7 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) => {
|
|
||||||
debug!("LineboxScanner: Working with box from work list: b%d", box.d().id);
|
|
||||||
box
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
if i == boxes.len() { break; }
|
if i == boxes.len() { break; }
|
||||||
let box = boxes[i]; i += 1;
|
let box = boxes[i]; i += 1;
|
||||||
debug!("LineboxScanner: Working with box from box list: b%d", box.d().id);
|
debug!("LineboxScanner: Working with box from box list: b%d", box.d().id);
|
||||||
box
|
box
|
||||||
}
|
} else {
|
||||||
|
let box = self.work_list.pop_front();
|
||||||
|
debug!("LineboxScanner: Working with box from work list: b%d", box.d().id);
|
||||||
|
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)
|
||||||
|
|
|
@ -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,
|
||||||
© layout_root.d().position,
|
© 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) => {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.")
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue