mirror of
https://github.com/servo/servo.git
synced 2025-06-24 00:54:32 +01:00
auto merge of #735 : kmcallister/servo/rust-upgrade, r=kmcallister,metajack
Was #734.
This commit is contained in:
commit
2359587cbb
103 changed files with 1199 additions and 1148 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -22,9 +22,6 @@
|
||||||
[submodule "src/support/opengles/rust-opengles"]
|
[submodule "src/support/opengles/rust-opengles"]
|
||||||
path = src/support/opengles/rust-opengles
|
path = src/support/opengles/rust-opengles
|
||||||
url = https://github.com/mozilla-servo/rust-opengles.git
|
url = https://github.com/mozilla-servo/rust-opengles.git
|
||||||
[submodule "src/support/glut/rust-glut"]
|
|
||||||
path = src/support/glut/rust-glut
|
|
||||||
url = https://github.com/mozilla-servo/rust-glut.git
|
|
||||||
[submodule "src/support/layers/rust-layers"]
|
[submodule "src/support/layers/rust-layers"]
|
||||||
path = src/support/layers/rust-layers
|
path = src/support/layers/rust-layers
|
||||||
url = https://github.com/mozilla-servo/rust-layers.git
|
url = https://github.com/mozilla-servo/rust-layers.git
|
||||||
|
|
12
Makefile.in
12
Makefile.in
|
@ -29,7 +29,7 @@ B := $(CFG_BUILD_DIR)
|
||||||
|
|
||||||
MKFILE_DEPS := config.stamp $(call rwildcard,$(S)mk/,*)
|
MKFILE_DEPS := config.stamp $(call rwildcard,$(S)mk/,*)
|
||||||
|
|
||||||
CFG_RUSTC_FLAGS := $(RUSTFLAGS) -A default_methods
|
CFG_RUSTC_FLAGS := $(RUSTFLAGS)
|
||||||
|
|
||||||
ifdef CFG_DISABLE_OPTIMIZE
|
ifdef CFG_DISABLE_OPTIMIZE
|
||||||
$(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE))
|
$(info cfg: disabling rustc optimization (CFG_DISABLE_OPTIMIZE))
|
||||||
|
@ -235,23 +235,23 @@ all: src/compiler/rust/rust-auto-clean-stamp servo package
|
||||||
|
|
||||||
$(DONE_util): $(DEPS_util)
|
$(DONE_util): $(DEPS_util)
|
||||||
@$(call E, compile: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(RUSTC) $(RFLAGS_util) -o $@ $< && touch $@
|
$(Q)$(RUSTC) $(RFLAGS_util) --out-dir src/components/util $< && touch $@
|
||||||
|
|
||||||
$(DONE_net): $(DEPS_net)
|
$(DONE_net): $(DEPS_net)
|
||||||
@$(call E, compile: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(RUSTC) $(RFLAGS_net) -o $@ $< && touch $@
|
$(Q)$(RUSTC) $(RFLAGS_net) --out-dir src/components/net $< && touch $@
|
||||||
|
|
||||||
$(DONE_msg): $(DEPS_msg)
|
$(DONE_msg): $(DEPS_msg)
|
||||||
@$(call E, compile: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(RUSTC) $(RFLAGS_msg) -o $@ $< && touch $@
|
$(Q)$(RUSTC) $(RFLAGS_msg) --out-dir src/components/msg $< && touch $@
|
||||||
|
|
||||||
$(DONE_gfx): $(DEPS_gfx)
|
$(DONE_gfx): $(DEPS_gfx)
|
||||||
@$(call E, compile: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(RUSTC) $(RFLAGS_gfx) -o $@ $< && touch $@
|
$(Q)$(RUSTC) $(RFLAGS_gfx) --out-dir src/components/gfx $< && touch $@
|
||||||
|
|
||||||
$(DONE_script): $(DEPS_script)
|
$(DONE_script): $(DEPS_script)
|
||||||
@$(call E, compile: $@)
|
@$(call E, compile: $@)
|
||||||
$(Q)$(RUSTC) $(RFLAGS_script) -o $@ $< && touch $@
|
$(Q)$(RUSTC) $(RFLAGS_script) --out-dir src/components/script $< && touch $@
|
||||||
|
|
||||||
BINDINGS_SRC = $(S)/src/components/script/dom/bindings/codegen
|
BINDINGS_SRC = $(S)/src/components/script/dom/bindings/codegen
|
||||||
|
|
||||||
|
|
2
configure
vendored
2
configure
vendored
|
@ -403,11 +403,9 @@ CFG_SUBMODULES="\
|
||||||
support/css/rust-css \
|
support/css/rust-css \
|
||||||
support/css/rust-cssparser \
|
support/css/rust-cssparser \
|
||||||
support/geom/rust-geom \
|
support/geom/rust-geom \
|
||||||
support/glut/rust-glut \
|
|
||||||
support/glfw/glfw \
|
support/glfw/glfw \
|
||||||
support/glfw/glfw-rs \
|
support/glfw/glfw-rs \
|
||||||
support/harfbuzz/rust-harfbuzz \
|
support/harfbuzz/rust-harfbuzz \
|
||||||
support/http-client/rust-http-client \
|
|
||||||
support/hubbub/libhubbub \
|
support/hubbub/libhubbub \
|
||||||
support/hubbub/rust-hubbub \
|
support/hubbub/rust-hubbub \
|
||||||
support/layers/rust-layers \
|
support/layers/rust-layers \
|
||||||
|
|
|
@ -51,10 +51,6 @@ DEPS_glfw-rs += \
|
||||||
glfw \
|
glfw \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
DEPS_rust-glut += \
|
|
||||||
rust-opengles \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
DEPS_rust-layers += \
|
DEPS_rust-layers += \
|
||||||
rust-geom \
|
rust-geom \
|
||||||
rust-opengles \
|
rust-opengles \
|
||||||
|
@ -143,10 +139,6 @@ DEPS_rust-layers += \
|
||||||
rust-cocoa \
|
rust-cocoa \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
DEPS_rust-glut += \
|
|
||||||
rust-cocoa \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(CFG_OSTYPE),unknown-linux-gnu)
|
ifeq ($(CFG_OSTYPE),unknown-linux-gnu)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5aa0ca9b2eb28166d9ab2e86557a5b1f84230b46
|
Subproject commit 0a677bcf6e359f6f013a7e580ef467b5f389e5b7
|
|
@ -1,4 +1,4 @@
|
||||||
# If this file is modified, then rust will be forcibly cleaned and then rebuilt.
|
# If this file is modified, then rust will be forcibly cleaned and then rebuilt.
|
||||||
# The actual contents of this file do not matter, but to trigger a change on the
|
# The actual contents of this file do not matter, but to trigger a change on the
|
||||||
# build bots then the contents should be changed so git updates the mtime.
|
# build bots then the contents should be changed so git updates the mtime.
|
||||||
2013-07-09
|
2013-08-15
|
||||||
|
|
|
@ -23,7 +23,7 @@ use std::cast::transmute_region;
|
||||||
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||||
use servo_net::image::base::Image;
|
use servo_net::image::base::Image;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
/// A list of rendering operations to be performed.
|
/// A list of rendering operations to be performed.
|
||||||
pub struct DisplayList<E> {
|
pub struct DisplayList<E> {
|
||||||
|
@ -48,7 +48,7 @@ impl<E> DisplayList<E> {
|
||||||
/// Draws the display list into the given render context.
|
/// Draws the display list into the given render context.
|
||||||
pub fn draw_into_context(&self, render_context: &RenderContext) {
|
pub fn draw_into_context(&self, render_context: &RenderContext) {
|
||||||
debug!("Beginning display list.");
|
debug!("Beginning display list.");
|
||||||
for self.list.iter().advance |item| {
|
for item in self.list.iter() {
|
||||||
// FIXME(Issue #150): crashes
|
// FIXME(Issue #150): crashes
|
||||||
//debug!("drawing %?", *item);
|
//debug!("drawing %?", *item);
|
||||||
item.draw_into_context(render_context)
|
item.draw_into_context(render_context)
|
||||||
|
@ -93,7 +93,7 @@ pub struct TextDisplayItem<E> {
|
||||||
/// Renders an image.
|
/// Renders an image.
|
||||||
pub struct ImageDisplayItem<E> {
|
pub struct ImageDisplayItem<E> {
|
||||||
base: BaseDisplayItem<E>,
|
base: BaseDisplayItem<E>,
|
||||||
image: ARC<~Image>,
|
image: Arc<~Image>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Renders a border.
|
/// Renders a border.
|
||||||
|
@ -156,7 +156,7 @@ impl<E> DisplayItem<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn base<'a>(&'a self) -> &'a BaseDisplayItem<E> {
|
pub fn base<'a>(&'a self) -> &'a BaseDisplayItem<E> {
|
||||||
// FIXME(tkuehn): Workaround for Rust region bug.
|
// FIXME(tkuehn): Workaround for Rust region bug.
|
||||||
unsafe {
|
unsafe {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -168,7 +168,7 @@ impl<E> DisplayItem<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounds(&self) -> Rect<Au> {
|
pub fn bounds(&self) -> Rect<Au> {
|
||||||
self.base().bounds
|
self.base().bounds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use platform::font::{FontHandle, FontTable};
|
||||||
use render_context::RenderContext;
|
use render_context::RenderContext;
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::result;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
@ -18,7 +17,7 @@ use servo_util::cache::{Cache, HashCache};
|
||||||
use text::glyph::{GlyphStore, GlyphIndex};
|
use text::glyph::{GlyphStore, GlyphIndex};
|
||||||
use text::shaping::ShaperMethods;
|
use text::shaping::ShaperMethods;
|
||||||
use text::{Shaper, TextRun};
|
use text::{Shaper, TextRun};
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
use azure::{AzFloat, AzScaledFontRef};
|
use azure::{AzFloat, AzScaledFontRef};
|
||||||
use azure::scaled_font::ScaledFont;
|
use azure::scaled_font::ScaledFont;
|
||||||
|
@ -58,12 +57,12 @@ pub type FractionalPixel = float;
|
||||||
|
|
||||||
pub type FontTableTag = u32;
|
pub type FontTableTag = u32;
|
||||||
|
|
||||||
trait FontTableTagConversions {
|
pub trait FontTableTagConversions {
|
||||||
pub fn tag_to_str(&self) -> ~str;
|
fn tag_to_str(&self) -> ~str;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontTableTagConversions for FontTableTag {
|
impl FontTableTagConversions for FontTableTag {
|
||||||
pub fn tag_to_str(&self) -> ~str {
|
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),
|
||||||
|
@ -183,7 +182,7 @@ impl FontGroup {
|
||||||
pub fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup {
|
pub fn new(families: @str, style: &UsedFontStyle, fonts: ~[@mut Font]) -> FontGroup {
|
||||||
FontGroup {
|
FontGroup {
|
||||||
families: families,
|
families: families,
|
||||||
style: copy *style,
|
style: (*style).clone(),
|
||||||
fonts: fonts,
|
fonts: fonts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +239,7 @@ pub struct Font {
|
||||||
metrics: FontMetrics,
|
metrics: FontMetrics,
|
||||||
backend: BackendType,
|
backend: BackendType,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
shape_cache: HashCache<~str, ARC<GlyphStore>>,
|
shape_cache: HashCache<~str, Arc<GlyphStore>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Font {
|
impl Font {
|
||||||
|
@ -252,9 +251,9 @@ impl Font {
|
||||||
-> Result<@mut Font, ()> {
|
-> Result<@mut Font, ()> {
|
||||||
let handle = FontHandleMethods::new_from_buffer(&ctx.handle, buffer, style);
|
let handle = FontHandleMethods::new_from_buffer(&ctx.handle, buffer, style);
|
||||||
let handle: FontHandle = if handle.is_ok() {
|
let handle: FontHandle = if handle.is_ok() {
|
||||||
result::unwrap(handle)
|
handle.unwrap()
|
||||||
} else {
|
} else {
|
||||||
return Err(handle.get_err());
|
return Err(handle.unwrap_err());
|
||||||
};
|
};
|
||||||
|
|
||||||
let metrics = handle.get_metrics();
|
let metrics = handle.get_metrics();
|
||||||
|
@ -264,7 +263,7 @@ impl Font {
|
||||||
handle: handle,
|
handle: handle,
|
||||||
azure_font: None,
|
azure_font: None,
|
||||||
shaper: None,
|
shaper: None,
|
||||||
style: copy *style,
|
style: (*style).clone(),
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
backend: backend,
|
backend: backend,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
|
@ -281,7 +280,7 @@ impl Font {
|
||||||
handle: handle,
|
handle: handle,
|
||||||
azure_font: None,
|
azure_font: None,
|
||||||
shaper: None,
|
shaper: None,
|
||||||
style: copy *style,
|
style: (*style).clone(),
|
||||||
metrics: metrics,
|
metrics: metrics,
|
||||||
backend: backend,
|
backend: backend,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
|
@ -302,7 +301,7 @@ impl Font {
|
||||||
return Ok(Font::new_from_adopted_handle(fctx, styled_handle, style, backend, profiler_chan));
|
return Ok(Font::new_from_adopted_handle(fctx, styled_handle, style, backend, profiler_chan));
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_shaper(@mut self) -> @Shaper {
|
fn get_shaper(@mut self) -> @Shaper {
|
||||||
// fast path: already created a shaper
|
// fast path: already created a shaper
|
||||||
match self.shaper {
|
match self.shaper {
|
||||||
Some(shaper) => { return shaper; },
|
Some(shaper) => { return shaper; },
|
||||||
|
@ -333,7 +332,7 @@ impl Font {
|
||||||
// TODO: this should return a borrowed pointer, but I can't figure
|
// TODO: this should return a borrowed pointer, but I can't figure
|
||||||
// out why borrowck doesn't like my implementation.
|
// out why borrowck doesn't like my implementation.
|
||||||
|
|
||||||
priv fn get_azure_font(&mut self) -> AzScaledFontRef {
|
fn get_azure_font(&mut self) -> AzScaledFontRef {
|
||||||
// fast path: we've already created the azure font resource
|
// fast path: we've already created the azure font resource
|
||||||
match self.azure_font {
|
match self.azure_font {
|
||||||
Some(ref azfont) => return azfont.get_ref(),
|
Some(ref azfont) => return azfont.get_ref(),
|
||||||
|
@ -347,14 +346,14 @@ impl Font {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
priv fn create_azure_font(&mut self) -> ScaledFont {
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os="linux")]
|
#[cfg(target_os="linux")]
|
||||||
priv fn create_azure_font(&self) -> ScaledFont {
|
fn create_azure_font(&self) -> ScaledFont {
|
||||||
let freetype_font = self.handle.face;
|
let freetype_font = self.handle.face;
|
||||||
let size = self.style.pt_size as AzFloat;
|
let size = self.style.pt_size as AzFloat;
|
||||||
ScaledFont::new(self.backend, freetype_font, size)
|
ScaledFont::new(self.backend, freetype_font, size)
|
||||||
|
@ -387,14 +386,14 @@ impl Font {
|
||||||
fields: 0x0200 as uint16_t
|
fields: 0x0200 as uint16_t
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut origin = copy baseline_origin;
|
let mut origin = baseline_origin.clone();
|
||||||
let mut azglyphs = ~[];
|
let mut azglyphs = ~[];
|
||||||
azglyphs.reserve(range.length());
|
azglyphs.reserve(range.length());
|
||||||
|
|
||||||
for run.iter_slices_for_range(range) |glyphs, _offset, slice_range| {
|
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
||||||
for glyphs.iter_glyphs_for_char_range(slice_range) |_i, glyph| {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
||||||
let glyph_advance = glyph.advance_();
|
let glyph_advance = glyph.advance();
|
||||||
let glyph_offset = glyph.offset().get_or_default(Au::zero_point());
|
let glyph_offset = glyph.offset().unwrap_or_default(Au::zero_point());
|
||||||
|
|
||||||
let azglyph = struct__AzGlyph {
|
let azglyph = struct__AzGlyph {
|
||||||
mIndex: glyph.index() as uint32_t,
|
mIndex: glyph.index() as uint32_t,
|
||||||
|
@ -431,9 +430,9 @@ impl Font {
|
||||||
// TODO(Issue #199): alter advance direction for RTL
|
// TODO(Issue #199): alter advance direction for RTL
|
||||||
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for run.iter_slices_for_range(range) |glyphs, _offset, slice_range| {
|
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
|
||||||
for glyphs.iter_glyphs_for_char_range(slice_range) |_i, glyph| {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
|
||||||
advance = advance + glyph.advance_();
|
advance = advance + glyph.advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RunMetrics::new(advance, self.metrics.ascent, self.metrics.descent)
|
RunMetrics::new(advance, self.metrics.ascent, self.metrics.descent)
|
||||||
|
@ -444,25 +443,25 @@ impl Font {
|
||||||
slice_range: &Range)
|
slice_range: &Range)
|
||||||
-> RunMetrics {
|
-> RunMetrics {
|
||||||
let mut advance = Au(0);
|
let mut advance = Au(0);
|
||||||
for glyphs.iter_glyphs_for_char_range(slice_range) |_i, glyph| {
|
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
|
||||||
advance = advance + glyph.advance_();
|
advance = advance + glyph.advance();
|
||||||
}
|
}
|
||||||
RunMetrics::new(advance, self.metrics.ascent, self.metrics.descent)
|
RunMetrics::new(advance, self.metrics.ascent, self.metrics.descent)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shape_text(@mut self, text: ~str, is_whitespace: bool) -> ARC<GlyphStore> {
|
pub fn shape_text(@mut self, text: ~str, is_whitespace: bool) -> Arc<GlyphStore> {
|
||||||
do profile(time::LayoutShapingCategory, self.profiler_chan.clone()) {
|
do profile(time::LayoutShapingCategory, self.profiler_chan.clone()) {
|
||||||
let shaper = self.get_shaper();
|
let shaper = self.get_shaper();
|
||||||
do self.shape_cache.find_or_create(&text) |txt| {
|
do self.shape_cache.find_or_create(&text) |txt| {
|
||||||
let mut glyphs = GlyphStore::new(text.char_len(), is_whitespace);
|
let mut glyphs = GlyphStore::new(text.char_len(), is_whitespace);
|
||||||
shaper.shape_text(*txt, &mut glyphs);
|
shaper.shape_text(*txt, &mut glyphs);
|
||||||
ARC(glyphs)
|
Arc::new(glyphs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_descriptor(&self) -> FontDescriptor {
|
pub fn get_descriptor(&self) -> FontDescriptor {
|
||||||
FontDescriptor::new(copy self.style, SelectorPlatformIdentifier(self.handle.face_identifier()))
|
FontDescriptor::new(self.style.clone(), SelectorPlatformIdentifier(self.handle.face_identifier()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
|
pub fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
|
||||||
|
|
|
@ -14,7 +14,6 @@ use platform::font_context::FontContextHandle;
|
||||||
|
|
||||||
use azure::azure_hl::BackendType;
|
use azure::azure_hl::BackendType;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
// TODO(Rust #3934): creating lots of new dummy styles is a workaround
|
// TODO(Rust #3934): creating lots of new dummy styles is a workaround
|
||||||
// for not being able to store symbolic enums in top-level constants.
|
// for not being able to store symbolic enums in top-level constants.
|
||||||
|
@ -34,7 +33,6 @@ pub trait FontContextHandleMethods {
|
||||||
fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
|
fn create_font_from_identifier(&self, ~str, UsedFontStyle) -> Result<FontHandle, ()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
pub struct FontContext {
|
pub struct FontContext {
|
||||||
instance_cache: LRUCache<FontDescriptor, @mut Font>,
|
instance_cache: LRUCache<FontDescriptor, @mut Font>,
|
||||||
font_list: Option<FontList>, // only needed by layout
|
font_list: Option<FontList>, // only needed by layout
|
||||||
|
@ -45,7 +43,6 @@ pub struct FontContext {
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
impl<'self> FontContext {
|
impl<'self> FontContext {
|
||||||
pub fn new(backend: BackendType,
|
pub fn new(backend: BackendType,
|
||||||
needs_font_list: bool,
|
needs_font_list: bool,
|
||||||
|
@ -75,7 +72,7 @@ impl<'self> FontContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_font_list(&'self self) -> &'self FontList {
|
fn get_font_list(&'self self) -> &'self FontList {
|
||||||
self.font_list.get_ref()
|
self.font_list.get_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,23 +110,23 @@ impl<'self> FontContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn transform_family(&self, family: &str) -> ~str {
|
fn transform_family(&self, family: &str) -> ~str {
|
||||||
// FIXME: Need a find_like() in HashMap.
|
// 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) {
|
||||||
None => family,
|
None => family,
|
||||||
Some(mapped_family) => copy *mapped_family
|
Some(mapped_family) => (*mapped_family).clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn create_font_group(&mut self, style: &SpecifiedFontStyle) -> @FontGroup {
|
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 style.families.split_iter(',').advance |family| {
|
for family in style.families.split_iter(',') {
|
||||||
let family_name = family.trim();
|
let family_name = family.trim();
|
||||||
let transformed_family_name = self.transform_family(family_name);
|
let transformed_family_name = self.transform_family(family_name);
|
||||||
debug!("(create font group) transformed family is `%s`", transformed_family_name);
|
debug!("(create font group) transformed family is `%s`", transformed_family_name);
|
||||||
|
@ -139,16 +136,16 @@ impl<'self> FontContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for result.iter().advance |font_entry| {
|
for font_entry in result.iter() {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
let font_id =
|
let font_id =
|
||||||
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
||||||
let font_desc = FontDescriptor::new(copy *style, font_id);
|
let font_desc = FontDescriptor::new((*style).clone(), font_id);
|
||||||
|
|
||||||
let instance = self.get_font_by_descriptor(&font_desc);
|
let instance = self.get_font_by_descriptor(&font_desc);
|
||||||
|
|
||||||
do result::iter(&instance) |font: &@mut Font| { fonts.push(*font); }
|
for font in instance.iter() { fonts.push(*font); }
|
||||||
};
|
};
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
|
@ -158,19 +155,19 @@ impl<'self> FontContext {
|
||||||
|
|
||||||
let last_resort = FontList::get_last_resort_font_families();
|
let last_resort = FontList::get_last_resort_font_families();
|
||||||
|
|
||||||
for last_resort.iter().advance |family| {
|
for family in last_resort.iter() {
|
||||||
let result = do self.font_list.chain_ref |fl| {
|
let result = do self.font_list.chain_ref |fl| {
|
||||||
fl.find_font_in_family(*family, style)
|
fl.find_font_in_family(*family, style)
|
||||||
};
|
};
|
||||||
|
|
||||||
for result.iter().advance |font_entry| {
|
for font_entry in result.iter() {
|
||||||
let font_id =
|
let font_id =
|
||||||
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
SelectorPlatformIdentifier(font_entry.handle.face_identifier());
|
||||||
let font_desc = FontDescriptor::new(copy *style, font_id);
|
let font_desc = FontDescriptor::new((*style).clone(), font_id);
|
||||||
|
|
||||||
let instance = self.get_font_by_descriptor(&font_desc);
|
let instance = self.get_font_by_descriptor(&font_desc);
|
||||||
|
|
||||||
do result::iter(&instance) |font: &@mut Font| {
|
for font in instance.iter() {
|
||||||
fonts.push(*font);
|
fonts.push(*font);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,26 +175,26 @@ impl<'self> FontContext {
|
||||||
|
|
||||||
assert!(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 = (*style).clone();
|
||||||
|
|
||||||
debug!("(create font group) --- finished ---");
|
debug!("(create font group) --- finished ---");
|
||||||
|
|
||||||
@FontGroup::new(style.families.to_managed(), &used_style, fonts)
|
@FontGroup::new(style.families.to_managed(), &used_style, fonts)
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn create_font_instance(&self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
|
fn create_font_instance(&self, desc: &FontDescriptor) -> Result<@mut Font, ()> {
|
||||||
return match &desc.selector {
|
return match &desc.selector {
|
||||||
// TODO(Issue #174): implement by-platform-name font selectors.
|
// TODO(Issue #174): implement by-platform-name font selectors.
|
||||||
&SelectorPlatformIdentifier(ref identifier) => {
|
&SelectorPlatformIdentifier(ref identifier) => {
|
||||||
let result_handle = self.handle.create_font_from_identifier(copy *identifier,
|
let result_handle = self.handle.create_font_from_identifier((*identifier).clone(),
|
||||||
copy desc.style);
|
desc.style.clone());
|
||||||
result::chain(result_handle, |handle| {
|
do result_handle.chain |handle| {
|
||||||
Ok(Font::new_from_adopted_handle(self,
|
Ok(Font::new_from_adopted_handle(self,
|
||||||
handle,
|
handle,
|
||||||
&desc.style,
|
&desc.style,
|
||||||
self.backend,
|
self.backend,
|
||||||
self.profiler_chan.clone()))
|
self.profiler_chan.clone()))
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl FontList {
|
||||||
list
|
list
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn refresh(&mut self, _: &FontContextHandle) {
|
fn refresh(&mut self, _: &FontContextHandle) {
|
||||||
// TODO(Issue #186): don't refresh unless something actually
|
// TODO(Issue #186): don't refresh unless something actually
|
||||||
// changed. Does OSX have a notification for this event?
|
// changed. Does OSX have a notification for this event?
|
||||||
//
|
//
|
||||||
|
@ -61,7 +61,7 @@ impl FontList {
|
||||||
|
|
||||||
// if such family exists, try to match style to a font
|
// if such family exists, try to match style to a font
|
||||||
let mut result: Option<@FontEntry> = None;
|
let mut result: Option<@FontEntry> = None;
|
||||||
for family.iter().advance |fam| {
|
for fam in family.iter() {
|
||||||
result = fam.find_font_for_style(&self.handle, style);
|
result = fam.find_font_for_style(&self.handle, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ impl FontList {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn find_family(&self, family_name: &str) -> Option<@mut FontFamily> {
|
fn find_family(&self, family_name: &str) -> Option<@mut FontFamily> {
|
||||||
// look up canonical name
|
// look up canonical name
|
||||||
let family = self.family_map.find_equiv(&family_name);
|
let family = self.family_map.find_equiv(&family_name);
|
||||||
|
|
||||||
|
@ -125,8 +125,7 @@ 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.
|
||||||
let this: &mut FontFamily = self; // FIXME: borrow checker workaround
|
for entry in self.entries.iter() {
|
||||||
for this.entries.iter().advance |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()) {
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
extern mod azure;
|
extern mod azure;
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod http_client;
|
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod extra;
|
extern mod extra;
|
||||||
extern mod servo_net (name = "net");
|
extern mod servo_net (name = "net");
|
||||||
|
@ -36,7 +35,7 @@ pub use gfx_font_list = font_list;
|
||||||
pub use servo_gfx_font = font;
|
pub use servo_gfx_font = font;
|
||||||
pub use servo_gfx_font_list = font_list;
|
pub use servo_gfx_font_list = font_list;
|
||||||
|
|
||||||
priv mod render_context;
|
mod render_context;
|
||||||
|
|
||||||
// Rendering
|
// Rendering
|
||||||
pub mod color;
|
pub mod color;
|
||||||
|
|
|
@ -23,7 +23,6 @@ pub struct Opts {
|
||||||
output_file: Option<~str>,
|
output_file: Option<~str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
use extra::getopts;
|
use extra::getopts;
|
||||||
|
|
||||||
|
@ -40,13 +39,13 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
|
|
||||||
let opt_match = match getopts::getopts(args, opts) {
|
let opt_match = match getopts::getopts(args, opts) {
|
||||||
result::Ok(m) => m,
|
result::Ok(m) => m,
|
||||||
result::Err(f) => fail!(getopts::fail_str(copy f)),
|
result::Err(f) => fail!(getopts::fail_str(f.clone())),
|
||||||
};
|
};
|
||||||
|
|
||||||
let urls = if opt_match.free.is_empty() {
|
let urls = if opt_match.free.is_empty() {
|
||||||
fail!(~"servo asks that you provide 1 or more URLs")
|
fail!(~"servo asks that you provide 1 or more URLs")
|
||||||
} else {
|
} else {
|
||||||
copy opt_match.free
|
opt_match.free.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
let render_backend = match getopts::opt_maybe_str(&opt_match, "r") {
|
let render_backend = match getopts::opt_maybe_str(&opt_match, "r") {
|
||||||
|
@ -69,18 +68,18 @@ pub fn from_cmdline_args(args: &[~str]) -> Opts {
|
||||||
};
|
};
|
||||||
|
|
||||||
let tile_size: uint = match getopts::opt_maybe_str(&opt_match, "s") {
|
let tile_size: uint = match getopts::opt_maybe_str(&opt_match, "s") {
|
||||||
Some(tile_size_str) => uint::from_str(tile_size_str).get(),
|
Some(tile_size_str) => uint::from_str(tile_size_str).unwrap(),
|
||||||
None => 512,
|
None => 512,
|
||||||
};
|
};
|
||||||
|
|
||||||
let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, "t") {
|
let n_render_threads: uint = match getopts::opt_maybe_str(&opt_match, "t") {
|
||||||
Some(n_render_threads_str) => uint::from_str(n_render_threads_str).get(),
|
Some(n_render_threads_str) => uint::from_str(n_render_threads_str).unwrap(),
|
||||||
None => 1, // FIXME: Number of cores.
|
None => 1, // FIXME: Number of cores.
|
||||||
};
|
};
|
||||||
|
|
||||||
// if only flag is present, default to 5 second period
|
// if only flag is present, default to 5 second period
|
||||||
let profiler_period = do getopts::opt_default(&opt_match, "p", "5").map |period| {
|
let profiler_period = do getopts::opt_default(&opt_match, "p", "5").map |period| {
|
||||||
float::from_str(*period).get()
|
float::from_str(*period).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let exit_after_load = getopts::opt_present(&opt_match, "x");
|
let exit_after_load = getopts::opt_present(&opt_match, "x");
|
||||||
|
|
|
@ -73,7 +73,7 @@ impl Drop for FontHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontHandleMethods for FontHandle {
|
impl FontHandleMethods for FontHandle {
|
||||||
pub fn new_from_buffer(fctx: &FontContextHandle,
|
fn new_from_buffer(fctx: &FontContextHandle,
|
||||||
buf: ~[u8],
|
buf: ~[u8],
|
||||||
style: &SpecifiedFontStyle)
|
style: &SpecifiedFontStyle)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
|
@ -173,12 +173,12 @@ impl FontHandleMethods for FontHandle {
|
||||||
FontHandleMethods::new_from_buffer(fctx, buf.clone(), style)
|
FontHandleMethods::new_from_buffer(fctx, buf.clone(), style)
|
||||||
}
|
}
|
||||||
FontSourceFile(ref file) => {
|
FontSourceFile(ref file) => {
|
||||||
FontHandle::new_from_file(fctx, copy *file, style)
|
FontHandle::new_from_file(fctx, (*file).clone(), style)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_index(&self,
|
fn glyph_index(&self,
|
||||||
codepoint: char) -> Option<GlyphIndex> {
|
codepoint: char) -> Option<GlyphIndex> {
|
||||||
assert!(self.face.is_not_null());
|
assert!(self.face.is_not_null());
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -192,7 +192,7 @@ impl FontHandleMethods for FontHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyph_h_advance(&self,
|
fn glyph_h_advance(&self,
|
||||||
glyph: GlyphIndex) -> Option<FractionalPixel> {
|
glyph: GlyphIndex) -> Option<FractionalPixel> {
|
||||||
assert!(self.face.is_not_null());
|
assert!(self.face.is_not_null());
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -213,7 +213,7 @@ impl FontHandleMethods for FontHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_metrics(&self) -> FontMetrics {
|
fn get_metrics(&self) -> FontMetrics {
|
||||||
/* TODO(Issue #76): complete me */
|
/* TODO(Issue #76): complete me */
|
||||||
let face = self.get_face_rec();
|
let face = self.get_face_rec();
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ impl FontHandleMethods for FontHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> FontHandle {
|
impl<'self> FontHandle {
|
||||||
priv fn set_char_size(face: FT_Face, pt_size: float) -> Result<(), ()>{
|
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;
|
||||||
|
@ -262,7 +262,7 @@ impl<'self> FontHandle {
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
let face_index = 0 as FT_Long;
|
let face_index = 0 as FT_Long;
|
||||||
do str::as_c_str(file) |file_str| {
|
do file.to_c_str().with_ref |file_str| {
|
||||||
FT_New_Face(ft_ctx, file_str,
|
FT_New_Face(ft_ctx, file_str,
|
||||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ impl<'self> FontHandle {
|
||||||
|
|
||||||
let mut face: FT_Face = ptr::null();
|
let mut face: FT_Face = ptr::null();
|
||||||
let face_index = 0 as FT_Long;
|
let face_index = 0 as FT_Long;
|
||||||
do str::as_c_str(file) |file_str| {
|
do file.to_c_str().with_ref |file_str| {
|
||||||
FT_New_Face(ft_ctx, file_str,
|
FT_New_Face(ft_ctx, file_str,
|
||||||
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
face_index, ptr::to_mut_unsafe_ptr(&mut face));
|
||||||
}
|
}
|
||||||
|
@ -305,13 +305,13 @@ impl<'self> FontHandle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_face_rec(&'self self) -> &'self FT_FaceRec {
|
fn get_face_rec(&'self self) -> &'self FT_FaceRec {
|
||||||
unsafe {
|
unsafe {
|
||||||
&(*self.face)
|
&(*self.face)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn font_units_to_au(&self, value: float) -> Au {
|
fn font_units_to_au(&self, value: float) -> Au {
|
||||||
let face = self.get_face_rec();
|
let face = self.get_face_rec();
|
||||||
|
|
||||||
// face.size is a *c_void in the bindings, presumably to avoid
|
// face.size is a *c_void in the bindings, presumably to avoid
|
||||||
|
|
|
@ -26,10 +26,9 @@ use platform::font_context::FontContextHandle;
|
||||||
|
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::libc;
|
use std::libc;
|
||||||
use std::libc::c_int;
|
use std::libc::{c_int, c_char};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::uint;
|
|
||||||
|
|
||||||
pub struct FontListHandle {
|
pub struct FontListHandle {
|
||||||
fctx: FontContextHandle,
|
fctx: FontContextHandle,
|
||||||
|
@ -45,13 +44,13 @@ impl FontListHandle {
|
||||||
unsafe {
|
unsafe {
|
||||||
let config = FcConfigGetCurrent();
|
let config = FcConfigGetCurrent();
|
||||||
let fontSet = FcConfigGetFonts(config, FcSetSystem);
|
let fontSet = FcConfigGetFonts(config, FcSetSystem);
|
||||||
for uint::range(0, (*fontSet).nfont as uint) |i| {
|
for i in range(0, (*fontSet).nfont as int) {
|
||||||
let font = (*fontSet).fonts.offset(i);
|
let font = (*fontSet).fonts.offset(i);
|
||||||
let family: *FcChar8 = ptr::null();
|
let family: *FcChar8 = ptr::null();
|
||||||
let mut v: c_int = 0;
|
let mut v: c_int = 0;
|
||||||
do str::as_c_str("family") |FC_FAMILY| {
|
do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||||
while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
|
while FcPatternGetString(*font, FC_FAMILY, v, &family) == FcResultMatch {
|
||||||
let family_name = str::raw::from_buf(family as *u8);
|
let family_name = str::raw::from_c_str(family as *c_char);
|
||||||
debug!("Creating new FontFamily for family: %s", family_name);
|
debug!("Creating new FontFamily for family: %s", family_name);
|
||||||
let new_family = @mut 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);
|
||||||
|
@ -71,8 +70,8 @@ impl FontListHandle {
|
||||||
let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
|
let font_set_array_ptr = ptr::to_unsafe_ptr(&font_set);
|
||||||
let pattern = FcPatternCreate();
|
let pattern = FcPatternCreate();
|
||||||
assert!(pattern.is_not_null());
|
assert!(pattern.is_not_null());
|
||||||
do str::as_c_str("family") |FC_FAMILY| {
|
do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||||
do str::as_c_str(family.family_name) |family_name| {
|
do family.family_name.to_c_str().with_ref |family_name| {
|
||||||
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
|
let ok = FcPatternAddString(pattern, FC_FAMILY, family_name as *FcChar8);
|
||||||
assert!(ok != 0);
|
assert!(ok != 0);
|
||||||
}
|
}
|
||||||
|
@ -81,10 +80,10 @@ impl FontListHandle {
|
||||||
let object_set = FcObjectSetCreate();
|
let object_set = FcObjectSetCreate();
|
||||||
assert!(object_set.is_not_null());
|
assert!(object_set.is_not_null());
|
||||||
|
|
||||||
do str::as_c_str("file") |FC_FILE| {
|
do "file".to_c_str().with_ref |FC_FILE| {
|
||||||
FcObjectSetAdd(object_set, FC_FILE);
|
FcObjectSetAdd(object_set, FC_FILE);
|
||||||
}
|
}
|
||||||
do str::as_c_str("index") |FC_INDEX| {
|
do "index".to_c_str().with_ref |FC_INDEX| {
|
||||||
FcObjectSetAdd(object_set, FC_INDEX);
|
FcObjectSetAdd(object_set, FC_INDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +91,9 @@ impl FontListHandle {
|
||||||
|
|
||||||
debug!("found %? variations", (*matches).nfont);
|
debug!("found %? variations", (*matches).nfont);
|
||||||
|
|
||||||
for uint::range(0, (*matches).nfont as uint) |i| {
|
for i in range(0, (*matches).nfont as int) {
|
||||||
let font = (*matches).fonts.offset(i);
|
let font = (*matches).fonts.offset(i);
|
||||||
let file = do str::as_c_str("file") |FC_FILE| {
|
let file = do "file".to_c_str().with_ref |FC_FILE| {
|
||||||
let file: *FcChar8 = ptr::null();
|
let file: *FcChar8 = ptr::null();
|
||||||
if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch {
|
if FcPatternGetString(*font, FC_FILE, 0, &file) == FcResultMatch {
|
||||||
str::raw::from_c_str(file as *libc::c_char)
|
str::raw::from_c_str(file as *libc::c_char)
|
||||||
|
@ -102,7 +101,7 @@ impl FontListHandle {
|
||||||
fail!();
|
fail!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let index = do str::as_c_str("index") |FC_INDEX| {
|
let index = do "index".to_c_str().with_ref |FC_INDEX| {
|
||||||
let index: libc::c_int = 0;
|
let index: libc::c_int = 0;
|
||||||
if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch {
|
if FcPatternGetInteger(*font, FC_INDEX, 0, &index) == FcResultMatch {
|
||||||
index
|
index
|
||||||
|
@ -151,8 +150,8 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, (
|
||||||
let config = FcConfigGetCurrent();
|
let config = FcConfigGetCurrent();
|
||||||
let wrapper = AutoPattern { pattern: FcPatternCreate() };
|
let wrapper = AutoPattern { pattern: FcPatternCreate() };
|
||||||
let pattern = wrapper.pattern;
|
let pattern = wrapper.pattern;
|
||||||
let res = do str::as_c_str("family") |FC_FAMILY| {
|
let res = do "family".to_c_str().with_ref |FC_FAMILY| {
|
||||||
do str::as_c_str(name) |family| {
|
do name.to_c_str().with_ref |family| {
|
||||||
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
|
FcPatternAddString(pattern, FC_FAMILY, family as *FcChar8)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -162,7 +161,7 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, (
|
||||||
}
|
}
|
||||||
|
|
||||||
if style.italic {
|
if style.italic {
|
||||||
let res = do str::as_c_str("slant") |FC_SLANT| {
|
let res = do "slant".to_c_str().with_ref |FC_SLANT| {
|
||||||
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
|
FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC)
|
||||||
};
|
};
|
||||||
if res != 1 {
|
if res != 1 {
|
||||||
|
@ -171,7 +170,7 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if style.weight.is_bold() {
|
if style.weight.is_bold() {
|
||||||
let res = do str::as_c_str("weight") |FC_WEIGHT| {
|
let res = do "weight".to_c_str().with_ref |FC_WEIGHT| {
|
||||||
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
|
FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD)
|
||||||
};
|
};
|
||||||
if res != 1 {
|
if res != 1 {
|
||||||
|
@ -194,13 +193,13 @@ pub fn path_from_identifier(name: ~str, style: &UsedFontStyle) -> Result<~str, (
|
||||||
}
|
}
|
||||||
|
|
||||||
let file: *FcChar8 = ptr::null();
|
let file: *FcChar8 = ptr::null();
|
||||||
let res = do str::as_c_str("file") |FC_FILE| {
|
let res = do "file".to_c_str().with_ref |FC_FILE| {
|
||||||
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
|
FcPatternGetString(result_pattern, FC_FILE, 0, &file)
|
||||||
};
|
};
|
||||||
if res != FcResultMatch {
|
if res != FcResultMatch {
|
||||||
debug!("getting filename for font failed");
|
debug!("getting filename for font failed");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(str::raw::from_buf(file as *u8))
|
Ok(str::raw::from_c_str(file as *c_char))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,6 @@ use platform::macos::font::FontHandle;
|
||||||
|
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
use std::result;
|
|
||||||
|
|
||||||
pub struct FontContextHandle {
|
pub struct FontContextHandle {
|
||||||
ctx: ()
|
ctx: ()
|
||||||
}
|
}
|
||||||
|
@ -33,7 +31,7 @@ impl FontContextHandleMethods for FontContextHandle {
|
||||||
style: UsedFontStyle)
|
style: UsedFontStyle)
|
||||||
-> Result<FontHandle, ()> {
|
-> Result<FontHandle, ()> {
|
||||||
let ctfont_result = core_text::font::new_from_name(name, style.pt_size);
|
let ctfont_result = core_text::font::new_from_name(name, style.pt_size);
|
||||||
do result::chain(ctfont_result) |ctfont| {
|
do ctfont_result.chain |ctfont| {
|
||||||
FontHandle::new_from_CTFont(self, ctfont)
|
FontHandle::new_from_CTFont(self, ctfont)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,9 @@ use core_foundation::array::CFArray;
|
||||||
use core_foundation::base::CFWrapper;
|
use core_foundation::base::CFWrapper;
|
||||||
use core_foundation::string::{CFString, CFStringRef};
|
use core_foundation::string::{CFString, CFStringRef};
|
||||||
use core_text::font_collection::CTFontCollectionMethods;
|
use core_text::font_collection::CTFontCollectionMethods;
|
||||||
use core_text::font_descriptor::CTFontDescriptorRef;
|
|
||||||
use core_text;
|
use core_text;
|
||||||
|
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
pub struct FontListHandle {
|
pub struct FontListHandle {
|
||||||
fctx: FontContextHandle,
|
fctx: FontContextHandle,
|
||||||
|
@ -32,24 +30,25 @@ impl FontListHandle {
|
||||||
pub fn get_available_families(&self) -> FontFamilyMap {
|
pub fn get_available_families(&self) -> FontFamilyMap {
|
||||||
let family_names: CFArray<CFStringRef> = core_text::font_collection::get_family_names();
|
let family_names: CFArray<CFStringRef> = core_text::font_collection::get_family_names();
|
||||||
let mut family_map: FontFamilyMap = HashMap::new();
|
let mut family_map: FontFamilyMap = HashMap::new();
|
||||||
for family_names.each |&strref: &CFStringRef| {
|
for strref in family_names.iter() {
|
||||||
let family_name = CFString::wrap_shared(strref).to_str();
|
let family_name = CFString::wrap_shared(strref).to_str();
|
||||||
debug!("Creating new FontFamily for family: %s", family_name);
|
debug!("Creating new FontFamily for family: %s", family_name);
|
||||||
|
|
||||||
let new_family = @mut 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;
|
family_map
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_variations_for_family(&self, family: @mut FontFamily) {
|
pub fn load_variations_for_family(&self, family: @mut FontFamily) {
|
||||||
debug!("Looking for faces of family: %s", family.family_name);
|
debug!("Looking for faces of family: %s", family.family_name);
|
||||||
|
|
||||||
let family_collection = core_text::font_collection::create_for_family(family.family_name);
|
let family_collection = core_text::font_collection::create_for_family(family.family_name);
|
||||||
for family_collection.get_descriptors().each |descref: &CTFontDescriptorRef| {
|
let family_descriptors = family_collection.get_descriptors();
|
||||||
let desc = CFWrapper::wrap_shared(*descref);
|
for descref in family_descriptors.iter() {
|
||||||
|
let desc = CFWrapper::wrap_shared(descref);
|
||||||
let font = core_text::font::new_from_descriptor(&desc, 0.0);
|
let font = core_text::font::new_from_descriptor(&desc, 0.0);
|
||||||
let handle = result::unwrap(FontHandle::new_from_CTFont(&self.fctx, font));
|
let handle = FontHandle::new_from_CTFont(&self.fctx, font).unwrap();
|
||||||
|
|
||||||
debug!("Creating new FontEntry for face: %s", handle.face_name());
|
debug!("Creating new FontEntry for face: %s", handle.face_name());
|
||||||
let entry = @FontEntry::new(handle);
|
let entry = @FontEntry::new(handle);
|
||||||
|
|
|
@ -16,7 +16,7 @@ use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::side_offsets::SideOffsets2D;
|
use geom::side_offsets::SideOffsets2D;
|
||||||
use servo_net::image::base::Image;
|
use servo_net::image::base::Image;
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
pub struct RenderContext<'self> {
|
pub struct RenderContext<'self> {
|
||||||
canvas: &'self LayerBuffer,
|
canvas: &'self LayerBuffer,
|
||||||
|
@ -77,7 +77,7 @@ impl<'self> RenderContext<'self> {
|
||||||
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
|
self.canvas.draw_target.stroke_line(start, end, &pattern, &stroke_opts, &draw_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_image(&self, bounds: Rect<Au>, image: ARC<~Image>) {
|
pub fn draw_image(&self, bounds: Rect<Au>, image: Arc<~Image>) {
|
||||||
let image = image.get();
|
let image = image.get();
|
||||||
let size = Size2D(image.width as i32, image.height as i32);
|
let size = Size2D(image.width as i32, image.height as i32);
|
||||||
let stride = image.width * 4;
|
let stride = image.width * 4;
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub enum Msg {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
|
/// A request from the compositor to the renderer for tiles that need to be (re)displayed.
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct BufferRequest {
|
pub struct BufferRequest {
|
||||||
// The rect in pixels that will be drawn to the screen
|
// The rect in pixels that will be drawn to the screen
|
||||||
screen_rect: Rect<uint>,
|
screen_rect: Rect<uint>,
|
||||||
|
@ -70,7 +71,7 @@ impl RenderChan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv struct RenderTask<C> {
|
struct RenderTask<C> {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
port: Port<Msg>,
|
port: Port<Msg>,
|
||||||
compositor: C,
|
compositor: C,
|
||||||
|
@ -87,7 +88,7 @@ priv struct RenderTask<C> {
|
||||||
/// Permission to send paint messages to the compositor
|
/// Permission to send paint messages to the compositor
|
||||||
paint_permission: bool,
|
paint_permission: bool,
|
||||||
/// Cached copy of last layers rendered
|
/// Cached copy of last layers rendered
|
||||||
last_paint_msg: Option<(arc::ARC<LayerBufferSet>, Size2D<uint>)>,
|
last_paint_msg: Option<(arc::Arc<LayerBufferSet>, Size2D<uint>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: RenderListener + Send> RenderTask<C> {
|
impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
|
@ -112,7 +113,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
id: id,
|
id: id,
|
||||||
port: port.take(),
|
port: port.take(),
|
||||||
compositor: compositor,
|
compositor: compositor,
|
||||||
font_ctx: @mut FontContext::new(copy opts.render_backend,
|
font_ctx: @mut FontContext::new(opts.render_backend.clone(),
|
||||||
false,
|
false,
|
||||||
profiler_chan.clone()),
|
profiler_chan.clone()),
|
||||||
opts: opts,
|
opts: opts,
|
||||||
|
@ -179,7 +180,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
|
|
||||||
// Divide up the layer into tiles.
|
// Divide up the layer into tiles.
|
||||||
do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) {
|
do time::profile(time::RenderingPrepBuffCategory, self.profiler_chan.clone()) {
|
||||||
for tiles.iter().advance |tile| {
|
for tile in tiles.iter() {
|
||||||
let width = tile.screen_rect.size.width;
|
let width = tile.screen_rect.size.width;
|
||||||
let height = tile.screen_rect.size.height;
|
let height = tile.screen_rect.size.height;
|
||||||
|
|
||||||
|
@ -230,7 +231,7 @@ impl<C: RenderListener + Send> RenderTask<C> {
|
||||||
let layer_buffer_set = LayerBufferSet {
|
let layer_buffer_set = LayerBufferSet {
|
||||||
buffers: new_buffers,
|
buffers: new_buffers,
|
||||||
};
|
};
|
||||||
let layer_buffer_set = arc::ARC(layer_buffer_set);
|
let layer_buffer_set = arc::Arc::new(layer_buffer_set);
|
||||||
|
|
||||||
debug!("render_task: returning surface");
|
debug!("render_task: returning surface");
|
||||||
if self.paint_permission {
|
if self.paint_permission {
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub struct ImageSurface {
|
||||||
impl ImageSurface {
|
impl ImageSurface {
|
||||||
pub fn new(size: Size2D<int>, format: format) -> ImageSurface {
|
pub fn new(size: Size2D<int>, format: format) -> ImageSurface {
|
||||||
ImageSurface {
|
ImageSurface {
|
||||||
size: copy size,
|
size: size.clone(),
|
||||||
format: format,
|
format: format,
|
||||||
buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8)
|
buffer: vec::from_elem((size.area() as uint) * format.bpp(), 0u8)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ use std::cmp::{Ord, Eq};
|
||||||
use std::num::NumCast;
|
use std::num::NumCast;
|
||||||
use std::u16;
|
use std::u16;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::uint;
|
|
||||||
use std::util;
|
use std::util;
|
||||||
|
use std::iterator;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use extra::sort;
|
use extra::sort;
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ use extra::sort;
|
||||||
/// In the uncommon case (multiple glyphs per unicode character, large glyph index/advance, or
|
/// In the uncommon case (multiple glyphs per unicode character, large glyph index/advance, or
|
||||||
/// glyph offsets), we pack the glyph count into GlyphEntry, and store the other glyph information
|
/// glyph offsets), we pack the glyph count into GlyphEntry, and store the other glyph information
|
||||||
/// in DetailedGlyphStore.
|
/// in DetailedGlyphStore.
|
||||||
|
#[deriving(Clone)]
|
||||||
struct GlyphEntry {
|
struct GlyphEntry {
|
||||||
value: u32
|
value: u32
|
||||||
}
|
}
|
||||||
|
@ -256,6 +257,7 @@ impl GlyphEntry {
|
||||||
|
|
||||||
// Stores data for a detailed glyph, in the case that several glyphs
|
// Stores data for a detailed glyph, in the case that several glyphs
|
||||||
// correspond to one character, or the glyph's data couldn't be packed.
|
// correspond to one character, or the glyph's data couldn't be packed.
|
||||||
|
#[deriving(Clone)]
|
||||||
struct DetailedGlyph {
|
struct DetailedGlyph {
|
||||||
index: GlyphIndex,
|
index: GlyphIndex,
|
||||||
// glyph's advance, in the text's direction (RTL or RTL)
|
// glyph's advance, in the text's direction (RTL or RTL)
|
||||||
|
@ -274,7 +276,7 @@ impl DetailedGlyph {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq, Clone)]
|
||||||
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,
|
||||||
|
@ -459,7 +461,7 @@ enum GlyphInfo<'self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'self> GlyphInfo<'self> {
|
impl<'self> GlyphInfo<'self> {
|
||||||
fn index(self) -> GlyphIndex {
|
pub fn index(self) -> GlyphIndex {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].index(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].index(),
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
|
@ -470,7 +472,7 @@ impl<'self> GlyphInfo<'self> {
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
|
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
|
||||||
fn advance_(self) -> Au {
|
pub fn advance(self) -> Au {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].advance(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].advance(),
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
|
@ -479,7 +481,7 @@ impl<'self> GlyphInfo<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset(self) -> Option<Point2D<Au>> {
|
pub fn offset(self) -> Option<Point2D<Au>> {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(_, _) => None,
|
SimpleGlyphInfo(_, _) => None,
|
||||||
DetailGlyphInfo(store, entry_i, detail_j) => {
|
DetailGlyphInfo(store, entry_i, detail_j) => {
|
||||||
|
@ -488,14 +490,14 @@ impl<'self> GlyphInfo<'self> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ligature_start(self) -> bool {
|
pub fn is_ligature_start(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_ligature_start(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_ligature_start(),
|
||||||
DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_ligature_start()
|
DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_ligature_start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cluster_start(self) -> bool {
|
pub fn is_cluster_start(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_cluster_start(),
|
SimpleGlyphInfo(store, entry_i) => store.entry_buffer[entry_i].is_cluster_start(),
|
||||||
DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_cluster_start()
|
DetailGlyphInfo(store, entry_i, _) => store.entry_buffer[entry_i].is_cluster_start()
|
||||||
|
@ -597,64 +599,26 @@ impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry;
|
self.entry_buffer[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_glyphs_for_char_index(&'self self,
|
pub fn iter_glyphs_for_char_index(&'self self, i: uint) -> GlyphIterator<'self> {
|
||||||
i: uint,
|
self.iter_glyphs_for_char_range(&Range::new(i, 1))
|
||||||
cb: &fn(uint, &GlyphInfo<'self>) -> bool)
|
|
||||||
-> bool {
|
|
||||||
assert!(i < self.entry_buffer.len());
|
|
||||||
|
|
||||||
let entry = &self.entry_buffer[i];
|
|
||||||
match entry.is_simple() {
|
|
||||||
true => {
|
|
||||||
let proxy = &SimpleGlyphInfo(self, i);
|
|
||||||
cb(i, proxy);
|
|
||||||
},
|
|
||||||
false => {
|
|
||||||
let glyphs = self.detail_store.get_detailed_glyphs_for_entry(i,
|
|
||||||
entry.glyph_count());
|
|
||||||
for uint::range(0, glyphs.len()) |j| {
|
|
||||||
let proxy = &DetailGlyphInfo(self, i, j as u16);
|
|
||||||
cb(i, proxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_glyphs_for_char_range(&'self self,
|
pub fn iter_glyphs_for_char_range(&'self self, rang: &Range) -> GlyphIterator<'self> {
|
||||||
range: &Range,
|
if rang.begin() >= self.entry_buffer.len() {
|
||||||
callback: &fn(uint, &GlyphInfo<'self>) -> bool)
|
fail!("iter_glyphs_for_range: range.begin beyond length!");
|
||||||
-> bool {
|
|
||||||
if range.begin() >= self.entry_buffer.len() {
|
|
||||||
error!("iter_glyphs_for_range: range.begin beyond length!");
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
if range.end() > self.entry_buffer.len() {
|
if rang.end() > self.entry_buffer.len() {
|
||||||
error!("iter_glyphs_for_range: range.end beyond length!");
|
fail!("iter_glyphs_for_range: range.end beyond length!");
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for range.eachi |i| {
|
GlyphIterator {
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
store: self,
|
||||||
if !self.iter_glyphs_for_char_index(i, |a, b| callback(a, b)) {
|
char_index: rang.begin(),
|
||||||
break
|
char_range: rang.eachi(),
|
||||||
|
glyph_range: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_all_glyphs(&'self self, callback: &fn(uint, &GlyphInfo<'self>) -> bool) -> bool {
|
|
||||||
for uint::range(0, self.entry_buffer.len()) |i| {
|
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
|
||||||
if !self.iter_glyphs_for_char_index(i, |a, b| callback(a, b)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
// getter methods
|
// getter methods
|
||||||
pub fn char_is_space(&self, i: uint) -> bool {
|
pub fn char_is_space(&self, i: uint) -> bool {
|
||||||
assert!(i < self.entry_buffer.len());
|
assert!(i < self.entry_buffer.len());
|
||||||
|
@ -711,3 +675,49 @@ impl<'self> GlyphStore {
|
||||||
self.entry_buffer[i] = entry.set_can_break_before(t);
|
self.entry_buffer[i] = entry.set_can_break_before(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GlyphIterator<'self> {
|
||||||
|
priv store: &'self GlyphStore,
|
||||||
|
priv char_index: uint,
|
||||||
|
priv char_range: iterator::Range<uint>,
|
||||||
|
priv glyph_range: Option<iterator::Range<uint>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<(uint, GlyphInfo<'self>)> for GlyphIterator<'self> {
|
||||||
|
// I tried to start with something simpler and apply FlatMap, but the
|
||||||
|
// inability to store free variables in the FlatMap struct was problematic.
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<(uint, GlyphInfo<'self>)> {
|
||||||
|
// Would use 'match' here but it borrows contents in a way that
|
||||||
|
// interferes with mutation.
|
||||||
|
if self.glyph_range.is_some() {
|
||||||
|
match self.glyph_range.unwrap().next() {
|
||||||
|
Some(j) => Some((self.char_index,
|
||||||
|
DetailGlyphInfo(self.store, self.char_index, j as u16))),
|
||||||
|
None => {
|
||||||
|
// No more glyphs for current character. Try to get another.
|
||||||
|
self.glyph_range = None;
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No glyph range. Look at next character.
|
||||||
|
match self.char_range.next() {
|
||||||
|
Some(i) => {
|
||||||
|
self.char_index = i;
|
||||||
|
assert!(i < self.store.entry_buffer.len());
|
||||||
|
let entry = &self.store.entry_buffer[i];
|
||||||
|
if entry.is_simple() {
|
||||||
|
Some((self.char_index, SimpleGlyphInfo(self.store, i)))
|
||||||
|
} else {
|
||||||
|
let glyphs = self.store.detail_store
|
||||||
|
.get_detailed_glyphs_for_entry(i, entry.glyph_count());
|
||||||
|
self.glyph_range = Some(range(0, glyphs.len()));
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use std::cast::transmute;
|
||||||
use std::libc::{c_uint, c_int, c_void, c_char};
|
use std::libc::{c_uint, c_int, c_void, c_char};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
use std::str;
|
|
||||||
use std::uint;
|
use std::uint;
|
||||||
use std::util::ignore;
|
use std::util::ignore;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
@ -86,7 +85,7 @@ impl ShapedGlyphData {
|
||||||
fn byte_offset_of_glyph(&self, i: uint) -> uint {
|
fn byte_offset_of_glyph(&self, i: uint) -> uint {
|
||||||
assert!(i < self.count);
|
assert!(i < self.count);
|
||||||
|
|
||||||
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
let glyph_info_i = ptr::offset(self.glyph_infos, i as int);
|
||||||
unsafe {
|
unsafe {
|
||||||
(*glyph_info_i).cluster as uint
|
(*glyph_info_i).cluster as uint
|
||||||
}
|
}
|
||||||
|
@ -101,8 +100,8 @@ impl ShapedGlyphData {
|
||||||
assert!(i < self.count);
|
assert!(i < self.count);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let glyph_info_i = ptr::offset(self.glyph_infos, i);
|
let glyph_info_i = ptr::offset(self.glyph_infos, i as int);
|
||||||
let pos_info_i = ptr::offset(self.pos_infos, i);
|
let pos_info_i = ptr::offset(self.pos_infos, i as int);
|
||||||
let x_offset = Shaper::fixed_to_float((*pos_info_i).x_offset);
|
let x_offset = Shaper::fixed_to_float((*pos_info_i).x_offset);
|
||||||
let y_offset = Shaper::fixed_to_float((*pos_info_i).y_offset);
|
let y_offset = Shaper::fixed_to_float((*pos_info_i).y_offset);
|
||||||
let x_advance = Shaper::fixed_to_float((*pos_info_i).x_advance);
|
let x_advance = Shaper::fixed_to_float((*pos_info_i).x_advance);
|
||||||
|
@ -216,8 +215,8 @@ impl ShaperMethods for Shaper {
|
||||||
let hb_buffer: *hb_buffer_t = hb_buffer_create();
|
let hb_buffer: *hb_buffer_t = hb_buffer_create();
|
||||||
hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);
|
hb_buffer_set_direction(hb_buffer, HB_DIRECTION_LTR);
|
||||||
|
|
||||||
// Using as_buf because it never does a copy - we don't need the trailing null
|
// Using as_imm_buf because it never does a copy - we don't need the trailing null
|
||||||
do str::as_buf(text) |ctext: *u8, _: uint| {
|
do text.as_imm_buf |ctext: *u8, _: uint| {
|
||||||
hb_buffer_add_utf8(hb_buffer,
|
hb_buffer_add_utf8(hb_buffer,
|
||||||
ctext as *c_char,
|
ctext as *c_char,
|
||||||
text.len() as c_int,
|
text.len() as c_int,
|
||||||
|
@ -272,7 +271,7 @@ impl Shaper {
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("(glyph idx) -> (text byte offset)");
|
debug!("(glyph idx) -> (text byte offset)");
|
||||||
for uint::range(0, glyph_data.len()) |i| {
|
for i in range(0, glyph_data.len()) {
|
||||||
// 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 {
|
||||||
|
@ -335,7 +334,7 @@ impl Shaper {
|
||||||
// extend glyph range to max glyph index covered by char_span,
|
// extend glyph range to max glyph index covered by char_span,
|
||||||
// in cases where one char made several glyphs and left some unassociated chars.
|
// in cases where one char made several glyphs and left some unassociated chars.
|
||||||
let mut max_glyph_idx = glyph_span.end();
|
let mut max_glyph_idx = glyph_span.end();
|
||||||
for char_byte_span.eachi |i| {
|
for i in char_byte_span.eachi() {
|
||||||
if byteToGlyph[i] > NO_GLYPH {
|
if byteToGlyph[i] > NO_GLYPH {
|
||||||
max_glyph_idx = uint::max(byteToGlyph[i] as uint, max_glyph_idx);
|
max_glyph_idx = uint::max(byteToGlyph[i] as uint, max_glyph_idx);
|
||||||
}
|
}
|
||||||
|
@ -359,7 +358,7 @@ impl Shaper {
|
||||||
probably doesn't work.");
|
probably doesn't work.");
|
||||||
|
|
||||||
let mut all_glyphs_are_within_cluster: bool = true;
|
let mut all_glyphs_are_within_cluster: bool = true;
|
||||||
for glyph_span.eachi |j| {
|
for j in glyph_span.eachi() {
|
||||||
let loc = glyph_data.byte_offset_of_glyph(j);
|
let loc = glyph_data.byte_offset_of_glyph(j);
|
||||||
if !char_byte_span.contains(loc) {
|
if !char_byte_span.contains(loc) {
|
||||||
all_glyphs_are_within_cluster = false;
|
all_glyphs_are_within_cluster = false;
|
||||||
|
@ -398,7 +397,7 @@ impl Shaper {
|
||||||
// cspan: [-]
|
// cspan: [-]
|
||||||
// covsp: [---------------]
|
// covsp: [---------------]
|
||||||
|
|
||||||
let mut covered_byte_span = copy char_byte_span;
|
let mut covered_byte_span = char_byte_span.clone();
|
||||||
// extend, clipping at end of text range.
|
// extend, clipping at end of text range.
|
||||||
while covered_byte_span.end() < byte_max
|
while covered_byte_span.end() < byte_max
|
||||||
&& byteToGlyph[covered_byte_span.end()] == NO_GLYPH {
|
&& byteToGlyph[covered_byte_span.end()] == NO_GLYPH {
|
||||||
|
@ -438,7 +437,7 @@ impl Shaper {
|
||||||
// collect all glyphs to be assigned to the first character.
|
// collect all glyphs to be assigned to the first character.
|
||||||
let mut datas = ~[];
|
let mut datas = ~[];
|
||||||
|
|
||||||
for glyph_span.eachi |glyph_i| {
|
for glyph_i in glyph_span.eachi() {
|
||||||
let shape = glyph_data.get_entry_for_glyph(glyph_i, &mut y_pos);
|
let shape = glyph_data.get_entry_for_glyph(glyph_i, &mut y_pos);
|
||||||
datas.push(GlyphData::new(shape.codepoint,
|
datas.push(GlyphData::new(shape.codepoint,
|
||||||
shape.advance,
|
shape.advance,
|
||||||
|
|
|
@ -2,27 +2,29 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use std::vec::VecIterator;
|
||||||
|
|
||||||
use font_context::FontContext;
|
use font_context::FontContext;
|
||||||
use geometry::Au;
|
use geometry::Au;
|
||||||
use text::glyph::GlyphStore;
|
use text::glyph::GlyphStore;
|
||||||
use font::{Font, FontDescriptor, RunMetrics};
|
use font::{Font, FontDescriptor, RunMetrics};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
/// A text run.
|
/// A text run.
|
||||||
pub struct TextRun {
|
pub struct TextRun {
|
||||||
text: ~str,
|
text: ~str,
|
||||||
font: @mut Font,
|
font: @mut Font,
|
||||||
underline: bool,
|
underline: bool,
|
||||||
glyphs: ~[ARC<GlyphStore>],
|
glyphs: ~[Arc<GlyphStore>],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a hack until TextRuns are normally sendable, or we instead use ARC<TextRun> everywhere.
|
/// This is a hack until TextRuns are normally sendable, or we instead use Arc<TextRun> everywhere.
|
||||||
pub struct SendableTextRun {
|
pub struct SendableTextRun {
|
||||||
text: ~str,
|
text: ~str,
|
||||||
font: FontDescriptor,
|
font: FontDescriptor,
|
||||||
underline: bool,
|
underline: bool,
|
||||||
priv glyphs: ~[ARC<GlyphStore>],
|
priv glyphs: ~[Arc<GlyphStore>],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SendableTextRun {
|
impl SendableTextRun {
|
||||||
|
@ -33,7 +35,7 @@ impl SendableTextRun {
|
||||||
};
|
};
|
||||||
|
|
||||||
TextRun {
|
TextRun {
|
||||||
text: copy self.text,
|
text: self.text.clone(),
|
||||||
font: font,
|
font: font,
|
||||||
underline: self.underline,
|
underline: self.underline,
|
||||||
glyphs: self.glyphs.clone(),
|
glyphs: self.glyphs.clone(),
|
||||||
|
@ -41,6 +43,78 @@ impl SendableTextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SliceIterator<'self> {
|
||||||
|
priv glyph_iter: VecIterator<'self, Arc<GlyphStore>>,
|
||||||
|
priv range: Range,
|
||||||
|
priv offset: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<(&'self GlyphStore, uint, Range)> for SliceIterator<'self> {
|
||||||
|
fn next(&mut self) -> Option<(&'self GlyphStore, uint, Range)> {
|
||||||
|
loop {
|
||||||
|
let slice_glyphs = self.glyph_iter.next();
|
||||||
|
if slice_glyphs.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let slice_glyphs = slice_glyphs.unwrap().get();
|
||||||
|
|
||||||
|
let slice_range = Range::new(self.offset, slice_glyphs.char_len());
|
||||||
|
let mut char_range = self.range.intersect(&slice_range);
|
||||||
|
char_range.shift_by(-(self.offset.to_int()));
|
||||||
|
|
||||||
|
let old_offset = self.offset;
|
||||||
|
self.offset += slice_glyphs.char_len();
|
||||||
|
if !char_range.is_empty() {
|
||||||
|
return Some((slice_glyphs, old_offset, char_range))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LineIterator<'self> {
|
||||||
|
priv range: Range,
|
||||||
|
priv clump: Option<Range>,
|
||||||
|
priv slices: SliceIterator<'self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'self> Iterator<Range> for LineIterator<'self> {
|
||||||
|
fn next(&mut self) -> Option<Range> {
|
||||||
|
// Loop until we hit whitespace and are in a clump.
|
||||||
|
loop {
|
||||||
|
match self.slices.next() {
|
||||||
|
Some((glyphs, offset, slice_range)) => {
|
||||||
|
match (glyphs.is_whitespace(), self.clump) {
|
||||||
|
(false, Some(ref mut c)) => {
|
||||||
|
c.extend_by(slice_range.length().to_int());
|
||||||
|
}
|
||||||
|
(false, None) => {
|
||||||
|
let mut c = slice_range;
|
||||||
|
c.shift_by(offset.to_int());
|
||||||
|
self.clump = Some(c);
|
||||||
|
}
|
||||||
|
(true, None) => { /* chomp whitespace */ }
|
||||||
|
(true, Some(c)) => {
|
||||||
|
self.clump = None;
|
||||||
|
// The final whitespace clump is not included.
|
||||||
|
return Some(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
// flush any remaining chars as a line
|
||||||
|
if self.clump.is_some() {
|
||||||
|
let mut c = self.clump.take_unwrap();
|
||||||
|
c.extend_to(self.range.end());
|
||||||
|
return Some(c);
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'self> TextRun {
|
impl<'self> TextRun {
|
||||||
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
pub fn new(font: @mut Font, text: ~str, underline: bool) -> TextRun {
|
||||||
let glyphs = TextRun::break_and_shape(font, text);
|
let glyphs = TextRun::break_and_shape(font, text);
|
||||||
|
@ -58,7 +132,7 @@ impl<'self> TextRun {
|
||||||
self.font.teardown();
|
self.font.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn break_and_shape(font: @mut Font, text: &str) -> ~[ARC<GlyphStore>] {
|
pub fn break_and_shape(font: @mut Font, text: &str) -> ~[Arc<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 glyphs = ~[];
|
let mut glyphs = ~[];
|
||||||
|
@ -115,7 +189,7 @@ impl<'self> TextRun {
|
||||||
|
|
||||||
pub fn serialize(&self) -> SendableTextRun {
|
pub fn serialize(&self) -> SendableTextRun {
|
||||||
SendableTextRun {
|
SendableTextRun {
|
||||||
text: copy self.text,
|
text: self.text.clone(),
|
||||||
font: self.font.get_descriptor(),
|
font: self.font.get_descriptor(),
|
||||||
underline: self.underline,
|
underline: self.underline,
|
||||||
glyphs: self.glyphs.clone(),
|
glyphs: self.glyphs.clone(),
|
||||||
|
@ -128,10 +202,10 @@ impl<'self> TextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glyphs(&'self self) -> &'self ~[ARC<GlyphStore>] { &self.glyphs }
|
pub fn glyphs(&'self self) -> &'self ~[Arc<GlyphStore>] { &self.glyphs }
|
||||||
|
|
||||||
pub fn range_is_trimmable_whitespace(&self, range: &Range) -> bool {
|
pub fn range_is_trimmable_whitespace(&self, range: &Range) -> bool {
|
||||||
for self.iter_slices_for_range(range) |slice_glyphs, _, _| {
|
for (slice_glyphs, _, _) in self.iter_slices_for_range(range) {
|
||||||
if !slice_glyphs.is_whitespace() { return false; }
|
if !slice_glyphs.is_whitespace() { return false; }
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
@ -148,61 +222,27 @@ impl<'self> TextRun {
|
||||||
pub fn min_width_for_range(&self, range: &Range) -> Au {
|
pub fn min_width_for_range(&self, range: &Range) -> Au {
|
||||||
let mut max_piece_width = Au(0);
|
let mut max_piece_width = Au(0);
|
||||||
debug!("iterating outer range %?", range);
|
debug!("iterating outer range %?", range);
|
||||||
for self.iter_slices_for_range(range) |glyphs, offset, slice_range| {
|
for (glyphs, offset, slice_range) in self.iter_slices_for_range(range) {
|
||||||
debug!("iterated on %?[%?]", offset, slice_range);
|
debug!("iterated on %?[%?]", offset, slice_range);
|
||||||
let metrics = self.font.measure_text_for_slice(glyphs, slice_range);
|
let metrics = self.font.measure_text_for_slice(glyphs, &slice_range);
|
||||||
max_piece_width = Au::max(max_piece_width, metrics.advance_width);
|
max_piece_width = Au::max(max_piece_width, metrics.advance_width);
|
||||||
}
|
}
|
||||||
max_piece_width
|
max_piece_width
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_slices_for_range(&self,
|
pub fn iter_slices_for_range(&'self self, range: &Range) -> SliceIterator<'self> {
|
||||||
range: &Range,
|
SliceIterator {
|
||||||
f: &fn(&GlyphStore, uint, &Range) -> bool)
|
glyph_iter: self.glyphs.iter(),
|
||||||
-> bool {
|
range: *range,
|
||||||
let mut offset = 0;
|
offset: 0,
|
||||||
for self.glyphs.iter().advance |slice_glyphs| {
|
|
||||||
// Determine the range of this slice that we need.
|
|
||||||
let slice_range = Range::new(offset, slice_glyphs.get().char_len());
|
|
||||||
let mut char_range = range.intersect(&slice_range);
|
|
||||||
char_range.shift_by(-(offset.to_int()));
|
|
||||||
|
|
||||||
let unwrapped_glyphs = slice_glyphs.get();
|
|
||||||
if !char_range.is_empty() {
|
|
||||||
if !f(unwrapped_glyphs, offset, &char_range) { break }
|
|
||||||
}
|
|
||||||
offset += unwrapped_glyphs.char_len();
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_natural_lines_for_range(&self, range: &Range, f: &fn(&Range) -> bool) -> bool {
|
|
||||||
let mut clump = Range::new(range.begin(), 0);
|
|
||||||
let mut in_clump = false;
|
|
||||||
|
|
||||||
for self.iter_slices_for_range(range) |glyphs, offset, slice_range| {
|
|
||||||
match (glyphs.is_whitespace(), in_clump) {
|
|
||||||
(false, true) => { clump.extend_by(slice_range.length().to_int()); }
|
|
||||||
(false, false) => {
|
|
||||||
in_clump = true;
|
|
||||||
clump = *slice_range;
|
|
||||||
clump.shift_by(offset.to_int());
|
|
||||||
}
|
|
||||||
(true, false) => { /* chomp whitespace */ }
|
|
||||||
(true, true) => {
|
|
||||||
in_clump = false;
|
|
||||||
// The final whitespace clump is not included.
|
|
||||||
if !f(&clump) { break }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush any remaining chars as a line
|
pub fn iter_natural_lines_for_range(&'self self, range: &Range) -> LineIterator<'self> {
|
||||||
if in_clump {
|
LineIterator {
|
||||||
clump.extend_to(range.end());
|
range: *range,
|
||||||
f(&clump);
|
clump: None,
|
||||||
}
|
slices: self.iter_slices_for_range(range),
|
||||||
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
let mut out_str: ~str = ~"";
|
let mut out_str: ~str = ~"";
|
||||||
let out_whitespace = match mode {
|
let out_whitespace = match mode {
|
||||||
CompressNone | DiscardNewline => {
|
CompressNone | DiscardNewline => {
|
||||||
for text.iter().advance |ch: char| {
|
for ch in text.iter() {
|
||||||
if is_discardable_char(ch, mode) {
|
if is_discardable_char(ch, mode) {
|
||||||
// TODO: record skipped char
|
// TODO: record skipped char
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,7 +40,7 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
|
||||||
|
|
||||||
CompressWhitespace | CompressWhitespaceNewline => {
|
CompressWhitespace | CompressWhitespaceNewline => {
|
||||||
let mut in_whitespace: bool = incoming_whitespace;
|
let mut in_whitespace: bool = incoming_whitespace;
|
||||||
for text.iter().advance |ch: char| {
|
for ch in text.iter() {
|
||||||
// TODO: discard newlines between CJK chars
|
// TODO: discard newlines between CJK chars
|
||||||
let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);
|
let mut next_in_whitespace: bool = is_in_whitespace(ch, mode);
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ fn test_transform_compress_none() {
|
||||||
~"foobarbaz\n\n"];
|
~"foobarbaz\n\n"];
|
||||||
let mode = CompressNone;
|
let mode = CompressNone;
|
||||||
|
|
||||||
for uint::range(0, test_strs.len()) |i| {
|
for i in range(0, test_strs.len()) {
|
||||||
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
||||||
assert!(trimmed_str == test_strs[i])
|
assert!(trimmed_str == test_strs[i])
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ fn test_transform_discard_newline() {
|
||||||
assert!(test_strs.len() == oracle_strs.len());
|
assert!(test_strs.len() == oracle_strs.len());
|
||||||
let mode = DiscardNewline;
|
let mode = DiscardNewline;
|
||||||
|
|
||||||
for uint::range(0, test_strs.len()) |i| {
|
for i in range(0, test_strs.len()) {
|
||||||
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
||||||
assert!(trimmed_str == oracle_strs[i])
|
assert!(trimmed_str == oracle_strs[i])
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ fn test_transform_compress_whitespace() {
|
||||||
assert!(test_strs.len() == oracle_strs.len());
|
assert!(test_strs.len() == oracle_strs.len());
|
||||||
let mode = CompressWhitespace;
|
let mode = CompressWhitespace;
|
||||||
|
|
||||||
for uint::range(0, test_strs.len()) |i| {
|
for i in range(0, test_strs.len()) {
|
||||||
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
||||||
assert!(trimmed_str == oracle_strs[i])
|
assert!(trimmed_str == oracle_strs[i])
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ fn test_transform_compress_whitespace_newline() {
|
||||||
assert!(test_strs.len() == oracle_strs.len());
|
assert!(test_strs.len() == oracle_strs.len());
|
||||||
let mode = CompressWhitespaceNewline;
|
let mode = CompressWhitespaceNewline;
|
||||||
|
|
||||||
for uint::range(0, test_strs.len()) |i| {
|
for i in range(0, test_strs.len()) {
|
||||||
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
(trimmed_str, _out) = transform_text(test_strs[i], mode, true);
|
||||||
assert!(trimmed_str == oracle_strs[i])
|
assert!(trimmed_str == oracle_strs[i])
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ fn test_transform_compress_whitespace_newline() {
|
||||||
assert!(test_strs.len() == oracle_strs.len());
|
assert!(test_strs.len() == oracle_strs.len());
|
||||||
let mode = CompressWhitespaceNewline;
|
let mode = CompressWhitespaceNewline;
|
||||||
|
|
||||||
for uint::range(0, test_strs.len()) |i| {
|
for i in range(0, test_strs.len()) {
|
||||||
(trimmed_str, _out) = transform_text(test_strs[i], mode, false);
|
(trimmed_str, _out) = transform_text(test_strs[i], mode, false);
|
||||||
assert!(trimmed_str == oracle_strs[i])
|
assert!(trimmed_str == oracle_strs[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl CompositorLayer {
|
||||||
// true; otherwise returns false, so a parent layer can scroll instead.
|
// true; otherwise returns false, so a parent layer can scroll instead.
|
||||||
pub fn scroll(&mut self, delta: Point2D<f32>, cursor: Point2D<f32>, window_size: Size2D<f32>) -> bool {
|
pub fn scroll(&mut self, delta: Point2D<f32>, cursor: Point2D<f32>, window_size: Size2D<f32>) -> bool {
|
||||||
let cursor = cursor - self.scroll_offset;
|
let cursor = cursor - self.scroll_offset;
|
||||||
for self.children.mut_iter().filter(|x| !x.child.hidden).advance |child| {
|
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
|
||||||
match child.container.scissor {
|
match child.container.scissor {
|
||||||
None => {
|
None => {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
|
@ -131,7 +131,7 @@ impl CompositorLayer {
|
||||||
// page coordinates.
|
// page coordinates.
|
||||||
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
|
pub fn send_mouse_event(&self, event: MouseWindowEvent, cursor: Point2D<f32>) {
|
||||||
let cursor = cursor - self.scroll_offset;
|
let cursor = cursor - self.scroll_offset;
|
||||||
for self.children.iter().filter(|&x| !x.child.hidden).advance |child| {
|
for child in self.children.iter().filter(|&x| !x.child.hidden) {
|
||||||
match child.container.scissor {
|
match child.container.scissor {
|
||||||
None => {
|
None => {
|
||||||
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
error!("CompositorLayer: unable to perform cursor hit test for layer");
|
||||||
|
@ -197,7 +197,7 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.children.mut_iter().filter(|x| !x.child.hidden)
|
self.children.mut_iter().filter(|x| !x.child.hidden)
|
||||||
.transform(transform)
|
.map(transform)
|
||||||
.fold(false, |a, b| a || b) || redisplay
|
.fold(false, |a, b| a || b) || redisplay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ impl CompositorLayer {
|
||||||
// and clip the layer to the specified size in page coordinates.
|
// and clip the layer to the specified size in page coordinates.
|
||||||
// This method returns false if the specified layer is not found.
|
// This method returns false if the specified layer is not found.
|
||||||
pub fn set_clipping_rect(&mut self, pipeline_id: PipelineId, new_rect: Rect<f32>) -> bool {
|
pub fn set_clipping_rect(&mut self, pipeline_id: PipelineId, new_rect: Rect<f32>) -> bool {
|
||||||
for self.children.iter().advance |child_node| {
|
for child_node in self.children.iter() {
|
||||||
if pipeline_id != child_node.child.pipeline.id {
|
if pipeline_id != child_node.child.pipeline.id {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID does not match any of our immediate children, so recurse on descendents (including hidden children)
|
// ID does not match any of our immediate children, so recurse on descendents (including hidden children)
|
||||||
self.children.mut_iter().transform(|x| &mut x.child).any(|x| x.set_clipping_rect(pipeline_id, new_rect))
|
self.children.mut_iter().map(|x| &mut x.child).any(|x| x.set_clipping_rect(pipeline_id, new_rect))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,15 +265,15 @@ impl CompositorLayer {
|
||||||
|
|
||||||
// Delete old layer.
|
// Delete old layer.
|
||||||
while current_layer_child.is_some() {
|
while current_layer_child.is_some() {
|
||||||
let trash = current_layer_child.get();
|
let trash = current_layer_child.unwrap();
|
||||||
do current_layer_child.get().with_common |common| {
|
do current_layer_child.unwrap().with_common |common| {
|
||||||
current_layer_child = common.next_sibling;
|
current_layer_child = common.next_sibling;
|
||||||
}
|
}
|
||||||
self.root_layer.remove_child(trash);
|
self.root_layer.remove_child(trash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add child layers.
|
// Add child layers.
|
||||||
for self.children.mut_iter().filter(|x| !x.child.hidden).advance |child| {
|
for child in self.children.mut_iter().filter(|x| !x.child.hidden) {
|
||||||
current_layer_child = match current_layer_child {
|
current_layer_child = match current_layer_child {
|
||||||
None => {
|
None => {
|
||||||
child.container.common.parent = None;
|
child.container.common.parent = None;
|
||||||
|
@ -295,7 +295,7 @@ impl CompositorLayer {
|
||||||
};
|
};
|
||||||
|
|
||||||
let all_tiles = quadtree.get_all_tiles();
|
let all_tiles = quadtree.get_all_tiles();
|
||||||
for all_tiles.iter().advance |buffer| {
|
for buffer in all_tiles.iter() {
|
||||||
debug!("osmain: compositing buffer rect %?", &buffer.rect);
|
debug!("osmain: compositing buffer rect %?", &buffer.rect);
|
||||||
|
|
||||||
// Find or create a texture layer.
|
// Find or create a texture layer.
|
||||||
|
@ -313,7 +313,7 @@ impl CompositorLayer {
|
||||||
texture_layer.manager = @buffer.draw_target.clone() as @TextureManager;
|
texture_layer.manager = @buffer.draw_target.clone() as @TextureManager;
|
||||||
|
|
||||||
// Move on to the next sibling.
|
// Move on to the next sibling.
|
||||||
do current_layer_child.get().with_common |common| {
|
do current_layer_child.unwrap().with_common |common| {
|
||||||
common.next_sibling
|
common.next_sibling
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ impl CompositorLayer {
|
||||||
Tree(ref mut quadtree) => quadtree,
|
Tree(ref mut quadtree) => quadtree,
|
||||||
};
|
};
|
||||||
|
|
||||||
for new_buffers.buffers.iter().advance |buffer| {
|
for buffer in new_buffers.buffers.iter() {
|
||||||
// TODO: This may return old buffers, which should be sent back to the renderer.
|
// TODO: This may return old buffers, which should be sent back to the renderer.
|
||||||
quadtree.add_tile_pixel(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y,
|
quadtree.add_tile_pixel(buffer.screen_pos.origin.x, buffer.screen_pos.origin.y,
|
||||||
buffer.resolution, ~buffer.clone());
|
buffer.resolution, ~buffer.clone());
|
||||||
|
@ -349,7 +349,7 @@ impl CompositorLayer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// ID does not match ours, so recurse on descendents (including hidden children).
|
// ID does not match ours, so recurse on descendents (including hidden children).
|
||||||
self.children.mut_iter().transform(|x| &mut x.child).any(|x| x.add_buffers(pipeline_id, new_buffers))
|
self.children.mut_iter().map(|x| &mut x.child).any(|x| x.add_buffers(pipeline_id, new_buffers))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deletes a specified sublayer, including hidden children. Returns false if the layer is not found.
|
// Deletes a specified sublayer, including hidden children. Returns false if the layer is not found.
|
||||||
|
@ -362,7 +362,7 @@ impl CompositorLayer {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.children.mut_iter().transform(|x| &mut x.child).any(|x| x.delete(pipeline_id))
|
self.children.mut_iter().map(|x| &mut x.child).any(|x| x.delete(pipeline_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,12 @@ use gfx::opts::Opts;
|
||||||
|
|
||||||
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
|
use azure::azure_hl::{DataSourceSurface, DrawTarget, SourceSurfaceMethods, current_gl_context};
|
||||||
use azure::azure::AzGLContext;
|
use azure::azure::AzGLContext;
|
||||||
use std::cell::Cell;
|
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::comm::{Chan, SharedChan, Port};
|
use std::comm::{Chan, SharedChan, Port};
|
||||||
use std::num::Orderable;
|
use std::num::Orderable;
|
||||||
use std::task;
|
|
||||||
use std::uint;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use extra::uv_global_loop;
|
use std::rt::rtio::RtioTimer;
|
||||||
use extra::timer;
|
use std::rt::io::timer::Timer;
|
||||||
use geom::matrix::identity;
|
use geom::matrix::identity;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
@ -80,7 +77,7 @@ impl RenderListener for CompositorChan {
|
||||||
port.recv()
|
port.recv()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&self, id: PipelineId, layer_buffer_set: arc::ARC<LayerBufferSet>) {
|
fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc<LayerBufferSet>) {
|
||||||
self.chan.send(Paint(id, layer_buffer_set))
|
self.chan.send(Paint(id, layer_buffer_set))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +133,7 @@ pub enum Msg {
|
||||||
DeleteLayer(PipelineId),
|
DeleteLayer(PipelineId),
|
||||||
|
|
||||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
||||||
Paint(PipelineId, arc::ARC<LayerBufferSet>),
|
Paint(PipelineId, arc::Arc<LayerBufferSet>),
|
||||||
/// Alerts the compositor to the current status of page loading.
|
/// Alerts the compositor to the current status of page loading.
|
||||||
ChangeReadyState(ReadyState),
|
ChangeReadyState(ReadyState),
|
||||||
/// Alerts the compositor to the current status of rendering.
|
/// Alerts the compositor to the current status of rendering.
|
||||||
|
@ -192,24 +189,7 @@ impl CompositorTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts the compositor, which listens for messages on the specified port.
|
/// Starts the compositor, which listens for messages on the specified port.
|
||||||
pub fn create(opts: Opts,
|
pub fn run(&self) {
|
||||||
port: Port<Msg>,
|
|
||||||
profiler_chan: ProfilerChan,
|
|
||||||
shutdown_chan: Chan<()>) {
|
|
||||||
let port = Cell::new(port);
|
|
||||||
let shutdown_chan = Cell::new(shutdown_chan);
|
|
||||||
let opts = Cell::new(opts);
|
|
||||||
do on_osmain {
|
|
||||||
let compositor_task = CompositorTask::new(opts.take(),
|
|
||||||
port.take(),
|
|
||||||
profiler_chan.clone(),
|
|
||||||
shutdown_chan.take());
|
|
||||||
debug!("preparing to enter main loop");
|
|
||||||
compositor_task.run_main_loop();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_main_loop(&self) {
|
|
||||||
let app: Application = ApplicationMethods::new();
|
let app: Application = ApplicationMethods::new();
|
||||||
let window: @mut Window = WindowMethods::new(&app);
|
let window: @mut Window = WindowMethods::new(&app);
|
||||||
|
|
||||||
|
@ -242,7 +222,7 @@ impl CompositorTask {
|
||||||
let ask_for_tiles = || {
|
let ask_for_tiles = || {
|
||||||
let window_size_page = Size2D(window_size.width as f32 / world_zoom,
|
let window_size_page = Size2D(window_size.width as f32 / world_zoom,
|
||||||
window_size.height as f32 / world_zoom);
|
window_size.height as f32 / world_zoom);
|
||||||
for compositor_layer.mut_iter().advance |layer| {
|
for layer in compositor_layer.mut_iter() {
|
||||||
recomposite = layer.get_buffer_request(Rect(Point2D(0f32, 0f32), window_size_page),
|
recomposite = layer.get_buffer_request(Rect(Point2D(0f32, 0f32), window_size_page),
|
||||||
world_zoom) || recomposite;
|
world_zoom) || recomposite;
|
||||||
}
|
}
|
||||||
|
@ -368,7 +348,7 @@ impl CompositorTask {
|
||||||
MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
MouseWindowMouseDownEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
||||||
MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
MouseWindowMouseUpEvent(_, p) => Point2D(p.x / world_zoom, p.y / world_zoom),
|
||||||
};
|
};
|
||||||
for compositor_layer.iter().advance |layer| {
|
for layer in compositor_layer.iter() {
|
||||||
layer.send_mouse_event(mouse_window_event, point);
|
layer.send_mouse_event(mouse_window_event, point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +360,7 @@ impl CompositorTask {
|
||||||
cursor.y as f32 / world_zoom);
|
cursor.y as f32 / world_zoom);
|
||||||
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
||||||
window_size.height as f32 / world_zoom);
|
window_size.height as f32 / world_zoom);
|
||||||
for compositor_layer.mut_iter().advance |layer| {
|
for layer in compositor_layer.mut_iter() {
|
||||||
recomposite = layer.scroll(page_delta, page_cursor, page_window) || recomposite;
|
recomposite = layer.scroll(page_delta, page_cursor, page_window) || recomposite;
|
||||||
}
|
}
|
||||||
ask_for_tiles();
|
ask_for_tiles();
|
||||||
|
@ -402,7 +382,7 @@ impl CompositorTask {
|
||||||
let page_cursor = Point2D(-1f32, -1f32); // Make sure this hits the base layer
|
let page_cursor = Point2D(-1f32, -1f32); // Make sure this hits the base layer
|
||||||
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
let page_window = Size2D(window_size.width as f32 / world_zoom,
|
||||||
window_size.height as f32 / world_zoom);
|
window_size.height as f32 / world_zoom);
|
||||||
for compositor_layer.mut_iter().advance |layer| {
|
for layer in compositor_layer.mut_iter() {
|
||||||
layer.scroll(page_delta, page_cursor, page_window);
|
layer.scroll(page_delta, page_cursor, page_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,7 +438,7 @@ impl CompositorTask {
|
||||||
// flip image vertically (texture is upside down)
|
// flip image vertically (texture is upside down)
|
||||||
let orig_pixels = pixels.clone();
|
let orig_pixels = pixels.clone();
|
||||||
let stride = width * 3;
|
let stride = width * 3;
|
||||||
for uint::range(0, height) |y| {
|
for y in range(0, height) {
|
||||||
let dst_start = y * stride;
|
let dst_start = y * stride;
|
||||||
let src_start = (height - y - 1) * stride;
|
let src_start = (height - y - 1) * stride;
|
||||||
vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride),
|
vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride),
|
||||||
|
@ -483,6 +463,7 @@ impl CompositorTask {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enter the main event loop.
|
// Enter the main event loop.
|
||||||
|
let tm = Timer::new().unwrap();
|
||||||
while !done {
|
while !done {
|
||||||
// Check for new messages coming from the rendering task.
|
// Check for new messages coming from the rendering task.
|
||||||
check_for_messages(&self.port);
|
check_for_messages(&self.port);
|
||||||
|
@ -495,7 +476,7 @@ impl CompositorTask {
|
||||||
composite();
|
composite();
|
||||||
}
|
}
|
||||||
|
|
||||||
timer::sleep(&uv_global_loop::get(), 10);
|
tm.sleep(10);
|
||||||
|
|
||||||
// If a pinch-zoom happened recently, ask for tiles at the new resolution
|
// If a pinch-zoom happened recently, ask for tiles at the new resolution
|
||||||
if zoom_action && precise_time_s() - zoom_time > 0.3 {
|
if zoom_action && precise_time_s() - zoom_time > 0.3 {
|
||||||
|
@ -508,14 +489,3 @@ impl CompositorTask {
|
||||||
self.shutdown_chan.send(())
|
self.shutdown_chan.send(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function for spawning into the platform's main thread.
|
|
||||||
fn on_osmain(f: ~fn()) {
|
|
||||||
// FIXME: rust#6399
|
|
||||||
let mut main_task = task::task();
|
|
||||||
main_task.sched_mode(task::PlatformThread);
|
|
||||||
do main_task.spawn {
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ struct QuadtreeNode<T> {
|
||||||
tile_mem: uint,
|
tile_mem: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
priv enum Quadrant {
|
enum Quadrant {
|
||||||
TL = 0,
|
TL = 0,
|
||||||
TR = 1,
|
TR = 1,
|
||||||
BL = 2,
|
BL = 2,
|
||||||
|
@ -212,7 +212,7 @@ impl<T: Tile> Quadtree<T> {
|
||||||
let difference = (new_size as f32 / self.root.size as f32).log2() as int;
|
let difference = (new_size as f32 / self.root.size as f32).log2() as int;
|
||||||
if difference > 0 { // doubling
|
if difference > 0 { // doubling
|
||||||
let difference = difference as uint;
|
let difference = difference as uint;
|
||||||
for range(0, difference) |i| {
|
for i in range(0, difference) {
|
||||||
let new_root = ~QuadtreeNode {
|
let new_root = ~QuadtreeNode {
|
||||||
tile: None,
|
tile: None,
|
||||||
origin: Point2D(0f32, 0f32),
|
origin: Point2D(0f32, 0f32),
|
||||||
|
@ -225,7 +225,7 @@ impl<T: Tile> Quadtree<T> {
|
||||||
}
|
}
|
||||||
} else if difference < 0 { // halving
|
} else if difference < 0 { // halving
|
||||||
let difference = difference.abs() as uint;
|
let difference = difference.abs() as uint;
|
||||||
for difference.times {
|
for _ in range(0, difference) {
|
||||||
let remove = replace(&mut self.root.quadrants[TL as int], None);
|
let remove = replace(&mut self.root.quadrants[TL as int], None);
|
||||||
match remove {
|
match remove {
|
||||||
Some(child) => self.root = child,
|
Some(child) => self.root = child,
|
||||||
|
@ -299,7 +299,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
fn get_all_tiles<'r>(&'r self) -> ~[&'r T] {
|
fn get_all_tiles<'r>(&'r self) -> ~[&'r T] {
|
||||||
let mut ret = ~[];
|
let mut ret = ~[];
|
||||||
|
|
||||||
for self.quadrants.iter().advance |quad| {
|
for quad in self.quadrants.iter() {
|
||||||
match *quad {
|
match *quad {
|
||||||
Some(ref child) => ret = ret + child.get_all_tiles(),
|
Some(ref child) => ret = ret + child.get_all_tiles(),
|
||||||
None => {}
|
None => {}
|
||||||
|
@ -332,7 +332,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
self.tile = Some(tile);
|
self.tile = Some(tile);
|
||||||
// FIXME: This should be inline, but currently won't compile
|
// FIXME: This should be inline, but currently won't compile
|
||||||
let quads = [TL, TR, BL, BR];
|
let quads = [TL, TR, BL, BR];
|
||||||
for quads.iter().advance |quad| {
|
for quad in quads.iter() {
|
||||||
self.quadrants[*quad as int] = None;
|
self.quadrants[*quad as int] = None;
|
||||||
}
|
}
|
||||||
self.render_flag = false;
|
self.render_flag = false;
|
||||||
|
@ -439,7 +439,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
let mut del_quad: Option<Quadrant> = None;
|
let mut del_quad: Option<Quadrant> = None;
|
||||||
let mut ret = (None, false, 0);
|
let mut ret = (None, false, 0);
|
||||||
|
|
||||||
for queue.iter().advance |quad| {
|
for quad in queue.iter() {
|
||||||
match self.quadrants[*quad as int] {
|
match self.quadrants[*quad as int] {
|
||||||
Some(ref mut child) => {
|
Some(ref mut child) => {
|
||||||
let (tile, flag, delta) = child.remove_tile(x, y);
|
let (tile, flag, delta) = child.remove_tile(x, y);
|
||||||
|
@ -514,7 +514,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
let old_mem = self.tile_mem;
|
let old_mem = self.tile_mem;
|
||||||
// FIXME: This should be inline, but currently won't compile
|
// FIXME: This should be inline, but currently won't compile
|
||||||
let quads = [TL, TR, BL, BR];
|
let quads = [TL, TR, BL, BR];
|
||||||
for quads.iter().advance |quad| {
|
for quad in quads.iter() {
|
||||||
self.quadrants[*quad as int] = None;
|
self.quadrants[*quad as int] = None;
|
||||||
}
|
}
|
||||||
self.tile_mem = tile.get_mem();
|
self.tile_mem = tile.get_mem();
|
||||||
|
@ -561,7 +561,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
let mut redisplay = false;
|
let mut redisplay = false;
|
||||||
let mut delta = 0;
|
let mut delta = 0;
|
||||||
|
|
||||||
for quads_to_check.iter().advance |quad| {
|
for quad in quads_to_check.iter() {
|
||||||
// Recurse into child
|
// Recurse into child
|
||||||
let new_window = match *quad {
|
let new_window = match *quad {
|
||||||
TL => Rect(window.origin,
|
TL => Rect(window.origin,
|
||||||
|
@ -628,7 +628,7 @@ impl<T: Tile> QuadtreeNode<T> {
|
||||||
ret = fmt!("%s<table border=1><tr>", ret);
|
ret = fmt!("%s<table border=1><tr>", ret);
|
||||||
// FIXME: This should be inline, but currently won't compile
|
// FIXME: This should be inline, but currently won't compile
|
||||||
let quads = [TL, TR, BL, BR];
|
let quads = [TL, TR, BL, BR];
|
||||||
for quads.iter().advance |quad| {
|
for quad in quads.iter() {
|
||||||
match self.quadrants[*quad as int] {
|
match self.quadrants[*quad as int] {
|
||||||
Some(ref child) => {
|
Some(ref child) => {
|
||||||
ret = fmt!("%s<td>%s</td>", ret, child.get_html());
|
ret = fmt!("%s<td>%s</td>", ret, child.get_html());
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
use compositing::{CompositorChan, SetIds};
|
use compositing::{CompositorChan, SetIds};
|
||||||
|
|
||||||
use extra::net::url;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::comm::Port;
|
use std::comm::Port;
|
||||||
|
@ -51,7 +49,7 @@ struct FrameTree {
|
||||||
// Need to clone the FrameTrees, but _not_ the Pipelines
|
// Need to clone the FrameTrees, but _not_ the Pipelines
|
||||||
impl Clone for FrameTree {
|
impl Clone for FrameTree {
|
||||||
fn clone(&self) -> FrameTree {
|
fn clone(&self) -> FrameTree {
|
||||||
let mut children = do self.children.iter().transform |&frame_tree| {
|
let mut children = do self.children.iter().map |&frame_tree| {
|
||||||
@mut (*frame_tree).clone()
|
@mut (*frame_tree).clone()
|
||||||
};
|
};
|
||||||
FrameTree {
|
FrameTree {
|
||||||
|
@ -95,27 +93,27 @@ impl FrameTree {
|
||||||
|
|
||||||
/// Replaces a node of the frame tree in place. Returns the node that was removed or the original node
|
/// Replaces a node of the frame tree in place. Returns the node that was removed or the original node
|
||||||
/// if the node to replace could not be found.
|
/// if the node to replace could not be found.
|
||||||
fn replace_child(&mut self, id: PipelineId, new_child: @mut FrameTree) -> Result<@mut FrameTree, @mut FrameTree> {
|
fn replace_child(&mut self, id: PipelineId, new_child: @mut FrameTree) -> Either<@mut FrameTree, @mut FrameTree> {
|
||||||
let new_child_cell = Cell::new(new_child);
|
let new_child_cell = Cell::new(new_child);
|
||||||
for self.children.mut_iter().advance |child| {
|
for child in self.children.mut_iter() {
|
||||||
let new_child = new_child_cell.take();
|
let new_child = new_child_cell.take();
|
||||||
if child.pipeline.id == id {
|
if child.pipeline.id == id {
|
||||||
new_child.parent = child.parent;
|
new_child.parent = child.parent;
|
||||||
return Ok(replace(child, new_child));
|
return Left(replace(child, new_child));
|
||||||
}
|
}
|
||||||
let replaced = child.replace_child(id, new_child);
|
let replaced = child.replace_child(id, new_child);
|
||||||
if replaced.is_ok() {
|
if replaced.is_left() {
|
||||||
return replaced;
|
return replaced;
|
||||||
}
|
}
|
||||||
new_child_cell.put_back(replaced.get_err());
|
new_child_cell.put_back(replaced.unwrap_right());
|
||||||
}
|
}
|
||||||
Err(new_child_cell.take())
|
Right(new_child_cell.take())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_sendable(&self) -> SendableFrameTree {
|
fn to_sendable(&self) -> SendableFrameTree {
|
||||||
let sendable_frame_tree = SendableFrameTree {
|
let sendable_frame_tree = SendableFrameTree {
|
||||||
pipeline: (*self.pipeline).clone(),
|
pipeline: (*self.pipeline).clone(),
|
||||||
children: self.children.iter().transform(|frame_tree| frame_tree.to_sendable()).collect(),
|
children: self.children.iter().map(|frame_tree| frame_tree.to_sendable()).collect(),
|
||||||
};
|
};
|
||||||
sendable_frame_tree
|
sendable_frame_tree
|
||||||
}
|
}
|
||||||
|
@ -169,17 +167,17 @@ impl NavigationContext {
|
||||||
* when it is known that there exists either a previous page or a next page. */
|
* when it is known that there exists either a previous page or a next page. */
|
||||||
|
|
||||||
pub fn back(&mut self) -> @mut FrameTree {
|
pub fn back(&mut self) -> @mut FrameTree {
|
||||||
self.next.push(self.current.swap_unwrap());
|
self.next.push(self.current.take_unwrap());
|
||||||
self.current = Some(self.previous.pop());
|
self.current = Some(self.previous.pop());
|
||||||
debug!("previous: %? next: %? current: %?", self.previous, self.next, *self.current.get_ref());
|
debug!("previous: %? next: %? current: %?", self.previous, self.next, *self.current.get_ref());
|
||||||
self.current.get()
|
self.current.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn forward(&mut self) -> @mut FrameTree {
|
pub fn forward(&mut self) -> @mut FrameTree {
|
||||||
self.previous.push(self.current.swap_unwrap());
|
self.previous.push(self.current.take_unwrap());
|
||||||
self.current = Some(self.next.pop());
|
self.current = Some(self.next.pop());
|
||||||
debug!("previous: %? next: %? current: %?", self.previous, self.next, *self.current.get_ref());
|
debug!("previous: %? next: %? current: %?", self.previous, self.next, *self.current.get_ref());
|
||||||
self.current.get()
|
self.current.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a new set of page frames, returning all evicted frame trees
|
/// Loads a new set of page frames, returning all evicted frame trees
|
||||||
|
@ -187,7 +185,7 @@ impl NavigationContext {
|
||||||
debug!("navigating to %?", frame_tree);
|
debug!("navigating to %?", frame_tree);
|
||||||
let evicted = replace(&mut self.next, ~[]);
|
let evicted = replace(&mut self.next, ~[]);
|
||||||
if self.current.is_some() {
|
if self.current.is_some() {
|
||||||
self.previous.push(self.current.swap_unwrap());
|
self.previous.push(self.current.take_unwrap());
|
||||||
}
|
}
|
||||||
self.current = Some(frame_tree);
|
self.current = Some(frame_tree);
|
||||||
evicted
|
evicted
|
||||||
|
@ -204,7 +202,7 @@ impl NavigationContext {
|
||||||
let from_prev = do self.previous.iter().filter_map |frame_tree| {
|
let from_prev = do self.previous.iter().filter_map |frame_tree| {
|
||||||
frame_tree.find_mut(pipeline_id)
|
frame_tree.find_mut(pipeline_id)
|
||||||
};
|
};
|
||||||
from_prev.chain_(from_current).chain_(from_next).collect()
|
from_prev.chain(from_current).chain(from_next).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&mut self, pipeline_id: PipelineId) -> bool {
|
pub fn contains(&mut self, pipeline_id: PipelineId) -> bool {
|
||||||
|
@ -212,7 +210,7 @@ impl NavigationContext {
|
||||||
let from_next = self.next.iter();
|
let from_next = self.next.iter();
|
||||||
let from_prev = self.previous.iter();
|
let from_prev = self.previous.iter();
|
||||||
|
|
||||||
let mut all_contained = from_prev.chain_(from_current).chain_(from_next);
|
let mut all_contained = from_prev.chain(from_current).chain(from_next);
|
||||||
do all_contained.any |frame_tree| {
|
do all_contained.any |frame_tree| {
|
||||||
frame_tree.contains(pipeline_id)
|
frame_tree.contains(pipeline_id)
|
||||||
}
|
}
|
||||||
|
@ -227,7 +225,7 @@ impl Constellation {
|
||||||
profiler_chan: ProfilerChan)
|
profiler_chan: ProfilerChan)
|
||||||
-> ConstellationChan {
|
-> ConstellationChan {
|
||||||
|
|
||||||
let opts = Cell::new(copy *opts);
|
let opts = Cell::new((*opts).clone());
|
||||||
|
|
||||||
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
||||||
let constellation_port = Cell::new(constellation_port);
|
let constellation_port = Cell::new(constellation_port);
|
||||||
|
@ -285,7 +283,7 @@ impl Constellation {
|
||||||
match request {
|
match request {
|
||||||
|
|
||||||
ExitMsg(sender) => {
|
ExitMsg(sender) => {
|
||||||
for self.pipelines.iter().advance |(_id, ref pipeline)| {
|
for (_id, ref pipeline) in self.pipelines.iter() {
|
||||||
pipeline.exit();
|
pipeline.exit();
|
||||||
}
|
}
|
||||||
self.image_cache_task.exit();
|
self.image_cache_task.exit();
|
||||||
|
@ -304,7 +302,7 @@ impl Constellation {
|
||||||
self.image_cache_task.clone(),
|
self.image_cache_task.clone(),
|
||||||
self.resource_task.clone(),
|
self.resource_task.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
copy self.opts,
|
self.opts.clone(),
|
||||||
{
|
{
|
||||||
let size = self.compositor_chan.get_size();
|
let size = self.compositor_chan.get_size();
|
||||||
from_value(Size2D(size.width as uint, size.height as uint))
|
from_value(Size2D(size.width as uint, size.height as uint))
|
||||||
|
@ -339,7 +337,7 @@ impl Constellation {
|
||||||
let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| {
|
let matching_pending_frames = do self.pending_frames.iter().filter_map |frame_change| {
|
||||||
frame_change.after.find_mut(source_pipeline_id)
|
frame_change.after.find_mut(source_pipeline_id)
|
||||||
};
|
};
|
||||||
matching_navi_frames.consume_iter().chain_(matching_pending_frames).collect()
|
matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
if frame_trees.is_empty() {
|
if frame_trees.is_empty() {
|
||||||
|
@ -370,7 +368,7 @@ impl Constellation {
|
||||||
self.compositor_chan.clone(),
|
self.compositor_chan.clone(),
|
||||||
self.image_cache_task.clone(),
|
self.image_cache_task.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
copy self.opts,
|
self.opts.clone(),
|
||||||
source_pipeline,
|
source_pipeline,
|
||||||
size_future)
|
size_future)
|
||||||
} else {
|
} else {
|
||||||
|
@ -382,7 +380,7 @@ impl Constellation {
|
||||||
self.image_cache_task.clone(),
|
self.image_cache_task.clone(),
|
||||||
self.resource_task.clone(),
|
self.resource_task.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
copy self.opts,
|
self.opts.clone(),
|
||||||
size_future)
|
size_future)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -391,7 +389,7 @@ impl Constellation {
|
||||||
} else {
|
} else {
|
||||||
pipeline.load(url, None);
|
pipeline.load(url, None);
|
||||||
}
|
}
|
||||||
for frame_trees.iter().advance |frame_tree| {
|
for frame_tree in frame_trees.iter() {
|
||||||
frame_tree.children.push(@mut FrameTree {
|
frame_tree.children.push(@mut FrameTree {
|
||||||
pipeline: pipeline,
|
pipeline: pipeline,
|
||||||
parent: Some(source_pipeline),
|
parent: Some(source_pipeline),
|
||||||
|
@ -405,14 +403,14 @@ impl Constellation {
|
||||||
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
// If there is already a pending page (self.pending_frames), it will not be overridden;
|
||||||
// However, if the id is not encompassed by another change, it will be.
|
// However, if the id is not encompassed by another change, it will be.
|
||||||
LoadUrlMsg(source_id, url, size_future) => {
|
LoadUrlMsg(source_id, url, size_future) => {
|
||||||
debug!("received message to load %s", url::to_str(&url));
|
debug!("received message to load %s", url.to_str());
|
||||||
// Make sure no pending page would be overridden.
|
// Make sure no pending page would be overridden.
|
||||||
let source_frame = self.current_frame().get_ref().find_mut(source_id).expect(
|
let source_frame = self.current_frame().get_ref().find_mut(source_id).expect(
|
||||||
"Constellation: received a LoadUrlMsg from a pipeline_id associated
|
"Constellation: received a LoadUrlMsg from a pipeline_id associated
|
||||||
with a pipeline not in the active frame tree. This should be
|
with a pipeline not in the active frame tree. This should be
|
||||||
impossible.");
|
impossible.");
|
||||||
|
|
||||||
for self.pending_frames.iter().advance |frame_change| {
|
for frame_change in self.pending_frames.iter() {
|
||||||
let old_id = frame_change.before.expect("Constellation: Received load msg
|
let old_id = frame_change.before.expect("Constellation: Received load msg
|
||||||
from pipeline, but there is no currently active page. This should
|
from pipeline, but there is no currently active page. This should
|
||||||
be impossible.");
|
be impossible.");
|
||||||
|
@ -438,7 +436,7 @@ impl Constellation {
|
||||||
self.image_cache_task.clone(),
|
self.image_cache_task.clone(),
|
||||||
self.resource_task.clone(),
|
self.resource_task.clone(),
|
||||||
self.profiler_chan.clone(),
|
self.profiler_chan.clone(),
|
||||||
copy self.opts,
|
self.opts.clone(),
|
||||||
size_future);
|
size_future);
|
||||||
|
|
||||||
if url.path.ends_with(".js") {
|
if url.path.ends_with(".js") {
|
||||||
|
@ -473,7 +471,7 @@ impl Constellation {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().get_ref();
|
let old = self.current_frame().get_ref();
|
||||||
for old.iter().advance |frame| {
|
for frame in old.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -485,7 +483,7 @@ impl Constellation {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
let old = self.current_frame().get_ref();
|
let old = self.current_frame().get_ref();
|
||||||
for old.iter().advance |frame| {
|
for frame in old.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.revoke_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,7 +491,7 @@ impl Constellation {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for destination_frame.iter().advance |frame| {
|
for frame in destination_frame.iter() {
|
||||||
let pipeline = &frame.pipeline;
|
let pipeline = &frame.pipeline;
|
||||||
pipeline.reload(Some(constellation_msg::Navigate));
|
pipeline.reload(Some(constellation_msg::Navigate));
|
||||||
}
|
}
|
||||||
|
@ -507,7 +505,7 @@ impl Constellation {
|
||||||
// from a pending frame. The only time that we will grant paint permission is
|
// from a pending frame. The only time that we will grant paint permission is
|
||||||
// when the message originates from a pending frame or the current frame.
|
// when the message originates from a pending frame or the current frame.
|
||||||
|
|
||||||
for self.current_frame().iter().advance |¤t_frame| {
|
for ¤t_frame in self.current_frame().iter() {
|
||||||
// Messages originating in the current frame are not navigations;
|
// Messages originating in the current frame are not navigations;
|
||||||
// TODO(tkuehn): In fact, this kind of message might be provably
|
// TODO(tkuehn): In fact, this kind of message might be provably
|
||||||
// impossible to occur.
|
// impossible to occur.
|
||||||
|
@ -523,26 +521,26 @@ impl Constellation {
|
||||||
let pending_index = do self.pending_frames.rposition |frame_change| {
|
let pending_index = do self.pending_frames.rposition |frame_change| {
|
||||||
frame_change.after.pipeline.id == pipeline_id
|
frame_change.after.pipeline.id == pipeline_id
|
||||||
};
|
};
|
||||||
for pending_index.iter().advance |&pending_index| {
|
for &pending_index in pending_index.iter() {
|
||||||
let frame_change = self.pending_frames.swap_remove(pending_index);
|
let frame_change = self.pending_frames.swap_remove(pending_index);
|
||||||
let to_add = frame_change.after;
|
let to_add = frame_change.after;
|
||||||
|
|
||||||
// Create the next frame tree that will be given to the compositor
|
// Create the next frame tree that will be given to the compositor
|
||||||
let next_frame_tree = match to_add.parent {
|
let next_frame_tree = match to_add.parent {
|
||||||
None => to_add, // to_add is the root
|
None => to_add, // to_add is the root
|
||||||
Some(_parent) => @mut (*self.current_frame().get()).clone(),
|
Some(_parent) => @mut (*self.current_frame().unwrap()).clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If there are frames to revoke permission from, do so now.
|
// If there are frames to revoke permission from, do so now.
|
||||||
match frame_change.before {
|
match frame_change.before {
|
||||||
Some(revoke_id) => {
|
Some(revoke_id) => {
|
||||||
let current_frame = self.current_frame().get();
|
let current_frame = self.current_frame().unwrap();
|
||||||
|
|
||||||
let to_revoke = current_frame.find_mut(revoke_id).expect(
|
let to_revoke = current_frame.find_mut(revoke_id).expect(
|
||||||
"Constellation: pending frame change refers to an old
|
"Constellation: pending frame change refers to an old
|
||||||
frame not contained in the current frame. This is a bug");
|
frame not contained in the current frame. This is a bug");
|
||||||
|
|
||||||
for to_revoke.iter().advance |frame| {
|
for frame in to_revoke.iter() {
|
||||||
frame.pipeline.revoke_paint_permission();
|
frame.pipeline.revoke_paint_permission();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +554,7 @@ impl Constellation {
|
||||||
// Add to_add to parent's children, if it is not the root
|
// Add to_add to parent's children, if it is not the root
|
||||||
let parent = &to_add.parent;
|
let parent = &to_add.parent;
|
||||||
let to_add = Cell::new(to_add);
|
let to_add = Cell::new(to_add);
|
||||||
for parent.iter().advance |parent| {
|
for parent in parent.iter() {
|
||||||
let parent = next_frame_tree.find_mut(parent.id).expect(
|
let parent = next_frame_tree.find_mut(parent.id).expect(
|
||||||
"Constellation: pending frame has a parent frame that is not
|
"Constellation: pending frame has a parent frame that is not
|
||||||
active. This is a bug.");
|
active. This is a bug.");
|
||||||
|
@ -571,13 +569,13 @@ impl Constellation {
|
||||||
ResizedWindowBroadcast(new_size) => match *self.current_frame() {
|
ResizedWindowBroadcast(new_size) => match *self.current_frame() {
|
||||||
Some(ref current_frame) => {
|
Some(ref current_frame) => {
|
||||||
let current_frame_id = current_frame.pipeline.id.clone();
|
let current_frame_id = current_frame.pipeline.id.clone();
|
||||||
for self.navigation_context.previous.iter().advance |frame_tree| {
|
for frame_tree in self.navigation_context.previous.iter() {
|
||||||
let pipeline = &frame_tree.pipeline;
|
let pipeline = &frame_tree.pipeline;
|
||||||
if current_frame_id != pipeline.id {
|
if current_frame_id != pipeline.id {
|
||||||
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for self.navigation_context.next.iter().advance |frame_tree| {
|
for frame_tree in self.navigation_context.next.iter() {
|
||||||
let pipeline = &frame_tree.pipeline;
|
let pipeline = &frame_tree.pipeline;
|
||||||
if current_frame_id != pipeline.id {
|
if current_frame_id != pipeline.id {
|
||||||
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||||
|
@ -585,10 +583,10 @@ impl Constellation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
for self.navigation_context.previous.iter().advance |frame_tree| {
|
for frame_tree in self.navigation_context.previous.iter() {
|
||||||
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||||
}
|
}
|
||||||
for self.navigation_context.next.iter().advance |frame_tree| {
|
for frame_tree in self.navigation_context.next.iter() {
|
||||||
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
frame_tree.pipeline.script_chan.send(ResizeInactiveMsg(new_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,9 +606,9 @@ impl Constellation {
|
||||||
match frame_tree.pipeline.navigation_type {
|
match frame_tree.pipeline.navigation_type {
|
||||||
Some(constellation_msg::Load) => {
|
Some(constellation_msg::Load) => {
|
||||||
let evicted = self.navigation_context.load(frame_tree);
|
let evicted = self.navigation_context.load(frame_tree);
|
||||||
for evicted.iter().advance |frame_tree| {
|
for frame_tree in evicted.iter() {
|
||||||
// exit any pipelines that don't exist outside the evicted frame trees
|
// exit any pipelines that don't exist outside the evicted frame trees
|
||||||
for frame_tree.iter().advance |frame| {
|
for frame in frame_tree.iter() {
|
||||||
if !self.navigation_context.contains(frame.pipeline.id) {
|
if !self.navigation_context.contains(frame.pipeline.id) {
|
||||||
frame_tree.pipeline.exit();
|
frame_tree.pipeline.exit();
|
||||||
self.pipelines.remove(&frame_tree.pipeline.id);
|
self.pipelines.remove(&frame_tree.pipeline.id);
|
||||||
|
@ -626,7 +624,7 @@ impl Constellation {
|
||||||
let (port, chan) = comm::stream();
|
let (port, chan) = comm::stream();
|
||||||
self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan));
|
self.compositor_chan.send(SetIds(frame_tree.to_sendable(), chan));
|
||||||
port.recv();
|
port.recv();
|
||||||
for frame_tree.iter().advance |frame| {
|
for frame in frame_tree.iter() {
|
||||||
frame.pipeline.grant_paint_permission();
|
frame.pipeline.grant_paint_permission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use layout::incremental;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use newcss::complete::CompleteSelectResults;
|
use newcss::complete::CompleteSelectResults;
|
||||||
use newcss::select::{SelectCtx, SelectResults};
|
use newcss::select::{SelectCtx, SelectResults};
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
pub trait MatchMethods {
|
pub trait MatchMethods {
|
||||||
fn restyle_subtree(&self, select_ctx: &SelectCtx);
|
fn restyle_subtree(&self, select_ctx: &SelectCtx);
|
||||||
|
@ -48,7 +48,7 @@ impl MatchMethods for AbstractNode<LayoutView> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
for self.each_child |kid| {
|
for kid in self.children() {
|
||||||
kid.restyle_subtree(select_ctx);
|
kid.restyle_subtree(select_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl<'self> NodeUtil<'self> for AbstractNode<LayoutView> {
|
||||||
if !self.has_layout_data() {
|
if !self.has_layout_data() {
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
self.layout_data().restyle_damage.get_or_default(default)
|
self.layout_data().restyle_damage.unwrap_or_default(default)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the restyle damage field.
|
/// Set the restyle damage field.
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use url_from_str = extra::net::url::from_str;
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::result;
|
use std::FromStr;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::select::SelectCtx;
|
use newcss::select::SelectCtx;
|
||||||
use newcss::types::OriginUA;
|
use newcss::types::OriginUA;
|
||||||
|
@ -29,7 +28,7 @@ fn servo_default_style() -> Stylesheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_url(name: &str) -> Url {
|
fn default_url(name: &str) -> Url {
|
||||||
result::unwrap(url_from_str(fmt!("http://%s", name)))
|
FromStr::from_str(fmt!("http://%s", name)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_stream(style: &str) -> DataStream {
|
fn style_stream(style: &str) -> DataStream {
|
||||||
|
|
|
@ -101,7 +101,7 @@ impl SelectHandler<AbstractNode<LayoutView>> for NodeSelectHandler {
|
||||||
None => false,
|
None => false,
|
||||||
Some(existing_classes) => {
|
Some(existing_classes) => {
|
||||||
let mut ret = false;
|
let mut ret = false;
|
||||||
for existing_classes.split_iter(' ').advance |s| {
|
for s in existing_classes.split_iter(' ') {
|
||||||
if s == class {
|
if s == class {
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -9,7 +9,7 @@ use layout::incremental::RestyleDamage;
|
||||||
|
|
||||||
use newcss::complete::CompleteSelectResults;
|
use newcss::complete::CompleteSelectResults;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
/// Data that layout associates with a node.
|
/// Data that layout associates with a node.
|
||||||
pub struct LayoutData {
|
pub struct LayoutData {
|
||||||
|
@ -37,7 +37,7 @@ impl LayoutData {
|
||||||
/// Functionality useful for querying the layout-specific data on DOM nodes.
|
/// Functionality useful for querying the layout-specific data on DOM nodes.
|
||||||
pub trait LayoutAuxMethods {
|
pub trait LayoutAuxMethods {
|
||||||
fn layout_data(self) -> @mut LayoutData;
|
fn layout_data(self) -> @mut LayoutData;
|
||||||
pub fn has_layout_data(self) -> bool;
|
fn has_layout_data(self) -> bool;
|
||||||
fn set_layout_data(self, data: @mut LayoutData);
|
fn set_layout_data(self, data: @mut LayoutData);
|
||||||
|
|
||||||
fn initialize_layout_data(self) -> Option<@mut LayoutData>;
|
fn initialize_layout_data(self) -> Option<@mut LayoutData>;
|
||||||
|
@ -45,17 +45,17 @@ pub trait LayoutAuxMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
||||||
pub fn layout_data(self) -> @mut LayoutData {
|
fn layout_data(self) -> @mut LayoutData {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.unsafe_layout_data()
|
self.unsafe_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn has_layout_data(self) -> bool {
|
fn has_layout_data(self) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.unsafe_has_layout_data()
|
self.unsafe_has_layout_data()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set_layout_data(self, data: @mut LayoutData) {
|
fn set_layout_data(self, data: @mut LayoutData) {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.unsafe_set_layout_data(data)
|
self.unsafe_set_layout_data(data)
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ impl LayoutAuxMethods for AbstractNode<LayoutView> {
|
||||||
/// Initializes layout data and styles for a Node tree, if any nodes do not have
|
/// Initializes layout data and styles for a Node tree, if any nodes do not have
|
||||||
/// this data already. Append created layout data to the task's GC roots.
|
/// this data already. Append created layout data to the task's GC roots.
|
||||||
fn initialize_style_for_subtree(self, refs: &mut ~[@mut LayoutData]) {
|
fn initialize_style_for_subtree(self, refs: &mut ~[@mut LayoutData]) {
|
||||||
let _ = for self.traverse_preorder |n| {
|
let _ = for n in self.traverse_preorder() {
|
||||||
match n.initialize_layout_data() {
|
match n.initialize_layout_data() {
|
||||||
Some(r) => refs.push(r),
|
Some(r) => refs.push(r),
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use gfx::geometry;
|
use gfx::geometry;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
pub struct BlockFlowData {
|
pub struct BlockFlowData {
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
|
@ -50,7 +50,7 @@ impl BlockFlowData {
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.common.teardown();
|
self.common.teardown();
|
||||||
for self.box.iter().advance |box| {
|
for box in self.box.iter() {
|
||||||
box.teardown();
|
box.teardown();
|
||||||
}
|
}
|
||||||
self.box = None;
|
self.box = None;
|
||||||
|
@ -94,7 +94,7 @@ impl BlockFlowData {
|
||||||
let mut num_floats = 0;
|
let mut num_floats = 0;
|
||||||
|
|
||||||
/* find max width from child block contexts */
|
/* find max width from child block contexts */
|
||||||
for BlockFlow(self).each_child |child_ctx| {
|
for child_ctx in BlockFlow(self).children() {
|
||||||
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
||||||
|
|
||||||
do child_ctx.with_mut_base |child_node| {
|
do child_ctx.with_mut_base |child_node| {
|
||||||
|
@ -124,7 +124,7 @@ impl BlockFlowData {
|
||||||
|
|
||||||
/// Computes left and right margins and width based on CSS 2.1 secion 10.3.3.
|
/// Computes left and right margins and width based on CSS 2.1 secion 10.3.3.
|
||||||
/// Requires borders and padding to already be computed
|
/// Requires borders and padding to already be computed
|
||||||
priv fn compute_horiz( &self,
|
fn compute_horiz( &self,
|
||||||
width: MaybeAuto,
|
width: MaybeAuto,
|
||||||
left_margin: MaybeAuto,
|
left_margin: MaybeAuto,
|
||||||
right_margin: MaybeAuto,
|
right_margin: MaybeAuto,
|
||||||
|
@ -192,7 +192,7 @@ impl BlockFlowData {
|
||||||
let mut remaining_width = self.common.position.size.width;
|
let mut remaining_width = self.common.position.size.width;
|
||||||
let mut x_offset = Au(0);
|
let mut x_offset = Au(0);
|
||||||
|
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
let style = box.style();
|
let style = box.style();
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
|
@ -239,7 +239,7 @@ impl BlockFlowData {
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_inorder_children = self.common.is_inorder || self.common.num_floats > 0;
|
let has_inorder_children = self.common.is_inorder || self.common.num_floats > 0;
|
||||||
for BlockFlow(self).each_child |kid| {
|
for kid in BlockFlow(self).children() {
|
||||||
assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
||||||
|
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
|
@ -278,7 +278,7 @@ impl BlockFlowData {
|
||||||
let mut left_offset = Au(0);
|
let mut left_offset = Au(0);
|
||||||
let mut float_ctx = Invalid;
|
let mut float_ctx = Invalid;
|
||||||
|
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
clearance = match box.clear() {
|
clearance = match box.clear() {
|
||||||
None => Au(0),
|
None => Au(0),
|
||||||
Some(clear) => {
|
Some(clear) => {
|
||||||
|
@ -303,7 +303,7 @@ impl BlockFlowData {
|
||||||
// repeat until all children are visited.
|
// repeat until all children are visited.
|
||||||
// last_child.floats_out -> self.floats_out (done at the end of this method)
|
// last_child.floats_out -> self.floats_out (done at the end of this method)
|
||||||
float_ctx = self.common.floats_in.translate(Point2D(-left_offset, -top_offset));
|
float_ctx = self.common.floats_in.translate(Point2D(-left_offset, -top_offset));
|
||||||
for BlockFlow(self).each_child |kid| {
|
for kid in BlockFlow(self).children() {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
child_node.floats_in = float_ctx.clone();
|
child_node.floats_in = float_ctx.clone();
|
||||||
}
|
}
|
||||||
|
@ -311,10 +311,9 @@ impl BlockFlowData {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
float_ctx = child_node.floats_out.clone();
|
float_ctx = child_node.floats_out.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for BlockFlow(self).each_child |kid| {
|
for kid in BlockFlow(self).children() {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
child_node.position.origin.y = cur_y;
|
child_node.position.origin.y = cur_y;
|
||||||
cur_y = cur_y + child_node.position.size.height;
|
cur_y = cur_y + child_node.position.size.height;
|
||||||
|
@ -327,7 +326,7 @@ impl BlockFlowData {
|
||||||
cur_y - top_offset
|
cur_y - top_offset
|
||||||
};
|
};
|
||||||
|
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
let style = box.style();
|
let style = box.style();
|
||||||
let maybe_height = MaybeAuto::from_height(style.height(), Au(0), style.font_size());
|
let maybe_height = MaybeAuto::from_height(style.height(), Au(0), style.font_size());
|
||||||
let maybe_height = maybe_height.specified_or_zero();
|
let maybe_height = maybe_height.specified_or_zero();
|
||||||
|
@ -380,7 +379,7 @@ impl BlockFlowData {
|
||||||
|
|
||||||
// go deeper into the flow tree
|
// go deeper into the flow tree
|
||||||
let flow = BlockFlow(self);
|
let flow = BlockFlow(self);
|
||||||
for flow.each_child |child| {
|
for child in flow.children() {
|
||||||
do child.with_mut_base |base| {
|
do child.with_mut_base |base| {
|
||||||
base.abs_position = self.common.abs_position + base.position.origin;
|
base.abs_position = self.common.abs_position + base.position.origin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ use std::cell::Cell;
|
||||||
use std::cmp::ApproxEq;
|
use std::cmp::ApproxEq;
|
||||||
use std::managed;
|
use std::managed;
|
||||||
use std::num::Zero;
|
use std::num::Zero;
|
||||||
use std::uint;
|
|
||||||
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
use geom::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||||
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass};
|
||||||
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
use gfx::display_list::{DisplayList, ImageDisplayItem, ImageDisplayItemClass};
|
||||||
|
@ -38,7 +37,7 @@ use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_net::image::holder::ImageHolder;
|
use servo_net::image::holder::ImageHolder;
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::range::*;
|
use servo_util::range::*;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
/// Render boxes (`struct RenderBox`) are the leaves of the layout tree. They cannot position
|
/// Render boxes (`struct RenderBox`) are the leaves of the layout tree. They cannot position
|
||||||
/// themselves. In general, render boxes do not have a simple correspondence with CSS boxes as in
|
/// themselves. In general, render boxes do not have a simple correspondence with CSS boxes as in
|
||||||
|
@ -292,14 +291,13 @@ impl RenderBox {
|
||||||
text_box.range,
|
text_box.range,
|
||||||
max_width);
|
max_width);
|
||||||
|
|
||||||
for text_box.run.iter_slices_for_range(&text_box.range)
|
for (glyphs, offset, slice_range) in text_box.run.iter_slices_for_range(&text_box.range) {
|
||||||
|glyphs, offset, slice_range| {
|
|
||||||
debug!("split_to_width: considering slice (offset=%?, range=%?, remain_width=%?)",
|
debug!("split_to_width: considering slice (offset=%?, range=%?, remain_width=%?)",
|
||||||
offset,
|
offset,
|
||||||
slice_range,
|
slice_range,
|
||||||
remaining_width);
|
remaining_width);
|
||||||
|
|
||||||
let metrics = text_box.run.metrics_for_slice(glyphs, slice_range);
|
let metrics = text_box.run.metrics_for_slice(glyphs, &slice_range);
|
||||||
let advance = metrics.advance_width;
|
let advance = metrics.advance_width;
|
||||||
let should_continue: bool;
|
let should_continue: bool;
|
||||||
|
|
||||||
|
@ -385,7 +383,7 @@ impl RenderBox {
|
||||||
//
|
//
|
||||||
// TODO(eatkinson): integrate with
|
// TODO(eatkinson): integrate with
|
||||||
// get_min_width and get_pref_width?
|
// get_min_width and get_pref_width?
|
||||||
priv fn guess_width (&self) -> Au {
|
fn guess_width (&self) -> Au {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
if(!base.node.is_element()) {
|
if(!base.node.is_element()) {
|
||||||
Au(0)
|
Au(0)
|
||||||
|
@ -433,7 +431,7 @@ impl RenderBox {
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
// TODO: Consult the CSS `width` property as well as margins and borders.
|
// TODO: Consult the CSS `width` property as well as margins and borders.
|
||||||
// TODO: If the image isn't available, consult `width`.
|
// TODO: If the image isn't available, consult `width`.
|
||||||
Au::from_px(image_box.image.get_size().get_or_default(Size2D(0, 0)).width)
|
Au::from_px(image_box.image.get_size().unwrap_or_default(Size2D(0, 0)).width)
|
||||||
}
|
}
|
||||||
|
|
||||||
TextRenderBoxClass(text_box) => {
|
TextRenderBoxClass(text_box) => {
|
||||||
|
@ -454,7 +452,7 @@ impl RenderBox {
|
||||||
GenericRenderBoxClass(*) => Au(0),
|
GenericRenderBoxClass(*) => Au(0),
|
||||||
|
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
Au::from_px(image_box.image.get_size().get_or_default(Size2D(0, 0)).width)
|
Au::from_px(image_box.image.get_size().unwrap_or_default(Size2D(0, 0)).width)
|
||||||
}
|
}
|
||||||
|
|
||||||
TextRenderBoxClass(text_box) => {
|
TextRenderBoxClass(text_box) => {
|
||||||
|
@ -465,9 +463,8 @@ impl RenderBox {
|
||||||
// report nothing and the parent flow can factor in minimum/preferred widths of any
|
// report nothing and the parent flow can factor in minimum/preferred widths of any
|
||||||
// text runs that it owns.
|
// text runs that it owns.
|
||||||
let mut max_line_width = Au(0);
|
let mut max_line_width = Au(0);
|
||||||
for text_box.run.iter_natural_lines_for_range(&text_box.range)
|
for line_range in text_box.run.iter_natural_lines_for_range(&text_box.range) {
|
||||||
|line_range| {
|
let line_metrics = text_box.run.metrics_for_range(&line_range);
|
||||||
let line_metrics = text_box.run.metrics_for_range(line_range);
|
|
||||||
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +779,7 @@ impl RenderBox {
|
||||||
// FIXME: Too much allocation here.
|
// FIXME: Too much allocation here.
|
||||||
let font_families = do my_style.font_family().map |family| {
|
let font_families = do my_style.font_family().map |family| {
|
||||||
match *family {
|
match *family {
|
||||||
CSSFontFamilyFamilyName(ref family_str) => copy *family_str,
|
CSSFontFamilyFamilyName(ref family_str) => (*family_str).clone(),
|
||||||
CSSFontFamilyGenericFamily(Serif) => ~"serif",
|
CSSFontFamilyGenericFamily(Serif) => ~"serif",
|
||||||
CSSFontFamilyGenericFamily(SansSerif) => ~"sans-serif",
|
CSSFontFamilyGenericFamily(SansSerif) => ~"sans-serif",
|
||||||
CSSFontFamilyGenericFamily(Cursive) => ~"cursive",
|
CSSFontFamilyGenericFamily(Cursive) => ~"cursive",
|
||||||
|
@ -823,7 +820,7 @@ impl RenderBox {
|
||||||
self.nearest_ancestor_element().style().text_align()
|
self.nearest_ancestor_element().style().text_align()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_height(&self) -> CSSLineHeight {
|
pub fn line_height(&self) -> CSSLineHeight {
|
||||||
self.nearest_ancestor_element().style().line_height()
|
self.nearest_ancestor_element().style().line_height()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,7 +872,7 @@ impl RenderBox {
|
||||||
/// Dumps a render box for debugging, with indentation.
|
/// Dumps a render box for debugging, with indentation.
|
||||||
pub fn dump_indent(&self, indent: uint) {
|
pub fn dump_indent(&self, indent: uint) {
|
||||||
let mut string = ~"";
|
let mut string = ~"";
|
||||||
for uint::range(0u, indent) |_i| {
|
for _ in range(0u, indent) {
|
||||||
string.push_str(" ");
|
string.push_str(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ use script::dom::element::*;
|
||||||
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
||||||
use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
|
use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeNode, TreeUtils};
|
use servo_util::tree::{TreeNodeRef, TreeNode};
|
||||||
|
|
||||||
pub struct LayoutTreeBuilder {
|
pub struct LayoutTreeBuilder {
|
||||||
root_flow: Option<FlowContext>,
|
root_flow: Option<FlowContext>,
|
||||||
|
@ -60,7 +60,7 @@ enum InlineSpacerSide {
|
||||||
LogicalAfter,
|
LogicalAfter,
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn simulate_UA_display_rules(node: AbstractNode<LayoutView>) -> CSSDisplay {
|
fn simulate_UA_display_rules(node: AbstractNode<LayoutView>) -> CSSDisplay {
|
||||||
// FIXME
|
// FIXME
|
||||||
/*let resolved = do node.aux |nd| {
|
/*let resolved = do node.aux |nd| {
|
||||||
match nd.style.display_type {
|
match nd.style.display_type {
|
||||||
|
@ -145,8 +145,7 @@ impl BoxGenerator {
|
||||||
} else if self.inline_spacers_needed_for_node(node) {
|
} else if self.inline_spacers_needed_for_node(node) {
|
||||||
// else, maybe make a spacer for "left" margin, border, padding
|
// else, maybe make a spacer for "left" margin, border, padding
|
||||||
let inline_spacer = self.make_inline_spacer_for_node_side(ctx, node, LogicalBefore);
|
let inline_spacer = self.make_inline_spacer_for_node_side(ctx, node, LogicalBefore);
|
||||||
for inline_spacer.iter().advance
|
for spacer in inline_spacer.iter() {
|
||||||
|spacer: &RenderBox| {
|
|
||||||
inline.boxes.push(*spacer);
|
inline.boxes.push(*spacer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,7 +219,7 @@ impl BoxGenerator {
|
||||||
// If this non-leaf box generates extra horizontal spacing, add a SpacerBox for
|
// If this non-leaf box generates extra horizontal spacing, add a SpacerBox for
|
||||||
// it.
|
// it.
|
||||||
let result = self.make_inline_spacer_for_node_side(ctx, node, LogicalAfter);
|
let result = self.make_inline_spacer_for_node_side(ctx, node, LogicalAfter);
|
||||||
for result.iter().advance |spacer| {
|
for spacer in result.iter() {
|
||||||
let boxes = &mut self.flow.inline().boxes;
|
let boxes = &mut self.flow.inline().boxes;
|
||||||
boxes.push(*spacer);
|
boxes.push(*spacer);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +268,7 @@ impl BoxGenerator {
|
||||||
do node.with_imm_image_element |image_element| {
|
do node.with_imm_image_element |image_element| {
|
||||||
if image_element.image.is_some() {
|
if image_element.image.is_some() {
|
||||||
// FIXME(pcwalton): Don't copy URLs.
|
// FIXME(pcwalton): Don't copy URLs.
|
||||||
let url = copy *image_element.image.get_ref();
|
let url = (*image_element.image.get_ref()).clone();
|
||||||
ImageRenderBoxClass(@mut ImageRenderBox::new(base, url, layout_ctx.image_cache))
|
ImageRenderBoxClass(@mut ImageRenderBox::new(base, url, layout_ctx.image_cache))
|
||||||
} else {
|
} else {
|
||||||
info!("Tried to make image box, but couldn't find image. Made generic box \
|
info!("Tried to make image box, but couldn't find image. Made generic box \
|
||||||
|
@ -328,7 +327,7 @@ impl LayoutTreeBuilder {
|
||||||
|
|
||||||
// recurse on child nodes.
|
// recurse on child nodes.
|
||||||
let mut prev_generator: Option<@mut BoxGenerator> = None;
|
let mut prev_generator: Option<@mut BoxGenerator> = None;
|
||||||
for cur_node.each_child |child_node| {
|
for child_node in cur_node.children() {
|
||||||
prev_generator = self.construct_recursively(layout_ctx, child_node, this_generator, prev_generator);
|
prev_generator = self.construct_recursively(layout_ctx, child_node, this_generator, prev_generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +339,7 @@ impl LayoutTreeBuilder {
|
||||||
// eventually be elided or split, but the mapping between
|
// eventually be elided or split, but the mapping between
|
||||||
// nodes and FlowContexts should not change during layout.
|
// nodes and FlowContexts should not change during layout.
|
||||||
let flow: &FlowContext = &this_generator.flow;
|
let flow: &FlowContext = &this_generator.flow;
|
||||||
for flow.each_child |child_flow| {
|
for child_flow in flow.children() {
|
||||||
do child_flow.with_base |child_node| {
|
do child_flow.with_base |child_node| {
|
||||||
let dom_node = child_node.node;
|
let dom_node = child_node.node;
|
||||||
assert!(dom_node.has_layout_data());
|
assert!(dom_node.has_layout_data());
|
||||||
|
@ -403,22 +402,22 @@ impl LayoutTreeBuilder {
|
||||||
// Floats
|
// Floats
|
||||||
(CSSDisplayBlock, BlockFlow(_), _) |
|
(CSSDisplayBlock, BlockFlow(_), _) |
|
||||||
(CSSDisplayBlock, FloatFlow(_), _) if !is_float.is_none() => {
|
(CSSDisplayBlock, FloatFlow(_), _) if !is_float.is_none() => {
|
||||||
self.create_child_generator(node, parent_generator, Flow_Float(is_float.get()))
|
self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap()))
|
||||||
}
|
}
|
||||||
// If we're placing a float after an inline, append the float to the inline flow,
|
// If we're placing a float after an inline, append the float to the inline flow,
|
||||||
// then continue building from the inline flow in case there are more inlines
|
// then continue building from the inline flow in case there are more inlines
|
||||||
// afterward.
|
// afterward.
|
||||||
(CSSDisplayBlock, _, Some(InlineFlow(_))) if !is_float.is_none() => {
|
(CSSDisplayBlock, _, Some(InlineFlow(_))) if !is_float.is_none() => {
|
||||||
let float_generator = self.create_child_generator(node,
|
let float_generator = self.create_child_generator(node,
|
||||||
sibling_generator.get(),
|
sibling_generator.unwrap(),
|
||||||
Flow_Float(is_float.get()));
|
Flow_Float(is_float.unwrap()));
|
||||||
return Some((float_generator, sibling_generator.get()));
|
return Some((float_generator, sibling_generator.unwrap()));
|
||||||
}
|
}
|
||||||
// This is a catch-all case for when:
|
// This is a catch-all case for when:
|
||||||
// a) sibling_flow is None
|
// a) sibling_flow is None
|
||||||
// b) sibling_flow is a BlockFlow
|
// b) sibling_flow is a BlockFlow
|
||||||
(CSSDisplayBlock, InlineFlow(_), _) if !is_float.is_none() => {
|
(CSSDisplayBlock, InlineFlow(_), _) if !is_float.is_none() => {
|
||||||
self.create_child_generator(node, parent_generator, Flow_Float(is_float.get()))
|
self.create_child_generator(node, parent_generator, Flow_Float(is_float.unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
(CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) {
|
(CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) {
|
||||||
|
@ -515,7 +514,7 @@ impl LayoutTreeBuilder {
|
||||||
let mut found_child_block = false;
|
let mut found_child_block = false;
|
||||||
|
|
||||||
let flow = *parent_flow;
|
let flow = *parent_flow;
|
||||||
for flow.each_child |child_ctx: FlowContext| {
|
for child_ctx in flow.children() {
|
||||||
match child_ctx {
|
match child_ctx {
|
||||||
InlineFlow(*) | InlineBlockFlow(*) => found_child_inline = true,
|
InlineFlow(*) | InlineBlockFlow(*) => found_child_inline = true,
|
||||||
BlockFlow(*) => found_child_block = true,
|
BlockFlow(*) => found_child_block = true,
|
||||||
|
@ -535,7 +534,7 @@ impl LayoutTreeBuilder {
|
||||||
let first_child = do parent_flow.with_base |parent_node| {
|
let first_child = do parent_flow.with_base |parent_node| {
|
||||||
parent_node.first_child
|
parent_node.first_child
|
||||||
};
|
};
|
||||||
for first_child.iter().advance |&first_flow| {
|
for &first_flow in first_child.iter() {
|
||||||
if first_flow.starts_inline_flow() {
|
if first_flow.starts_inline_flow() {
|
||||||
// FIXME: workaround for rust#6393
|
// FIXME: workaround for rust#6393
|
||||||
let mut do_remove = false;
|
let mut do_remove = false;
|
||||||
|
@ -558,7 +557,7 @@ impl LayoutTreeBuilder {
|
||||||
let last_child = do parent_flow.with_base |parent_node| {
|
let last_child = do parent_flow.with_base |parent_node| {
|
||||||
parent_node.last_child
|
parent_node.last_child
|
||||||
};
|
};
|
||||||
for last_child.iter().advance |&last_flow| {
|
for &last_flow in last_child.iter() {
|
||||||
if last_flow.starts_inline_flow() {
|
if last_flow.starts_inline_flow() {
|
||||||
// FIXME: workaround for rust#6393
|
// FIXME: workaround for rust#6393
|
||||||
let mut do_remove = false;
|
let mut do_remove = false;
|
||||||
|
@ -580,7 +579,7 @@ impl LayoutTreeBuilder {
|
||||||
|
|
||||||
// Issue 543: We only need to do this if there are inline child
|
// Issue 543: We only need to do this if there are inline child
|
||||||
// flows, but there's not a quick way to check at the moment.
|
// flows, but there's not a quick way to check at the moment.
|
||||||
for (*parent_flow).each_child |child_flow: FlowContext| {
|
for child_flow in (*parent_flow).children() {
|
||||||
match child_flow {
|
match child_flow {
|
||||||
InlineFlow(*) | InlineBlockFlow(*) => {
|
InlineFlow(*) | InlineBlockFlow(*) => {
|
||||||
let mut scanner = TextRunScanner::new();
|
let mut scanner = TextRunScanner::new();
|
||||||
|
|
|
@ -15,7 +15,7 @@ use geom::rect::Rect;
|
||||||
use gfx::display_list::DisplayList;
|
use gfx::display_list::DisplayList;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use gfx::geometry;
|
use gfx::geometry;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
pub struct FloatFlowData {
|
pub struct FloatFlowData {
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
|
@ -55,7 +55,7 @@ impl FloatFlowData {
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.common.teardown();
|
self.common.teardown();
|
||||||
for self.box.iter().advance |box| {
|
for box in self.box.iter() {
|
||||||
box.teardown();
|
box.teardown();
|
||||||
}
|
}
|
||||||
self.box = None;
|
self.box = None;
|
||||||
|
@ -69,7 +69,7 @@ impl FloatFlowData {
|
||||||
let mut pref_width = Au(0);
|
let mut pref_width = Au(0);
|
||||||
let mut num_floats = 0;
|
let mut num_floats = 0;
|
||||||
|
|
||||||
for FloatFlow(self).each_child |child_ctx| {
|
for child_ctx in FloatFlow(self).children() {
|
||||||
//assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
//assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
||||||
|
|
||||||
do child_ctx.with_mut_base |child_node| {
|
do child_ctx.with_mut_base |child_node| {
|
||||||
|
@ -108,7 +108,7 @@ impl FloatFlowData {
|
||||||
// Parent usually sets this, but floats are never inorder
|
// Parent usually sets this, but floats are never inorder
|
||||||
self.common.is_inorder = false;
|
self.common.is_inorder = false;
|
||||||
|
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
let style = box.style();
|
let style = box.style();
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
// Can compute padding here since we know containing block width.
|
// Can compute padding here since we know containing block width.
|
||||||
|
@ -162,7 +162,7 @@ impl FloatFlowData {
|
||||||
self.common.position.size.width = remaining_width;
|
self.common.position.size.width = remaining_width;
|
||||||
|
|
||||||
let has_inorder_children = self.common.num_floats > 0;
|
let has_inorder_children = self.common.num_floats > 0;
|
||||||
for FloatFlow(self).each_child |kid| {
|
for kid in FloatFlow(self).children() {
|
||||||
//assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
//assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
||||||
|
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
|
@ -199,7 +199,6 @@ impl FloatFlowData {
|
||||||
};
|
};
|
||||||
|
|
||||||
do box.with_base |base| {
|
do box.with_base |base| {
|
||||||
|
|
||||||
let noncontent_width = base.model.padding.left + base.model.padding.right +
|
let noncontent_width = base.model.padding.left + base.model.padding.right +
|
||||||
base.model.border.left + base.model.border.right;
|
base.model.border.left + base.model.border.right;
|
||||||
let noncontent_height = base.model.padding.top + base.model.padding.bottom +
|
let noncontent_height = base.model.padding.top + base.model.padding.bottom +
|
||||||
|
@ -207,7 +206,6 @@ impl FloatFlowData {
|
||||||
|
|
||||||
full_noncontent_width = noncontent_width + base.model.margin.left + base.model.margin.right;
|
full_noncontent_width = noncontent_width + base.model.margin.left + base.model.margin.right;
|
||||||
full_noncontent_height = noncontent_height + base.model.margin.top + base.model.margin.bottom;
|
full_noncontent_height = noncontent_height + base.model.margin.top + base.model.margin.bottom;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -231,7 +229,7 @@ impl FloatFlowData {
|
||||||
let has_inorder_children = self.common.num_floats > 0;
|
let has_inorder_children = self.common.num_floats > 0;
|
||||||
if has_inorder_children {
|
if has_inorder_children {
|
||||||
let mut float_ctx = FloatContext::new(self.floated_children);
|
let mut float_ctx = FloatContext::new(self.floated_children);
|
||||||
for FloatFlow(self).each_child |kid| {
|
for kid in FloatFlow(self).children() {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
child_node.floats_in = float_ctx.clone();
|
child_node.floats_in = float_ctx.clone();
|
||||||
}
|
}
|
||||||
|
@ -245,14 +243,14 @@ impl FloatFlowData {
|
||||||
let mut cur_y = Au(0);
|
let mut cur_y = Au(0);
|
||||||
let mut top_offset = Au(0);
|
let mut top_offset = Au(0);
|
||||||
|
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
do box.with_model |model| {
|
do box.with_model |model| {
|
||||||
top_offset = model.margin.top + model.border.top + model.padding.top;
|
top_offset = model.margin.top + model.border.top + model.padding.top;
|
||||||
cur_y = cur_y + top_offset;
|
cur_y = cur_y + top_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for FloatFlow(self).each_child |kid| {
|
for kid in FloatFlow(self).children() {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
child_node.position.origin.y = cur_y;
|
child_node.position.origin.y = cur_y;
|
||||||
cur_y = cur_y + child_node.position.size.height;
|
cur_y = cur_y + child_node.position.size.height;
|
||||||
|
@ -279,7 +277,7 @@ impl FloatFlowData {
|
||||||
|
|
||||||
|
|
||||||
//TODO(eatkinson): compute heights properly using the 'height' property.
|
//TODO(eatkinson): compute heights properly using the 'height' property.
|
||||||
for self.box.iter().advance |&box| {
|
for &box in self.box.iter() {
|
||||||
let height_prop =
|
let height_prop =
|
||||||
MaybeAuto::from_height(box.style().height(),
|
MaybeAuto::from_height(box.style().height(),
|
||||||
Au(0),
|
Au(0),
|
||||||
|
@ -316,7 +314,7 @@ impl FloatFlowData {
|
||||||
|
|
||||||
// go deeper into the flow tree
|
// go deeper into the flow tree
|
||||||
let flow = FloatFlow(self);
|
let flow = FloatFlow(self);
|
||||||
for flow.each_child |child| {
|
for child in flow.children() {
|
||||||
do child.with_mut_base |base| {
|
do child.with_mut_base |base| {
|
||||||
base.abs_position = offset + base.position.origin;
|
base.abs_position = offset + base.position.origin;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::util::replace;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::i32::max_value;
|
use std::i32::max_value;
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub enum FloatType{
|
pub enum FloatType{
|
||||||
FloatLeft,
|
FloatLeft,
|
||||||
FloatRight
|
FloatRight
|
||||||
|
@ -28,6 +29,7 @@ struct FloatContextBase{
|
||||||
offset: Point2D<Au>
|
offset: Point2D<Au>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
struct FloatData{
|
struct FloatData{
|
||||||
bounds: Rect<Au>,
|
bounds: Rect<Au>,
|
||||||
f_type: FloatType
|
f_type: FloatType
|
||||||
|
@ -174,7 +176,7 @@ impl FloatContextBase{
|
||||||
let mut r_bottom = None;
|
let mut r_bottom = None;
|
||||||
|
|
||||||
// Find the float collisions for the given vertical range.
|
// Find the float collisions for the given vertical range.
|
||||||
for self.float_data.iter().advance |float| {
|
for float in self.float_data.iter() {
|
||||||
debug!("available_rect: Checking for collision against float");
|
debug!("available_rect: Checking for collision against float");
|
||||||
match *float{
|
match *float{
|
||||||
None => (),
|
None => (),
|
||||||
|
@ -268,7 +270,7 @@ impl FloatContextBase{
|
||||||
|
|
||||||
/// Returns true if the given rect overlaps with any floats.
|
/// Returns true if the given rect overlaps with any floats.
|
||||||
fn collides_with_float(&self, bounds: &Rect<Au>) -> bool {
|
fn collides_with_float(&self, bounds: &Rect<Au>) -> bool {
|
||||||
for self.float_data.iter().advance |float| {
|
for float in self.float_data.iter() {
|
||||||
match *float{
|
match *float{
|
||||||
None => (),
|
None => (),
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
|
@ -290,7 +292,7 @@ impl FloatContextBase{
|
||||||
let left = left - self.offset.x;
|
let left = left - self.offset.x;
|
||||||
let mut max_height = None;
|
let mut max_height = None;
|
||||||
|
|
||||||
for self.float_data.iter().advance |float| {
|
for float in self.float_data.iter() {
|
||||||
match *float {
|
match *float {
|
||||||
None => (),
|
None => (),
|
||||||
Some(f_data) => {
|
Some(f_data) => {
|
||||||
|
@ -298,7 +300,7 @@ impl FloatContextBase{
|
||||||
f_data.bounds.origin.x + f_data.bounds.size.width > left &&
|
f_data.bounds.origin.x + f_data.bounds.size.width > left &&
|
||||||
f_data.bounds.origin.x < left + width {
|
f_data.bounds.origin.x < left + width {
|
||||||
let new_y = f_data.bounds.origin.y;
|
let new_y = f_data.bounds.origin.y;
|
||||||
max_height = Some(min(max_height.get_or_default(new_y), new_y));
|
max_height = Some(min(max_height.unwrap_or_default(new_y), new_y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +340,7 @@ impl FloatContextBase{
|
||||||
let height = self.max_height_for_bounds(rect.origin.x,
|
let height = self.max_height_for_bounds(rect.origin.x,
|
||||||
rect.origin.y,
|
rect.origin.y,
|
||||||
rect.size.width);
|
rect.size.width);
|
||||||
let height = height.get_or_default(Au(max_value));
|
let height = height.unwrap_or_default(Au(max_value));
|
||||||
return match info.f_type {
|
return match info.f_type {
|
||||||
FloatLeft => Rect(Point2D(rect.origin.x, float_y),
|
FloatLeft => Rect(Point2D(rect.origin.x, float_y),
|
||||||
Size2D(rect.size.width, height)),
|
Size2D(rect.size.width, height)),
|
||||||
|
@ -359,7 +361,7 @@ impl FloatContextBase{
|
||||||
|
|
||||||
fn clearance(&self, clear: ClearType) -> Au {
|
fn clearance(&self, clear: ClearType) -> Au {
|
||||||
let mut clearance = Au(0);
|
let mut clearance = Au(0);
|
||||||
for self.float_data.iter().advance |float| {
|
for float in self.float_data.iter() {
|
||||||
match *float {
|
match *float {
|
||||||
None => (),
|
None => (),
|
||||||
Some(f_data) => {
|
Some(f_data) => {
|
||||||
|
|
|
@ -36,14 +36,13 @@ use layout::incremental::RestyleDamage;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::uint;
|
|
||||||
use std::io::stderr;
|
use std::io::stderr;
|
||||||
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;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNode, TreeNodeRef};
|
||||||
|
|
||||||
/// The type of the formatting context and data specific to each context, such as line box
|
/// The type of the formatting context and data specific to each context, such as line box
|
||||||
/// structures or float lists.
|
/// structures or float lists.
|
||||||
|
@ -84,29 +83,25 @@ impl FlowContext {
|
||||||
//
|
//
|
||||||
// FIXME: Unify this with traverse_preorder_prune, which takes a separate
|
// FIXME: Unify this with traverse_preorder_prune, which takes a separate
|
||||||
// 'prune' function.
|
// 'prune' function.
|
||||||
fn partially_traverse_preorder(&self, callback: &fn(FlowContext) -> bool) {
|
pub fn partially_traverse_preorder(&self, callback: &fn(FlowContext) -> bool) {
|
||||||
if !callback((*self).clone()) {
|
if !callback((*self).clone()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for self.each_child |kid| {
|
for kid in self.children() {
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
||||||
kid.partially_traverse_preorder(|a| callback(a));
|
kid.partially_traverse_preorder(|a| callback(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_bu_sub_inorder (&self, callback: &fn(FlowContext) -> bool) -> bool {
|
pub fn traverse_bu_sub_inorder (&self, callback: &fn(FlowContext)) {
|
||||||
for self.each_child |kid| {
|
for kid in self.children() {
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
||||||
if !kid.traverse_bu_sub_inorder(|a| callback(a)) {
|
kid.traverse_bu_sub_inorder(|a| callback(a));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.is_inorder() {
|
if !self.is_inorder() {
|
||||||
callback((*self).clone())
|
callback((*self).clone())
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,14 +114,14 @@ impl FlowData {
|
||||||
// or we risk dynamic borrow failures.
|
// or we risk dynamic borrow failures.
|
||||||
self.parent = None;
|
self.parent = None;
|
||||||
|
|
||||||
for self.first_child.iter().advance |flow| {
|
for flow in self.first_child.iter() {
|
||||||
flow.teardown();
|
flow.teardown();
|
||||||
}
|
}
|
||||||
self.first_child = None;
|
self.first_child = None;
|
||||||
|
|
||||||
self.last_child = None;
|
self.last_child = None;
|
||||||
|
|
||||||
for self.next_sibling.iter().advance |flow| {
|
for flow in self.next_sibling.iter() {
|
||||||
flow.teardown();
|
flow.teardown();
|
||||||
}
|
}
|
||||||
self.next_sibling = None;
|
self.next_sibling = None;
|
||||||
|
@ -164,8 +159,50 @@ impl TreeNodeRef<FlowData> for FlowContext {
|
||||||
TableFlow(info) => callback(info),
|
TableFlow(info) => callback(info),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parent_node(node: &FlowData) -> Option<FlowContext> {
|
||||||
|
node.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn first_child(node: &FlowData) -> Option<FlowContext> {
|
||||||
|
node.first_child
|
||||||
|
}
|
||||||
|
|
||||||
|
fn last_child(node: &FlowData) -> Option<FlowContext> {
|
||||||
|
node.last_child
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prev_sibling(node: &FlowData) -> Option<FlowContext> {
|
||||||
|
node.prev_sibling
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_sibling(node: &FlowData) -> Option<FlowContext> {
|
||||||
|
node.next_sibling
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent_node(node: &mut FlowData, new_parent_node: Option<FlowContext>) {
|
||||||
|
node.parent = new_parent_node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_first_child(node: &mut FlowData, new_first_child: Option<FlowContext>) {
|
||||||
|
node.first_child = new_first_child
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_last_child(node: &mut FlowData, new_last_child: Option<FlowContext>) {
|
||||||
|
node.last_child = new_last_child
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_prev_sibling(node: &mut FlowData, new_prev_sibling: Option<FlowContext>) {
|
||||||
|
node.prev_sibling = new_prev_sibling
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_next_sibling(node: &mut FlowData, new_next_sibling: Option<FlowContext>) {
|
||||||
|
node.next_sibling = new_next_sibling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TreeNode<FlowContext> for FlowData { }
|
||||||
|
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
///
|
///
|
||||||
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
|
/// FIXME: We need a naming convention for pseudo-inheritance like this. How about
|
||||||
|
@ -196,45 +233,20 @@ pub struct FlowData {
|
||||||
is_inorder: bool,
|
is_inorder: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeNode<FlowContext> for FlowData {
|
pub struct BoxIterator {
|
||||||
fn parent_node(&self) -> Option<FlowContext> {
|
priv boxes: ~[RenderBox],
|
||||||
self.parent
|
priv index: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn first_child(&self) -> Option<FlowContext> {
|
impl Iterator<RenderBox> for BoxIterator {
|
||||||
self.first_child
|
fn next(&mut self) -> Option<RenderBox> {
|
||||||
|
if self.index >= self.boxes.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let v = self.boxes[self.index].clone();
|
||||||
|
self.index += 1;
|
||||||
|
Some(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn last_child(&self) -> Option<FlowContext> {
|
|
||||||
self.last_child
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prev_sibling(&self) -> Option<FlowContext> {
|
|
||||||
self.prev_sibling
|
|
||||||
}
|
|
||||||
|
|
||||||
fn next_sibling(&self) -> Option<FlowContext> {
|
|
||||||
self.next_sibling
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent_node(&mut self, new_parent_node: Option<FlowContext>) {
|
|
||||||
self.parent = new_parent_node
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_first_child(&mut self, new_first_child: Option<FlowContext>) {
|
|
||||||
self.first_child = new_first_child
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_last_child(&mut self, new_last_child: Option<FlowContext>) {
|
|
||||||
self.last_child = new_last_child
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_prev_sibling(&mut self, new_prev_sibling: Option<FlowContext>) {
|
|
||||||
self.prev_sibling = new_prev_sibling
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_next_sibling(&mut self, new_next_sibling: Option<FlowContext>) {
|
|
||||||
self.next_sibling = new_next_sibling
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,43 +420,15 @@ impl<'self> FlowContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_all_boxes(&self, cb: &fn(RenderBox) -> bool) -> bool {
|
pub fn iter_all_boxes(&self) -> BoxIterator {
|
||||||
match *self {
|
BoxIterator {
|
||||||
BlockFlow(block) => {
|
boxes: match *self {
|
||||||
let block = &mut *block;
|
BlockFlow (block) => block.box.map_default(~[], |&x| ~[x]),
|
||||||
for block.box.iter().advance |box| {
|
InlineFlow(inline) => inline.boxes.clone(),
|
||||||
if !cb(*box) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InlineFlow(inline) => {
|
|
||||||
let inline = &mut *inline;
|
|
||||||
for inline.boxes.iter().advance |box| {
|
|
||||||
if !cb(*box) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 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))
|
||||||
|
},
|
||||||
|
index: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn iter_boxes_for_node(&self,
|
|
||||||
node: AbstractNode<LayoutView>,
|
|
||||||
callback: &fn(RenderBox) -> bool)
|
|
||||||
-> bool {
|
|
||||||
for self.iter_all_boxes |box| {
|
|
||||||
if box.node() == node {
|
|
||||||
if !callback(box) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dumps the flow tree for debugging.
|
/// Dumps the flow tree for debugging.
|
||||||
|
@ -455,7 +439,7 @@ impl<'self> FlowContext {
|
||||||
/// Dumps the flow tree, for debugging, with indentation.
|
/// Dumps the flow tree, for debugging, with indentation.
|
||||||
pub fn dump_indent(&self, indent: uint) {
|
pub fn dump_indent(&self, indent: uint) {
|
||||||
let mut s = ~"|";
|
let mut s = ~"|";
|
||||||
for uint::range(0, indent) |_i| {
|
for _ in range(0, indent) {
|
||||||
s.push_str("---- ");
|
s.push_str("---- ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +447,7 @@ impl<'self> FlowContext {
|
||||||
stderr().write_line(s);
|
stderr().write_line(s);
|
||||||
|
|
||||||
// FIXME: this should have a pure/const version?
|
// FIXME: this should have a pure/const version?
|
||||||
for self.each_child |child| {
|
for child in self.children() {
|
||||||
child.dump_indent(indent + 1)
|
child.dump_indent(indent + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,9 @@ use newcss::values::{CSSTextAlignLeft, CSSTextAlignCenter, CSSTextAlignRight, CS
|
||||||
use newcss::units::{Em, Px, Pt};
|
use newcss::units::{Em, Px, Pt};
|
||||||
use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage};
|
use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLength, CSSLineHeightPercentage};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::TreeNodeRef;
|
||||||
use extra::deque::Deque;
|
use extra::container::Deque;
|
||||||
|
use extra::ringbuf::RingBuf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Lineboxes are represented as offsets into the child list, rather than
|
Lineboxes are represented as offsets into the child list, rather than
|
||||||
|
@ -62,7 +63,7 @@ struct LineboxScanner {
|
||||||
flow: FlowContext,
|
flow: FlowContext,
|
||||||
floats: FloatContext,
|
floats: FloatContext,
|
||||||
new_boxes: ~[RenderBox],
|
new_boxes: ~[RenderBox],
|
||||||
work_list: @mut Deque<RenderBox>,
|
work_list: @mut RingBuf<RenderBox>,
|
||||||
pending_line: LineBox,
|
pending_line: LineBox,
|
||||||
lines: ~[LineBox],
|
lines: ~[LineBox],
|
||||||
cur_y: Au,
|
cur_y: Au,
|
||||||
|
@ -76,7 +77,7 @@ impl LineboxScanner {
|
||||||
flow: inline,
|
flow: inline,
|
||||||
floats: float_ctx,
|
floats: float_ctx,
|
||||||
new_boxes: ~[],
|
new_boxes: ~[],
|
||||||
work_list: @mut Deque::new(),
|
work_list: @mut RingBuf::new(),
|
||||||
pending_line: LineBox {
|
pending_line: LineBox {
|
||||||
range: Range::empty(),
|
range: Range::empty(),
|
||||||
bounds: Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0))),
|
bounds: Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0))),
|
||||||
|
@ -122,7 +123,7 @@ impl LineboxScanner {
|
||||||
debug!("LineboxScanner: Working with box from box list: b%d", box.id());
|
debug!("LineboxScanner: Working with box from box list: b%d", box.id());
|
||||||
box
|
box
|
||||||
} else {
|
} else {
|
||||||
let box = self.work_list.pop_front();
|
let box = self.work_list.pop_front().unwrap();
|
||||||
debug!("LineboxScanner: Working with box from work list: b%d", box.id());
|
debug!("LineboxScanner: Working with box from work list: b%d", box.id());
|
||||||
box
|
box
|
||||||
};
|
};
|
||||||
|
@ -176,7 +177,7 @@ impl LineboxScanner {
|
||||||
match box {
|
match box {
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
let size = image_box.image.get_size();
|
let size = image_box.image.get_size();
|
||||||
let height = Au::from_px(size.get_or_default(Size2D(0, 0)).height);
|
let height = Au::from_px(size.unwrap_or_default(Size2D(0, 0)).height);
|
||||||
image_box.base.position.size.height = height;
|
image_box.base.position.size.height = height;
|
||||||
debug!("box_height: found image height: %?", height);
|
debug!("box_height: found image height: %?", height);
|
||||||
height
|
height
|
||||||
|
@ -360,11 +361,11 @@ impl LineboxScanner {
|
||||||
self.pending_line.green_zone = next_green_zone;
|
self.pending_line.green_zone = next_green_zone;
|
||||||
|
|
||||||
assert!(!line_is_empty, "Non-terminating line breaking");
|
assert!(!line_is_empty, "Non-terminating line breaking");
|
||||||
self.work_list.add_front(in_box);
|
self.work_list.push_front(in_box);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
debug!("LineboxScanner: case=adding box collides vertically with floats: breaking line");
|
debug!("LineboxScanner: case=adding box collides vertically with floats: breaking line");
|
||||||
self.work_list.add_front(in_box);
|
self.work_list.push_front(in_box);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -407,7 +408,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.add_front(right_box);
|
self.work_list.push_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),
|
||||||
|
@ -423,7 +424,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.add_front(right_box);
|
self.work_list.push_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);
|
||||||
|
@ -438,7 +439,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.add_front(in_box);
|
self.work_list.push_front(in_box);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -491,7 +492,7 @@ impl InlineFlowData {
|
||||||
|
|
||||||
pub fn teardown(&mut self) {
|
pub fn teardown(&mut self) {
|
||||||
self.common.teardown();
|
self.common.teardown();
|
||||||
for self.boxes.iter().advance |box| {
|
for box in self.boxes.iter() {
|
||||||
box.teardown();
|
box.teardown();
|
||||||
}
|
}
|
||||||
self.boxes = ~[];
|
self.boxes = ~[];
|
||||||
|
@ -515,7 +516,7 @@ impl InlineFlowData {
|
||||||
pub fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) {
|
pub fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) {
|
||||||
let mut num_floats = 0;
|
let mut num_floats = 0;
|
||||||
|
|
||||||
for InlineFlow(self).each_child |kid| {
|
for kid in InlineFlow(self).children() {
|
||||||
do kid.with_mut_base |base| {
|
do kid.with_mut_base |base| {
|
||||||
num_floats += base.num_floats;
|
num_floats += base.num_floats;
|
||||||
base.floats_in = FloatContext::new(base.num_floats);
|
base.floats_in = FloatContext::new(base.num_floats);
|
||||||
|
@ -528,7 +529,7 @@ impl InlineFlowData {
|
||||||
let mut min_width = Au(0);
|
let mut min_width = Au(0);
|
||||||
let mut pref_width = Au(0);
|
let mut pref_width = Au(0);
|
||||||
|
|
||||||
for this.boxes.iter().advance |box| {
|
for box in this.boxes.iter() {
|
||||||
debug!("FlowContext[%d]: measuring %s", self.common.id, box.debug_str());
|
debug!("FlowContext[%d]: measuring %s", self.common.id, box.debug_str());
|
||||||
min_width = Au::max(min_width, box.get_min_width(ctx));
|
min_width = Au::max(min_width, box.get_min_width(ctx));
|
||||||
pref_width = Au::max(pref_width, box.get_pref_width(ctx));
|
pref_width = Au::max(pref_width, box.get_pref_width(ctx));
|
||||||
|
@ -549,11 +550,11 @@ impl InlineFlowData {
|
||||||
// `RenderBox`.
|
// `RenderBox`.
|
||||||
{
|
{
|
||||||
let this = &mut *self;
|
let this = &mut *self;
|
||||||
for this.boxes.iter().advance |&box| {
|
for &box in this.boxes.iter() {
|
||||||
match box {
|
match box {
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
let size = image_box.image.get_size();
|
let size = image_box.image.get_size();
|
||||||
let width = Au::from_px(size.get_or_default(Size2D(0, 0)).width);
|
let width = Au::from_px(size.unwrap_or_default(Size2D(0, 0)).width);
|
||||||
image_box.base.position.size.width = width;
|
image_box.base.position.size.width = width;
|
||||||
}
|
}
|
||||||
TextRenderBoxClass(_) => {
|
TextRenderBoxClass(_) => {
|
||||||
|
@ -571,7 +572,7 @@ impl InlineFlowData {
|
||||||
} // End of for loop.
|
} // End of for loop.
|
||||||
}
|
}
|
||||||
|
|
||||||
for InlineFlow(self).each_child |kid| {
|
for kid in InlineFlow(self).children() {
|
||||||
do kid.with_mut_base |base| {
|
do kid.with_mut_base |base| {
|
||||||
base.position.size.width = self.common.position.size.width;
|
base.position.size.width = self.common.position.size.width;
|
||||||
base.is_inorder = self.common.is_inorder;
|
base.is_inorder = self.common.is_inorder;
|
||||||
|
@ -587,7 +588,7 @@ impl InlineFlowData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_height_inorder_inline(@mut self, ctx: &mut LayoutContext) {
|
pub fn assign_height_inorder_inline(@mut self, ctx: &mut LayoutContext) {
|
||||||
for InlineFlow(self).each_child |kid| {
|
for kid in InlineFlow(self).children() {
|
||||||
kid.assign_height_inorder(ctx);
|
kid.assign_height_inorder(ctx);
|
||||||
}
|
}
|
||||||
self.assign_height_inline(ctx);
|
self.assign_height_inline(ctx);
|
||||||
|
@ -607,7 +608,7 @@ impl InlineFlowData {
|
||||||
scanner.scan_for_lines();
|
scanner.scan_for_lines();
|
||||||
|
|
||||||
// Now, go through each line and lay out the boxes inside
|
// Now, go through each line and lay out the boxes inside
|
||||||
for self.lines.iter().advance |line| {
|
for line in self.lines.iter() {
|
||||||
// We need to distribute extra width based on text-align.
|
// We need to distribute extra width based on text-align.
|
||||||
let mut slack_width = line.green_zone.width - line.bounds.size.width;
|
let mut slack_width = line.green_zone.width - line.bounds.size.width;
|
||||||
if slack_width < Au(0) {
|
if slack_width < Au(0) {
|
||||||
|
@ -633,7 +634,7 @@ impl InlineFlowData {
|
||||||
// So sorry, but justified text is more complicated than shuffling linebox coordinates.
|
// So sorry, but justified text is more complicated than shuffling linebox coordinates.
|
||||||
// TODO(Issue #213): implement `text-align: justify`
|
// TODO(Issue #213): implement `text-align: justify`
|
||||||
CSSTextAlignLeft | CSSTextAlignJustify => {
|
CSSTextAlignLeft | CSSTextAlignJustify => {
|
||||||
for line.range.eachi |i| {
|
for i in line.range.eachi() {
|
||||||
do self.boxes[i].with_mut_base |base| {
|
do self.boxes[i].with_mut_base |base| {
|
||||||
base.position.origin.x = offset_x;
|
base.position.origin.x = offset_x;
|
||||||
offset_x = offset_x + base.position.size.width;
|
offset_x = offset_x + base.position.size.width;
|
||||||
|
@ -642,7 +643,7 @@ impl InlineFlowData {
|
||||||
}
|
}
|
||||||
CSSTextAlignCenter => {
|
CSSTextAlignCenter => {
|
||||||
offset_x = offset_x + slack_width.scale_by(0.5f);
|
offset_x = offset_x + slack_width.scale_by(0.5f);
|
||||||
for line.range.eachi |i| {
|
for i in line.range.eachi() {
|
||||||
do self.boxes[i].with_mut_base |base| {
|
do self.boxes[i].with_mut_base |base| {
|
||||||
base.position.origin.x = offset_x;
|
base.position.origin.x = offset_x;
|
||||||
offset_x = offset_x + base.position.size.width;
|
offset_x = offset_x + base.position.size.width;
|
||||||
|
@ -651,7 +652,7 @@ impl InlineFlowData {
|
||||||
}
|
}
|
||||||
CSSTextAlignRight => {
|
CSSTextAlignRight => {
|
||||||
offset_x = offset_x + slack_width;
|
offset_x = offset_x + slack_width;
|
||||||
for line.range.eachi |i| {
|
for i in line.range.eachi() {
|
||||||
do self.boxes[i].with_mut_base |base| {
|
do self.boxes[i].with_mut_base |base| {
|
||||||
base.position.origin.x = offset_x;
|
base.position.origin.x = offset_x;
|
||||||
offset_x = offset_x + base.position.size.width;
|
offset_x = offset_x + base.position.size.width;
|
||||||
|
@ -665,13 +666,13 @@ impl InlineFlowData {
|
||||||
// the baseline.
|
// the baseline.
|
||||||
let mut baseline_offset = Au(0);
|
let mut baseline_offset = Au(0);
|
||||||
let mut max_height = Au(0);
|
let mut max_height = Au(0);
|
||||||
for line.range.eachi |box_i| {
|
for box_i in line.range.eachi() {
|
||||||
let cur_box = self.boxes[box_i];
|
let cur_box = self.boxes[box_i];
|
||||||
|
|
||||||
match cur_box {
|
match cur_box {
|
||||||
ImageRenderBoxClass(image_box) => {
|
ImageRenderBoxClass(image_box) => {
|
||||||
let size = image_box.image.get_size();
|
let size = image_box.image.get_size();
|
||||||
let height = Au::from_px(size.get_or_default(Size2D(0, 0)).height);
|
let height = Au::from_px(size.unwrap_or_default(Size2D(0, 0)).height);
|
||||||
image_box.base.position.size.height = height;
|
image_box.base.position.size.height = height;
|
||||||
|
|
||||||
image_box.base.position.translate(&Point2D(Au(0), -height))
|
image_box.base.position.translate(&Point2D(Au(0), -height))
|
||||||
|
@ -718,7 +719,7 @@ impl InlineFlowData {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go back and adjust the Y coordinates to match the baseline we determined.
|
// Now go back and adjust the Y coordinates to match the baseline we determined.
|
||||||
for line.range.eachi |box_i| {
|
for box_i in line.range.eachi() {
|
||||||
let cur_box = self.boxes[box_i];
|
let cur_box = self.boxes[box_i];
|
||||||
|
|
||||||
// TODO(#226): This is completely wrong. We need to use the element's `line-height`
|
// TODO(#226): This is completely wrong. We need to use the element's `line-height`
|
||||||
|
@ -765,7 +766,7 @@ impl InlineFlowData {
|
||||||
self.common.id,
|
self.common.id,
|
||||||
self.boxes.len());
|
self.boxes.len());
|
||||||
|
|
||||||
for self.boxes.iter().advance |box| {
|
for box in self.boxes.iter() {
|
||||||
box.build_display_list(builder, dirty, &self.common.abs_position, list)
|
box.build_display_list(builder, dirty, &self.common.abs_position, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,10 @@ use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
|
use servo_msg::constellation_msg::{ConstellationChan, PipelineId};
|
||||||
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
use servo_net::image_cache_task::{ImageCacheTask, ImageResponseMsg};
|
||||||
use servo_net::local_image_cache::LocalImageCache;
|
use servo_net::local_image_cache::LocalImageCache;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::TreeNodeRef;
|
||||||
use servo_util::time::{ProfilerChan, profile};
|
use servo_util::time::{ProfilerChan, profile};
|
||||||
use servo_util::time;
|
use servo_util::time;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
struct LayoutTask {
|
struct LayoutTask {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
|
@ -181,7 +181,7 @@ impl LayoutTask {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Bad copy!
|
// FIXME: Bad copy!
|
||||||
let doc_url = copy data.url;
|
let doc_url = data.url.clone();
|
||||||
let script_chan = data.script_chan.clone();
|
let script_chan = data.script_chan.clone();
|
||||||
|
|
||||||
debug!("layout: received layout request for: %s", doc_url.to_str());
|
debug!("layout: received layout request for: %s", doc_url.to_str());
|
||||||
|
@ -232,7 +232,7 @@ impl LayoutTask {
|
||||||
|
|
||||||
// Propagate restyle damage up and down the tree, as appropriate.
|
// Propagate restyle damage up and down the tree, as appropriate.
|
||||||
// FIXME: Merge this with flow tree building and/or the other traversals.
|
// FIXME: Merge this with flow tree building and/or the other traversals.
|
||||||
for layout_root.traverse_preorder |flow| {
|
for flow in layout_root.traverse_preorder() {
|
||||||
// Also set any damage implied by resize.
|
// Also set any damage implied by resize.
|
||||||
if resized {
|
if resized {
|
||||||
do flow.with_mut_base |base| {
|
do flow.with_mut_base |base| {
|
||||||
|
@ -242,7 +242,7 @@ impl LayoutTask {
|
||||||
|
|
||||||
let prop = flow.with_base(|base| base.restyle_damage.propagate_down());
|
let prop = flow.with_base(|base| base.restyle_damage.propagate_down());
|
||||||
if prop.is_nonempty() {
|
if prop.is_nonempty() {
|
||||||
for flow.each_child |kid_ctx| {
|
for kid_ctx in flow.children() {
|
||||||
do kid_ctx.with_mut_base |kid| {
|
do kid_ctx.with_mut_base |kid| {
|
||||||
kid.restyle_damage.union_in_place(prop);
|
kid.restyle_damage.union_in_place(prop);
|
||||||
}
|
}
|
||||||
|
@ -250,8 +250,8 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for layout_root.traverse_postorder |flow| {
|
for flow in layout_root.traverse_postorder() {
|
||||||
for flow.each_child |child| {
|
for child in flow.children() {
|
||||||
do child.with_base |child_base| {
|
do child.with_base |child_base| {
|
||||||
do flow.with_mut_base |base| {
|
do flow.with_mut_base |base| {
|
||||||
base.restyle_damage.union_in_place(child_base.restyle_damage);
|
base.restyle_damage.union_in_place(child_base.restyle_damage);
|
||||||
|
@ -266,20 +266,20 @@ impl LayoutTask {
|
||||||
// Perform the primary layout passes over the flow tree to compute the locations of all
|
// Perform the primary layout passes over the flow tree to compute the locations of all
|
||||||
// the boxes.
|
// the boxes.
|
||||||
do profile(time::LayoutMainCategory, self.profiler_chan.clone()) {
|
do profile(time::LayoutMainCategory, self.profiler_chan.clone()) {
|
||||||
for layout_root.traverse_postorder_prune(|f| f.restyle_damage().lacks(BubbleWidths)) |flow| {
|
for flow in layout_root.traverse_postorder_prune(|f| f.restyle_damage().lacks(BubbleWidths)) {
|
||||||
flow.bubble_widths(&mut layout_ctx);
|
flow.bubble_widths(&mut layout_ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: We want to do
|
// FIXME: We want to do
|
||||||
// for layout_root.traverse_preorder_prune(|f| f.restyle_damage().lacks(Reflow)) |flow| {
|
// for flow in layout_root.traverse_preorder_prune(|f| f.restyle_damage().lacks(Reflow)) {
|
||||||
// but FloatContext values can't be reused, so we need to recompute them every time.
|
// but FloatContext values can't be reused, so we need to recompute them every time.
|
||||||
for layout_root.traverse_preorder |flow| {
|
for flow in layout_root.traverse_preorder() {
|
||||||
flow.assign_widths(&mut layout_ctx);
|
flow.assign_widths(&mut layout_ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
// For now, this is an inorder traversal
|
// For now, this is an inorder traversal
|
||||||
// FIXME: prune this traversal as well
|
// FIXME: prune this traversal as well
|
||||||
for layout_root.traverse_bu_sub_inorder |flow| {
|
do layout_root.traverse_bu_sub_inorder |flow| {
|
||||||
flow.assign_height(&mut layout_ctx);
|
flow.assign_height(&mut layout_ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,9 +366,11 @@ impl LayoutTask {
|
||||||
None => Err(()),
|
None => Err(()),
|
||||||
Some(flow) => {
|
Some(flow) => {
|
||||||
let mut boxes = ~[];
|
let mut boxes = ~[];
|
||||||
for flow.iter_boxes_for_node(node) |box| {
|
for box in flow.iter_all_boxes() {
|
||||||
|
if box.node() == node {
|
||||||
boxes.push(box.content_box());
|
boxes.push(box.content_box());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(ContentBoxesResponse(boxes))
|
Ok(ContentBoxesResponse(boxes))
|
||||||
}
|
}
|
||||||
|
@ -382,7 +384,7 @@ impl LayoutTask {
|
||||||
transmute(node)
|
transmute(node)
|
||||||
};
|
};
|
||||||
let mut flow_node: AbstractNode<LayoutView> = node;
|
let mut flow_node: AbstractNode<LayoutView> = node;
|
||||||
for node.traverse_preorder |node| {
|
for node in node.traverse_preorder() {
|
||||||
if node.layout_data().flow.is_some() {
|
if node.layout_data().flow.is_some() {
|
||||||
flow_node = node;
|
flow_node = node;
|
||||||
break;
|
break;
|
||||||
|
@ -413,7 +415,7 @@ impl LayoutTask {
|
||||||
let mut resp = Err(());
|
let mut resp = Err(());
|
||||||
let display_list = &display_list.take().list;
|
let display_list = &display_list.take().list;
|
||||||
// iterate in reverse to ensure we have the most recently painted render box
|
// iterate in reverse to ensure we have the most recently painted render box
|
||||||
for display_list.rev_iter().advance |display_item| {
|
for display_item in display_list.rev_iter() {
|
||||||
let bounds = display_item.bounds();
|
let bounds = display_item.bounds();
|
||||||
// TODO this check should really be performed by a method of DisplayItem
|
// TODO this check should really be performed by a method of DisplayItem
|
||||||
if x <= bounds.origin.x + bounds.size.width &&
|
if x <= bounds.origin.x + bounds.size.width &&
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
//! Text layout.
|
//! Text layout.
|
||||||
|
|
||||||
use std::uint;
|
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
use gfx::text::text_run::TextRun;
|
use gfx::text::text_run::TextRun;
|
||||||
|
@ -13,7 +12,6 @@ use layout::box::{RenderBox, RenderBoxBase, TextRenderBox};
|
||||||
use layout::box::{TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
use layout::box::{TextRenderBoxClass, UnscannedTextRenderBoxClass};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
use layout::util::{NodeRange};
|
|
||||||
use newcss::values::{CSSTextDecoration, CSSTextDecorationUnderline};
|
use newcss::values::{CSSTextDecoration, CSSTextDecorationUnderline};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
|
||||||
|
@ -50,7 +48,7 @@ pub trait UnscannedMethods {
|
||||||
impl UnscannedMethods for RenderBox {
|
impl UnscannedMethods for RenderBox {
|
||||||
fn raw_text(&self) -> ~str {
|
fn raw_text(&self) -> ~str {
|
||||||
match *self {
|
match *self {
|
||||||
UnscannedTextRenderBoxClass(text_box) => copy text_box.text,
|
UnscannedTextRenderBoxClass(text_box) => text_box.text.clone(),
|
||||||
_ => fail!(~"unsupported operation: box.raw_text() on non-unscanned text box."),
|
_ => fail!(~"unsupported operation: box.raw_text() on non-unscanned text box."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +73,7 @@ impl TextRunScanner {
|
||||||
|
|
||||||
let mut last_whitespace = true;
|
let mut last_whitespace = true;
|
||||||
let mut out_boxes = ~[];
|
let mut out_boxes = ~[];
|
||||||
for uint::range(0, flow.inline().boxes.len()) |box_i| {
|
for box_i in range(0, flow.inline().boxes.len()) {
|
||||||
debug!("TextRunScanner: considering box: %?", flow.inline().boxes[box_i].debug_str());
|
debug!("TextRunScanner: considering box: %?", flow.inline().boxes[box_i].debug_str());
|
||||||
if box_i > 0 && !can_coalesce_text_nodes(flow.inline().boxes, box_i-1, box_i) {
|
if box_i > 0 && !can_coalesce_text_nodes(flow.inline().boxes, box_i-1, box_i) {
|
||||||
last_whitespace = self.flush_clump_to_list(ctx, flow, last_whitespace, &mut out_boxes);
|
last_whitespace = self.flush_clump_to_list(ctx, flow, last_whitespace, &mut out_boxes);
|
||||||
|
@ -204,7 +202,7 @@ impl TextRunScanner {
|
||||||
let mut run_str: ~str = ~"";
|
let mut run_str: ~str = ~"";
|
||||||
let mut new_ranges: ~[Range] = ~[];
|
let mut new_ranges: ~[Range] = ~[];
|
||||||
let mut char_total = 0;
|
let mut char_total = 0;
|
||||||
for uint::range(0, transformed_strs.len()) |i| {
|
for i in range(0, transformed_strs.len()) {
|
||||||
let added_chars = transformed_strs[i].char_len();
|
let added_chars = transformed_strs[i].char_len();
|
||||||
new_ranges.push(Range::new(char_total, added_chars));
|
new_ranges.push(Range::new(char_total, added_chars));
|
||||||
run_str.push_str(transformed_strs[i]);
|
run_str.push_str(transformed_strs[i]);
|
||||||
|
@ -231,7 +229,7 @@ impl TextRunScanner {
|
||||||
|
|
||||||
// Make new boxes with the run and adjusted text indices.
|
// Make new boxes with the run and adjusted text indices.
|
||||||
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
|
debug!("TextRunScanner: pushing box(es) in range: %?", self.clump);
|
||||||
for clump.eachi |i| {
|
for i in clump.eachi() {
|
||||||
let range = new_ranges[i - self.clump.begin()];
|
let range = new_ranges[i - self.clump.begin()];
|
||||||
if range.length() == 0 {
|
if range.length() == 0 {
|
||||||
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
||||||
|
@ -241,7 +239,7 @@ impl TextRunScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
do in_boxes[i].with_base |base| {
|
do in_boxes[i].with_base |base| {
|
||||||
let new_box = @mut adapt_textbox_with_range(*base, run.get(), range);
|
let new_box = @mut adapt_textbox_with_range(*base, run.unwrap(), range);
|
||||||
out_boxes.push(TextRenderBoxClass(new_box));
|
out_boxes.push(TextRenderBoxClass(new_box));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,19 +247,19 @@ impl TextRunScanner {
|
||||||
} // End of match.
|
} // End of match.
|
||||||
|
|
||||||
debug!("--- In boxes: ---");
|
debug!("--- In boxes: ---");
|
||||||
for in_boxes.iter().enumerate().advance |(i, box)| {
|
for (i, box) in in_boxes.iter().enumerate() {
|
||||||
debug!("%u --> %s", i, box.debug_str());
|
debug!("%u --> %s", i, box.debug_str());
|
||||||
}
|
}
|
||||||
debug!("------------------");
|
debug!("------------------");
|
||||||
|
|
||||||
debug!("--- Out boxes: ---");
|
debug!("--- Out boxes: ---");
|
||||||
for out_boxes.iter().enumerate().advance |(i, box)| {
|
for (i, box) in out_boxes.iter().enumerate() {
|
||||||
debug!("%u --> %s", i, box.debug_str());
|
debug!("%u --> %s", i, box.debug_str());
|
||||||
}
|
}
|
||||||
debug!("------------------");
|
debug!("------------------");
|
||||||
|
|
||||||
debug!("--- Elem ranges: ---");
|
debug!("--- Elem ranges: ---");
|
||||||
for inline.elems.eachi_mut |i: uint, nr: &NodeRange| {
|
for (i, nr) in inline.elems.eachi() {
|
||||||
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str()); ()
|
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str()); ()
|
||||||
}
|
}
|
||||||
debug!("--------------------");
|
debug!("--------------------");
|
||||||
|
|
|
@ -6,6 +6,9 @@ use layout::box::{RenderBox};
|
||||||
use script::dom::node::{AbstractNode, LayoutView};
|
use script::dom::node::{AbstractNode, LayoutView};
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
|
|
||||||
|
use std::iterator::Enumerate;
|
||||||
|
use std::vec::VecIterator;
|
||||||
|
|
||||||
pub struct NodeRange {
|
pub struct NodeRange {
|
||||||
node: AbstractNode<LayoutView>,
|
node: AbstractNode<LayoutView>,
|
||||||
range: Range,
|
range: Range,
|
||||||
|
@ -13,7 +16,7 @@ pub struct NodeRange {
|
||||||
|
|
||||||
impl NodeRange {
|
impl NodeRange {
|
||||||
pub fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
pub fn new(node: AbstractNode<LayoutView>, range: &Range) -> NodeRange {
|
||||||
NodeRange { node: node, range: copy *range }
|
NodeRange { node: node, range: (*range).clone() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +34,7 @@ impl ElementMapping {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn each(&self, callback: &fn(nr: &NodeRange) -> bool) -> bool {
|
pub fn each(&self, callback: &fn(nr: &NodeRange) -> bool) -> bool {
|
||||||
for self.entries.iter().advance |nr| {
|
for nr in self.entries.iter() {
|
||||||
if !callback(nr) {
|
if !callback(nr) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -39,41 +42,27 @@ impl ElementMapping {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eachi(&self, callback: &fn(i: uint, nr: &NodeRange) -> bool) -> bool {
|
pub fn eachi<'a>(&'a self) -> Enumerate<VecIterator<'a, NodeRange>> {
|
||||||
for self.entries.iter().enumerate().advance |(i, nr)| {
|
self.entries.iter().enumerate()
|
||||||
if !callback(i, nr) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eachi_mut(&self, callback: &fn(i: uint, nr: &NodeRange) -> bool) -> bool {
|
|
||||||
for self.entries.iter().enumerate().advance |(i, nr)| {
|
|
||||||
if !callback(i, nr) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repair_for_box_changes(&mut self, old_boxes: &[RenderBox], new_boxes: &[RenderBox]) {
|
pub fn repair_for_box_changes(&mut self, old_boxes: &[RenderBox], new_boxes: &[RenderBox]) {
|
||||||
let entries = &mut self.entries;
|
let entries = &mut self.entries;
|
||||||
|
|
||||||
debug!("--- Old boxes: ---");
|
debug!("--- Old boxes: ---");
|
||||||
for old_boxes.iter().enumerate().advance |(i, box)| {
|
for (i, box) in old_boxes.iter().enumerate() {
|
||||||
debug!("%u --> %s", i, box.debug_str());
|
debug!("%u --> %s", i, box.debug_str());
|
||||||
}
|
}
|
||||||
debug!("------------------");
|
debug!("------------------");
|
||||||
|
|
||||||
debug!("--- New boxes: ---");
|
debug!("--- New boxes: ---");
|
||||||
for new_boxes.iter().enumerate().advance |(i, box)| {
|
for (i, box) in new_boxes.iter().enumerate() {
|
||||||
debug!("%u --> %s", i, box.debug_str());
|
debug!("%u --> %s", i, box.debug_str());
|
||||||
}
|
}
|
||||||
debug!("------------------");
|
debug!("------------------");
|
||||||
|
|
||||||
debug!("--- Elem ranges before repair: ---");
|
debug!("--- Elem ranges before repair: ---");
|
||||||
for entries.iter().enumerate().advance |(i, nr)| {
|
for (i, nr) in entries.iter().enumerate() {
|
||||||
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str());
|
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str());
|
||||||
}
|
}
|
||||||
debug!("----------------------------------");
|
debug!("----------------------------------");
|
||||||
|
@ -126,7 +115,7 @@ impl ElementMapping {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!("--- Elem ranges after repair: ---");
|
debug!("--- Elem ranges after repair: ---");
|
||||||
for entries.iter().enumerate().advance |(i, nr)| {
|
for (i, nr) in entries.iter().enumerate() {
|
||||||
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str());
|
debug!("%u: %? --> %s", i, nr.range, nr.node.debug_str());
|
||||||
}
|
}
|
||||||
debug!("----------------------------------");
|
debug!("----------------------------------");
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use compositing::CompositorChan;
|
use compositing::CompositorChan;
|
||||||
use gfx::render_task::{RenderChan, RenderTask};
|
use gfx::render_task::{RenderChan, RenderTask};
|
||||||
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
|
||||||
|
@ -52,7 +52,7 @@ impl Pipeline {
|
||||||
RenderTask::create(id,
|
RenderTask::create(id,
|
||||||
render_port,
|
render_port,
|
||||||
compositor_chan.clone(),
|
compositor_chan.clone(),
|
||||||
copy opts,
|
opts.clone(),
|
||||||
profiler_chan.clone());
|
profiler_chan.clone());
|
||||||
|
|
||||||
LayoutTask::create(id,
|
LayoutTask::create(id,
|
||||||
|
@ -61,7 +61,7 @@ impl Pipeline {
|
||||||
script_pipeline.script_chan.clone(),
|
script_pipeline.script_chan.clone(),
|
||||||
render_chan.clone(),
|
render_chan.clone(),
|
||||||
image_cache_task.clone(),
|
image_cache_task.clone(),
|
||||||
copy opts,
|
opts.clone(),
|
||||||
profiler_chan);
|
profiler_chan);
|
||||||
|
|
||||||
let new_layout_info = NewLayoutInfo {
|
let new_layout_info = NewLayoutInfo {
|
||||||
|
@ -109,7 +109,7 @@ impl Pipeline {
|
||||||
RenderTask::create(id,
|
RenderTask::create(id,
|
||||||
render_port,
|
render_port,
|
||||||
compositor_chan.clone(),
|
compositor_chan.clone(),
|
||||||
copy opts,
|
opts.clone(),
|
||||||
profiler_chan.clone());
|
profiler_chan.clone());
|
||||||
|
|
||||||
LayoutTask::create(id,
|
LayoutTask::create(id,
|
||||||
|
@ -118,7 +118,7 @@ impl Pipeline {
|
||||||
script_chan.clone(),
|
script_chan.clone(),
|
||||||
render_chan.clone(),
|
render_chan.clone(),
|
||||||
image_cache_task,
|
image_cache_task,
|
||||||
copy opts,
|
opts.clone(),
|
||||||
profiler_chan);
|
profiler_chan);
|
||||||
Pipeline::new(id,
|
Pipeline::new(id,
|
||||||
subpage_id,
|
subpage_id,
|
||||||
|
|
|
@ -25,7 +25,7 @@ static THROBBER: [char, ..8] = [ '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯'
|
||||||
pub struct Application;
|
pub struct Application;
|
||||||
|
|
||||||
impl ApplicationMethods for Application {
|
impl ApplicationMethods for Application {
|
||||||
pub fn new() -> Application {
|
fn new() -> Application {
|
||||||
glfw::init();
|
glfw::init();
|
||||||
Application
|
Application
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ extern mod azure;
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod gfx (name = "gfx");
|
extern mod gfx (name = "gfx");
|
||||||
extern mod glfw;
|
extern mod glfw;
|
||||||
extern mod http_client;
|
//extern mod http_client;
|
||||||
extern mod js;
|
extern mod js;
|
||||||
extern mod layers;
|
extern mod layers;
|
||||||
extern mod newcss (name = "css");
|
extern mod newcss (name = "css");
|
||||||
|
@ -39,17 +39,21 @@ use compositing::{CompositorChan, CompositorTask};
|
||||||
use constellation::Constellation;
|
use constellation::Constellation;
|
||||||
use servo_msg::constellation_msg::{ExitMsg, InitLoadUrlMsg};
|
use servo_msg::constellation_msg::{ExitMsg, InitLoadUrlMsg};
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
use gfx::opts;
|
use gfx::opts;
|
||||||
|
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::time::{Profiler, ProfilerChan, PrintMsg};
|
use servo_util::time::{Profiler, ProfilerChan, PrintMsg};
|
||||||
use extra::uv_global_loop;
|
|
||||||
|
|
||||||
pub use gfx::opts::Opts;
|
pub use gfx::opts::Opts;
|
||||||
pub use gfx::text;
|
pub use gfx::text;
|
||||||
pub use servo_util::url::make_url;
|
pub use servo_util::url::make_url;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
|
#[cfg(not(test))]
|
||||||
use std::os;
|
use std::os;
|
||||||
|
use std::rt::rtio::RtioTimer;
|
||||||
|
use std::rt::io::timer::Timer;
|
||||||
|
|
||||||
#[path="compositing/mod.rs"]
|
#[path="compositing/mod.rs"]
|
||||||
pub mod compositing;
|
pub mod compositing;
|
||||||
|
@ -57,8 +61,8 @@ pub mod compositing;
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
|
||||||
pub mod css {
|
pub mod css {
|
||||||
priv mod select_handler;
|
mod select_handler;
|
||||||
priv mod node_util;
|
mod node_util;
|
||||||
|
|
||||||
pub mod select;
|
pub mod select;
|
||||||
pub mod matching;
|
pub mod matching;
|
||||||
|
@ -94,33 +98,43 @@ pub mod platform;
|
||||||
#[path = "util/mod.rs"]
|
#[path = "util/mod.rs"]
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
fn main() {
|
#[cfg(not(test))]
|
||||||
run(&opts::from_cmdline_args(os::args()))
|
#[start]
|
||||||
|
fn start(argc: int, argv: **u8, crate_map: *u8) -> int {
|
||||||
|
do std::rt::start_on_main_thread(argc, argv, crate_map) {
|
||||||
|
let opts = opts::from_cmdline_args(os::args());
|
||||||
|
run(opts)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(opts: &Opts) {
|
fn run(opts: Opts) {
|
||||||
let (shutdown_port, shutdown_chan) = comm::stream();
|
let (shutdown_port, shutdown_chan) = comm::stream();
|
||||||
|
|
||||||
// Create the profiler channel.
|
|
||||||
let (profiler_port, profiler_chan) = comm::stream();
|
let (profiler_port, profiler_chan) = comm::stream();
|
||||||
|
let (compositor_port, compositor_chan) = comm::stream();
|
||||||
|
|
||||||
let profiler_chan = ProfilerChan::new(profiler_chan);
|
let profiler_chan = ProfilerChan::new(profiler_chan);
|
||||||
Profiler::create(profiler_port);
|
Profiler::create(profiler_port);
|
||||||
do opts.profiler_period.map |period| {
|
do opts.profiler_period.map |&period| {
|
||||||
let profiler_chan = profiler_chan.clone();
|
let profiler_chan = profiler_chan.clone();
|
||||||
let period = *period;
|
let period = (period * 1000f) as u64;
|
||||||
do spawn {
|
do spawn {
|
||||||
|
let tm = Timer::new().unwrap();
|
||||||
loop {
|
loop {
|
||||||
extra::timer::sleep(&uv_global_loop::get(),
|
tm.sleep(period);
|
||||||
(period * 1000f) as uint);
|
|
||||||
profiler_chan.send(PrintMsg);
|
profiler_chan.send(PrintMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the compositor.
|
|
||||||
let (compositor_port, compositor_chan) = comm::stream();
|
|
||||||
let compositor_chan = CompositorChan::new(compositor_chan);
|
let compositor_chan = CompositorChan::new(compositor_chan);
|
||||||
CompositorTask::create(opts.clone(), compositor_port, profiler_chan.clone(), shutdown_chan);
|
let profiler_chan_clone = profiler_chan.clone();
|
||||||
|
|
||||||
|
let opts_clone = opts.clone();
|
||||||
|
|
||||||
|
do spawn {
|
||||||
|
let profiler_chan = profiler_chan_clone.clone();
|
||||||
|
let compositor_chan = compositor_chan.clone();
|
||||||
|
|
||||||
|
let opts = &opts_clone.clone();
|
||||||
|
|
||||||
// Create a Servo instance.
|
// Create a Servo instance.
|
||||||
|
|
||||||
|
@ -133,7 +147,7 @@ fn run(opts: &Opts) {
|
||||||
profiler_chan.clone());
|
profiler_chan.clone());
|
||||||
|
|
||||||
// Send the URL command to the constellation.
|
// Send the URL command to the constellation.
|
||||||
for opts.urls.iter().advance |filename| {
|
for filename in opts.urls.iter() {
|
||||||
constellation_chan.send(InitLoadUrlMsg(make_url(filename.clone(), None)))
|
constellation_chan.send(InitLoadUrlMsg(make_url(filename.clone(), None)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,3 +161,12 @@ fn run(opts: &Opts) {
|
||||||
exit_response_from_constellation.recv();
|
exit_response_from_constellation.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let compositor_task = CompositorTask::new(opts,
|
||||||
|
compositor_port,
|
||||||
|
profiler_chan,
|
||||||
|
shutdown_chan);
|
||||||
|
debug!("preparing to enter main loop");
|
||||||
|
compositor_task.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,21 +51,21 @@ pub trait ApplicationMethods {
|
||||||
|
|
||||||
pub trait WindowMethods<A> {
|
pub trait WindowMethods<A> {
|
||||||
/// Creates a new window.
|
/// Creates a new window.
|
||||||
pub fn new(app: &A) -> @mut Self;
|
fn new(app: &A) -> @mut Self;
|
||||||
/// Returns the size of the window.
|
/// Returns the size of the window.
|
||||||
pub fn size(&self) -> Size2D<f32>;
|
fn size(&self) -> Size2D<f32>;
|
||||||
/// Presents the window to the screen (perhaps by page flipping).
|
/// Presents the window to the screen (perhaps by page flipping).
|
||||||
pub fn present(&mut self);
|
fn present(&mut self);
|
||||||
|
|
||||||
/// Spins the event loop and returns the next event.
|
/// Spins the event loop and returns the next event.
|
||||||
pub fn recv(@mut self) -> WindowEvent;
|
fn recv(@mut self) -> WindowEvent;
|
||||||
|
|
||||||
/// Sets the ready state of the current page.
|
/// Sets the ready state of the current page.
|
||||||
pub fn set_ready_state(@mut self, ready_state: ReadyState);
|
fn set_ready_state(@mut self, ready_state: ReadyState);
|
||||||
/// Sets the render state of the current page.
|
/// Sets the render state of the current page.
|
||||||
pub fn set_render_state(@mut self, render_state: RenderState);
|
fn set_render_state(@mut self, render_state: RenderState);
|
||||||
|
|
||||||
/// Returns the hidpi factor of the monitor.
|
/// Returns the hidpi factor of the monitor.
|
||||||
pub fn hidpi_factor(@mut self) -> f32;
|
fn hidpi_factor(@mut self) -> f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub trait RenderListener {
|
||||||
fn new_layer(&self, PipelineId, Size2D<uint>);
|
fn new_layer(&self, PipelineId, Size2D<uint>);
|
||||||
fn resize_layer(&self, PipelineId, Size2D<uint>);
|
fn resize_layer(&self, PipelineId, Size2D<uint>);
|
||||||
fn delete_layer(&self, PipelineId);
|
fn delete_layer(&self, PipelineId);
|
||||||
fn paint(&self, id: PipelineId, layer_buffer_set: arc::ARC<LayerBufferSet>);
|
fn paint(&self, id: PipelineId, layer_buffer_set: arc::Arc<LayerBufferSet>);
|
||||||
fn set_render_state(&self, render_state: RenderState);
|
fn set_render_state(&self, render_state: RenderState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
/// coupling between these two components
|
/// coupling between these two components
|
||||||
|
|
||||||
use std::comm::{Chan, SharedChan};
|
use std::comm::{Chan, SharedChan};
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use extra::future::Future;
|
use extra::future::Future;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
|
|
|
@ -8,18 +8,18 @@ use local_image_cache::LocalImageCache;
|
||||||
|
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
|
|
||||||
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
// FIXME: Nasty coupling here This will be a problem if we want to factor out image handling from
|
||||||
// the network stack. This should probably be factored out into an interface and use dependency
|
// the network stack. This should probably be factored out into an interface and use dependency
|
||||||
// injection.
|
// injection.
|
||||||
|
|
||||||
/// A struct to store image data. The image will be loaded once the first time it is requested,
|
/// A struct to store image data. The image will be loaded once the first time it is requested,
|
||||||
/// and an ARC will be stored. Clones of this ARC are given out on demand.
|
/// and an Arc will be stored. Clones of this Arc are given out on demand.
|
||||||
pub struct ImageHolder {
|
pub struct ImageHolder {
|
||||||
url: Url,
|
url: Url,
|
||||||
image: Option<ARC<~Image>>,
|
image: Option<Arc<~Image>>,
|
||||||
cached_size: Size2D<int>,
|
cached_size: Size2D<int>,
|
||||||
local_image_cache: @mut LocalImageCache,
|
local_image_cache: @mut LocalImageCache,
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ impl ImageHolder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_image(&mut self) -> Option<ARC<~Image>> {
|
pub fn get_image(&mut self) -> Option<Arc<~Image>> {
|
||||||
debug!("get_image() %?", self.url);
|
debug!("get_image() %?", self.url);
|
||||||
|
|
||||||
// If this is the first time we've called this function, load
|
// If this is the first time we've called this function, load
|
||||||
|
|
|
@ -13,8 +13,8 @@ use std::task::spawn;
|
||||||
use std::to_str::ToStr;
|
use std::to_str::ToStr;
|
||||||
use std::util::replace;
|
use std::util::replace;
|
||||||
use std::result;
|
use std::result;
|
||||||
use extra::arc::ARC;
|
use extra::arc::Arc;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
/// Tell the cache that we may need a particular image soon. Must be posted
|
/// Tell the cache that we may need a particular image soon. Must be posted
|
||||||
|
@ -29,7 +29,7 @@ pub enum Msg {
|
||||||
Decode(Url),
|
Decode(Url),
|
||||||
|
|
||||||
/// Used by the decoder tasks to post decoded images back to the cache
|
/// Used by the decoder tasks to post decoded images back to the cache
|
||||||
priv StoreImage(Url, Option<ARC<~Image>>),
|
priv StoreImage(Url, Option<Arc<~Image>>),
|
||||||
|
|
||||||
/// Request an Image object for a URL. If the image is not is not immediately
|
/// Request an Image object for a URL. If the image is not is not immediately
|
||||||
/// available then ImageNotReady is returned.
|
/// available then ImageNotReady is returned.
|
||||||
|
@ -46,7 +46,7 @@ pub enum Msg {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ImageResponseMsg {
|
pub enum ImageResponseMsg {
|
||||||
ImageReady(ARC<~Image>),
|
ImageReady(Arc<~Image>),
|
||||||
ImageNotReady,
|
ImageNotReady,
|
||||||
ImageFailed
|
ImageFailed
|
||||||
}
|
}
|
||||||
|
@ -157,21 +157,22 @@ struct ImageCache {
|
||||||
need_exit: Option<Chan<()>>,
|
need_exit: Option<Chan<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
enum ImageState {
|
enum ImageState {
|
||||||
Init,
|
Init,
|
||||||
Prefetching(AfterPrefetch),
|
Prefetching(AfterPrefetch),
|
||||||
Prefetched(@Cell<~[u8]>),
|
Prefetched(@Cell<~[u8]>),
|
||||||
Decoding,
|
Decoding,
|
||||||
Decoded(@ARC<~Image>),
|
Decoded(@Arc<~Image>),
|
||||||
Failed
|
Failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
enum AfterPrefetch {
|
enum AfterPrefetch {
|
||||||
DoDecode,
|
DoDecode,
|
||||||
DoNotDecode
|
DoNotDecode
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
impl ImageCache {
|
impl ImageCache {
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
let mut msg_handlers: ~[~fn(msg: &Msg)] = ~[];
|
let mut msg_handlers: ~[~fn(msg: &Msg)] = ~[];
|
||||||
|
@ -179,7 +180,7 @@ impl ImageCache {
|
||||||
loop {
|
loop {
|
||||||
let msg = self.port.recv();
|
let msg = self.port.recv();
|
||||||
|
|
||||||
for msg_handlers.iter().advance |handler| {
|
for handler in msg_handlers.iter() {
|
||||||
(*handler)(&msg)
|
(*handler)(&msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +211,7 @@ impl ImageCache {
|
||||||
// Wait until we have no outstanding requests and subtasks
|
// Wait until we have no outstanding requests and subtasks
|
||||||
// before exiting
|
// before exiting
|
||||||
let mut can_exit = true;
|
let mut can_exit = true;
|
||||||
for self.state_map.each_value |state| {
|
for (_, state) in self.state_map.iter() {
|
||||||
match *state {
|
match *state {
|
||||||
Prefetching(*) => can_exit = false,
|
Prefetching(*) => can_exit = false,
|
||||||
Decoding => can_exit = false,
|
Decoding => can_exit = false,
|
||||||
|
@ -231,37 +232,37 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_state(&self, url: Url) -> ImageState {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn set_state(&self, url: Url, state: ImageState) {
|
fn set_state(&self, url: Url, state: ImageState) {
|
||||||
self.state_map.insert(url, state);
|
self.state_map.insert(url, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn prefetch(&self, url: Url) {
|
fn prefetch(&self, url: Url) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Init => {
|
Init => {
|
||||||
let to_cache = self.chan.clone();
|
let to_cache = self.chan.clone();
|
||||||
let resource_task = self.resource_task.clone();
|
let resource_task = self.resource_task.clone();
|
||||||
let url_cell = Cell::new(copy url);
|
let url_cell = Cell::new(url.clone());
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
let url = url_cell.take();
|
let url = url_cell.take();
|
||||||
debug!("image_cache_task: started fetch for %s", url.to_str());
|
debug!("image_cache_task: started fetch for %s", url.to_str());
|
||||||
|
|
||||||
let image = load_image_data(copy url, resource_task.clone());
|
let image = load_image_data(url.clone(), resource_task.clone());
|
||||||
|
|
||||||
let result = if image.is_ok() {
|
let result = if image.is_ok() {
|
||||||
Ok(Cell::new(result::unwrap(image)))
|
Ok(Cell::new(image.unwrap()))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
};
|
};
|
||||||
to_cache.send(StorePrefetchedImageData(copy url, result));
|
to_cache.send(StorePrefetchedImageData(url.clone(), result));
|
||||||
debug!("image_cache_task: ended fetch for %s", (copy url).to_str());
|
debug!("image_cache_task: ended fetch for %s", (url.clone()).to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_state(url, Prefetching(DoNotDecode));
|
self.set_state(url, Prefetching(DoNotDecode));
|
||||||
|
@ -273,20 +274,20 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn store_prefetched_image_data(&self, url: Url, data: Result<Cell<~[u8]>, ()>) {
|
fn store_prefetched_image_data(&self, url: Url, data: Result<Cell<~[u8]>, ()>) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Prefetching(next_step) => {
|
Prefetching(next_step) => {
|
||||||
match data {
|
match data {
|
||||||
Ok(data_cell) => {
|
Ok(data_cell) => {
|
||||||
let data = data_cell.take();
|
let data = data_cell.take();
|
||||||
self.set_state(copy url, Prefetched(@Cell::new(data)));
|
self.set_state(url.clone(), Prefetched(@Cell::new(data)));
|
||||||
match next_step {
|
match next_step {
|
||||||
DoDecode => self.decode(url),
|
DoDecode => self.decode(url),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(*) => {
|
Err(*) => {
|
||||||
self.set_state(copy url, Failed);
|
self.set_state(url.clone(), Failed);
|
||||||
self.purge_waiters(url, || ImageFailed);
|
self.purge_waiters(url, || ImageFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,8 +303,8 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn decode(&self, url: Url) {
|
fn decode(&self, url: Url) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Init => fail!(~"decoding image before prefetch"),
|
Init => fail!(~"decoding image before prefetch"),
|
||||||
|
|
||||||
Prefetching(DoNotDecode) => {
|
Prefetching(DoNotDecode) => {
|
||||||
|
@ -320,7 +321,7 @@ impl ImageCache {
|
||||||
|
|
||||||
let data = data_cell.take();
|
let data = data_cell.take();
|
||||||
let to_cache = self.chan.clone();
|
let to_cache = self.chan.clone();
|
||||||
let url_cell = Cell::new(copy url);
|
let url_cell = Cell::new(url.clone());
|
||||||
let decode = (self.decoder_factory)();
|
let decode = (self.decoder_factory)();
|
||||||
|
|
||||||
do spawn {
|
do spawn {
|
||||||
|
@ -328,11 +329,11 @@ 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(~image.unwrap()))
|
Some(Arc::new(~image.unwrap()))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
to_cache.send(StoreImage(copy url, image));
|
to_cache.send(StoreImage(url.clone(), image));
|
||||||
debug!("image_cache_task: ended image decode for %s", url.to_str());
|
debug!("image_cache_task: ended image decode for %s", url.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,17 +346,17 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn store_image(&self, url: Url, image: Option<ARC<~Image>>) {
|
fn store_image(&self, url: Url, image: Option<Arc<~Image>>) {
|
||||||
|
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Decoding => {
|
Decoding => {
|
||||||
match image {
|
match image {
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
self.set_state(copy url, Decoded(@image.clone()));
|
self.set_state(url.clone(), Decoded(@image.clone()));
|
||||||
self.purge_waiters(url, || ImageReady(image.clone()) );
|
self.purge_waiters(url, || ImageReady(image.clone()) );
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.set_state(copy url, Failed);
|
self.set_state(url.clone(), Failed);
|
||||||
self.purge_waiters(url, || ImageFailed );
|
self.purge_waiters(url, || ImageFailed );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -372,10 +373,10 @@ impl ImageCache {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn purge_waiters(&self, url: Url, f: &fn() -> ImageResponseMsg) {
|
fn purge_waiters(&self, url: Url, f: &fn() -> ImageResponseMsg) {
|
||||||
match self.wait_map.pop(&url) {
|
match self.wait_map.pop(&url) {
|
||||||
Some(waiters) => {
|
Some(waiters) => {
|
||||||
for waiters.iter().advance |response| {
|
for response in waiters.iter() {
|
||||||
response.send(f());
|
response.send(f());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,8 +384,8 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
fn get_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Init => fail!(~"request for image before prefetch"),
|
Init => fail!(~"request for image before prefetch"),
|
||||||
Prefetching(DoDecode) => response.send(ImageNotReady),
|
Prefetching(DoDecode) => response.send(ImageNotReady),
|
||||||
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
||||||
|
@ -394,8 +395,8 @@ impl ImageCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn wait_for_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
fn wait_for_image(&self, url: Url, response: Chan<ImageResponseMsg>) {
|
||||||
match self.get_state(copy url) {
|
match self.get_state(url.clone()) {
|
||||||
Init => fail!(~"request for image before prefetch"),
|
Init => fail!(~"request for image before prefetch"),
|
||||||
|
|
||||||
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
Prefetching(DoNotDecode) | Prefetched(*) => fail!(~"request for image before decode"),
|
||||||
|
@ -541,7 +542,7 @@ fn should_fail_if_requesting_image_before_requesting_decode() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
// no decode message
|
// no decode message
|
||||||
|
|
||||||
let (chan, _port) = stream();
|
let (chan, _port) = stream();
|
||||||
|
@ -564,7 +565,7 @@ fn should_not_request_url_from_resource_task_on_multiple_prefetches() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Prefetch(url));
|
image_cache_task.send(Prefetch(url));
|
||||||
url_requested.recv();
|
url_requested.recv();
|
||||||
image_cache_task.exit();
|
image_cache_task.exit();
|
||||||
|
@ -587,8 +588,8 @@ fn should_return_image_not_ready_if_data_has_not_arrived() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
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));
|
||||||
assert!(response_port.recv() == ImageNotReady);
|
assert!(response_port.recv() == ImageNotReady);
|
||||||
|
@ -617,8 +618,8 @@ fn should_return_decoded_image_data_if_data_has_arrived() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_image_chan.recv();
|
wait_for_image_chan.recv();
|
||||||
|
@ -654,15 +655,15 @@ fn should_return_decoded_image_data_for_multiple_requests() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_image.recv();
|
wait_for_image.recv();
|
||||||
|
|
||||||
for iter::repeat(2) {
|
for _ in iter::repeat(2) {
|
||||||
let (response_chan, response_port) = stream();
|
let (response_chan, response_port) = stream();
|
||||||
image_cache_task.send(GetImage(copy url, response_chan));
|
image_cache_task.send(GetImage(url.clone(), response_chan));
|
||||||
match response_port.recv() {
|
match response_port.recv() {
|
||||||
ImageReady(_) => (),
|
ImageReady(_) => (),
|
||||||
_ => fail
|
_ => fail
|
||||||
|
@ -700,12 +701,12 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
image_bin_sent.recv();
|
image_bin_sent.recv();
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
|
|
||||||
image_cache_task.exit();
|
image_cache_task.exit();
|
||||||
mock_resource_task.send(resource_task::Exit);
|
mock_resource_task.send(resource_task::Exit);
|
||||||
|
@ -744,14 +745,14 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
image_bin_sent.recv();
|
image_bin_sent.recv();
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
image_cache_task.exit();
|
image_cache_task.exit();
|
||||||
mock_resource_task.send(resource_task::Exit);
|
mock_resource_task.send(resource_task::Exit);
|
||||||
|
@ -784,8 +785,8 @@ fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_prefetech.recv();
|
wait_for_prefetech.recv();
|
||||||
|
@ -822,14 +823,14 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_prefetech.recv();
|
wait_for_prefetech.recv();
|
||||||
|
|
||||||
let (response_chan, response_port) = stream();
|
let (response_chan, response_port) = stream();
|
||||||
image_cache_task.send(GetImage(copy url, response_chan));
|
image_cache_task.send(GetImage(url.clone(), response_chan));
|
||||||
match response_port.recv() {
|
match response_port.recv() {
|
||||||
ImageFailed => (),
|
ImageFailed => (),
|
||||||
_ => fail
|
_ => fail
|
||||||
|
@ -879,8 +880,8 @@ fn should_return_not_ready_if_image_is_still_decoding() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_prefetech.recv();
|
wait_for_prefetech.recv();
|
||||||
|
@ -922,8 +923,8 @@ fn should_return_failed_if_image_decode_fails() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_decode.recv();
|
wait_for_decode.recv();
|
||||||
|
@ -961,8 +962,8 @@ fn should_return_image_on_wait_if_image_is_already_loaded() {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
// Wait until our mock resource task has sent the image to the image cache
|
// Wait until our mock resource task has sent the image to the image cache
|
||||||
wait_for_decode.recv();
|
wait_for_decode.recv();
|
||||||
|
@ -991,8 +992,8 @@ fn should_return_image_on_wait_if_image_is_not_yet_loaded() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
let (response_chan, response_port) = stream();
|
let (response_chan, response_port) = stream();
|
||||||
image_cache_task.send(WaitForImage(url, response_chan));
|
image_cache_task.send(WaitForImage(url, response_chan));
|
||||||
|
@ -1021,8 +1022,8 @@ fn should_return_image_failed_on_wait_if_image_fails_to_load() {
|
||||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
let (response_chan, response_port) = stream();
|
let (response_chan, response_port) = stream();
|
||||||
image_cache_task.send(WaitForImage(url, response_chan));
|
image_cache_task.send(WaitForImage(url, response_chan));
|
||||||
|
@ -1048,8 +1049,8 @@ fn sync_cache_should_wait_for_images() {
|
||||||
let image_cache_task = SyncImageCacheTask(mock_resource_task);
|
let image_cache_task = SyncImageCacheTask(mock_resource_task);
|
||||||
let url = make_url(~"file", None);
|
let url = make_url(~"file", None);
|
||||||
|
|
||||||
image_cache_task.send(Prefetch(copy url));
|
image_cache_task.send(Prefetch(url.clone()));
|
||||||
image_cache_task.send(Decode(copy url));
|
image_cache_task.send(Decode(url.clone()));
|
||||||
|
|
||||||
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));
|
||||||
|
|
|
@ -15,7 +15,7 @@ use std::comm;
|
||||||
use std::comm::Port;
|
use std::comm::Port;
|
||||||
use std::task;
|
use std::task;
|
||||||
use servo_util::url::{UrlMap, url_map};
|
use servo_util::url::{UrlMap, url_map};
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
pub fn LocalImageCache(image_cache_task: ImageCacheTask) -> LocalImageCache {
|
||||||
LocalImageCache {
|
LocalImageCache {
|
||||||
|
@ -33,14 +33,13 @@ pub struct LocalImageCache {
|
||||||
priv state_map: UrlMap<@mut ImageState>
|
priv state_map: UrlMap<@mut ImageState>
|
||||||
}
|
}
|
||||||
|
|
||||||
priv struct ImageState {
|
struct ImageState {
|
||||||
prefetched: bool,
|
prefetched: bool,
|
||||||
decoded: bool,
|
decoded: bool,
|
||||||
last_request_round: uint,
|
last_request_round: uint,
|
||||||
last_response: ImageResponseMsg
|
last_response: ImageResponseMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)] // Using maps of Urls
|
|
||||||
impl LocalImageCache {
|
impl LocalImageCache {
|
||||||
/// The local cache will only do a single remote request for a given
|
/// The local cache will only do a single remote request for a given
|
||||||
/// URL in each 'round'. Layout should call this each time it begins
|
/// URL in each 'round'. Layout should call this each time it begins
|
||||||
|
@ -52,7 +51,7 @@ impl LocalImageCache {
|
||||||
pub fn prefetch(&self, url: &Url) {
|
pub fn prefetch(&self, url: &Url) {
|
||||||
let state = self.get_state(url);
|
let state = self.get_state(url);
|
||||||
if !state.prefetched {
|
if !state.prefetched {
|
||||||
self.image_cache_task.send(Prefetch(copy *url));
|
self.image_cache_task.send(Prefetch((*url).clone()));
|
||||||
state.prefetched = true;
|
state.prefetched = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +59,7 @@ impl LocalImageCache {
|
||||||
pub fn decode(&self, url: &Url) {
|
pub fn decode(&self, url: &Url) {
|
||||||
let state = self.get_state(url);
|
let state = self.get_state(url);
|
||||||
if !state.decoded {
|
if !state.decoded {
|
||||||
self.image_cache_task.send(Decode(copy *url));
|
self.image_cache_task.send(Decode((*url).clone()));
|
||||||
state.decoded = true;
|
state.decoded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +97,7 @@ impl LocalImageCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (response_port, response_chan) = comm::stream();
|
let (response_port, response_chan) = comm::stream();
|
||||||
self.image_cache_task.send(GetImage(copy *url, response_chan));
|
self.image_cache_task.send(GetImage((*url).clone(), response_chan));
|
||||||
|
|
||||||
let response = response_port.recv();
|
let response = response_port.recv();
|
||||||
match response {
|
match response {
|
||||||
|
@ -110,11 +109,11 @@ impl LocalImageCache {
|
||||||
// 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();
|
||||||
assert!(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.unwrap()();
|
||||||
let url = copy *url;
|
let url = (*url).clone();
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
let (response_port, response_chan) = comm::stream();
|
let (response_port, response_chan) = comm::stream();
|
||||||
image_cache_task.send(WaitForImage(copy url, response_chan));
|
image_cache_task.send(WaitForImage(url.clone(), response_chan));
|
||||||
on_image_available(response_port.recv());
|
on_image_available(response_port.recv());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +133,7 @@ impl LocalImageCache {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn get_state(&self, url: &Url) -> @mut ImageState {
|
fn get_state(&self, url: &Url) -> @mut ImageState {
|
||||||
let state = do self.state_map.find_or_insert_with(url.clone()) |_| {
|
let state = do self.state_map.find_or_insert_with(url.clone()) |_| {
|
||||||
let new_state = @mut ImageState {
|
let new_state = @mut ImageState {
|
||||||
prefetched: false,
|
prefetched: false,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#[crate_type = "lib"];
|
#[crate_type = "lib"];
|
||||||
|
|
||||||
extern mod geom;
|
extern mod geom;
|
||||||
extern mod http_client;
|
//extern mod http_client;
|
||||||
extern mod servo_util (name = "util");
|
extern mod servo_util (name = "util");
|
||||||
extern mod stb_image;
|
extern mod stb_image;
|
||||||
extern mod extra;
|
extern mod extra;
|
||||||
|
@ -25,7 +25,7 @@ pub mod image {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod file_loader;
|
pub mod file_loader;
|
||||||
pub mod http_loader;
|
//pub mod http_loader;
|
||||||
pub mod image_cache_task;
|
pub mod image_cache_task;
|
||||||
pub mod local_image_cache;
|
pub mod local_image_cache;
|
||||||
pub mod resource_task;
|
pub mod resource_task;
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
//! A task that takes a URL and streams back the binary data.
|
//! A task that takes a URL and streams back the binary data.
|
||||||
|
|
||||||
use file_loader;
|
use file_loader;
|
||||||
use http_loader;
|
//use http_loader;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm::{Chan, Port, SharedChan};
|
use std::comm::{Chan, Port, SharedChan};
|
||||||
use extra::net::url::{Url, to_str};
|
use extra::url::Url;
|
||||||
use util::spawn_listener;
|
use util::spawn_listener;
|
||||||
|
|
||||||
pub enum ControlMsg {
|
pub enum ControlMsg {
|
||||||
|
@ -43,10 +43,10 @@ pub type LoaderTask = ~fn(url: Url, Chan<ProgressMsg>);
|
||||||
/// Create a ResourceTask with the default loaders
|
/// Create a ResourceTask with the default loaders
|
||||||
pub fn ResourceTask() -> ResourceTask {
|
pub fn ResourceTask() -> ResourceTask {
|
||||||
let file_loader_factory: LoaderTaskFactory = file_loader::factory;
|
let file_loader_factory: LoaderTaskFactory = file_loader::factory;
|
||||||
let http_loader_factory: LoaderTaskFactory = http_loader::factory;
|
//let http_loader_factory: LoaderTaskFactory = http_loader::factory;
|
||||||
let loaders = ~[
|
let loaders = ~[
|
||||||
(~"file", file_loader_factory),
|
(~"file", file_loader_factory),
|
||||||
(~"http", http_loader_factory)
|
//(~"http", http_loader_factory)
|
||||||
];
|
];
|
||||||
create_resource_task_with_loaders(loaders)
|
create_resource_task_with_loaders(loaders)
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ impl ResourceManager {
|
||||||
|
|
||||||
match self.get_loader_factory(&url) {
|
match self.get_loader_factory(&url) {
|
||||||
Some(loader_factory) => {
|
Some(loader_factory) => {
|
||||||
debug!("resource_task: loading url: %s", to_str(&url));
|
debug!("resource_task: loading url: %s", url.to_str());
|
||||||
loader_factory(url, progress_chan);
|
loader_factory(url, progress_chan);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -105,7 +105,7 @@ impl ResourceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_loader_factory(&self, url: &Url) -> Option<LoaderTask> {
|
fn get_loader_factory(&self, url: &Url) -> Option<LoaderTask> {
|
||||||
for self.loaders.iter().advance |scheme_loader| {
|
for scheme_loader in self.loaders.iter() {
|
||||||
match *scheme_loader {
|
match *scheme_loader {
|
||||||
(ref scheme, ref loader_factory) => {
|
(ref scheme, ref loader_factory) => {
|
||||||
if (*scheme) == url.scheme {
|
if (*scheme) == url.scheme {
|
||||||
|
@ -142,7 +142,7 @@ fn test_bad_scheme() {
|
||||||
fn should_delegate_to_scheme_loader() {
|
fn should_delegate_to_scheme_loader() {
|
||||||
let payload = ~[1, 2, 3];
|
let payload = ~[1, 2, 3];
|
||||||
let loader_factory = |_url: Url, progress_chan: Chan<ProgressMsg>| {
|
let loader_factory = |_url: Url, progress_chan: Chan<ProgressMsg>| {
|
||||||
progress_chan.send(Payload(copy payload));
|
progress_chan.send(Payload(payload.clone()));
|
||||||
progress_chan.send(Done(Ok(())));
|
progress_chan.send(Done(Ok(())));
|
||||||
};
|
};
|
||||||
let loader_factories = ~[(~"snicklefritz", loader_factory)];
|
let loader_factories = ~[(~"snicklefritz", loader_factory)];
|
||||||
|
|
|
@ -1044,7 +1044,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
||||||
# " return false;\n"
|
# " return false;\n"
|
||||||
# "}" % (nullBehavior, undefinedBehavior, varName))
|
# "}" % (nullBehavior, undefinedBehavior, varName))
|
||||||
strval = "str(strval.get())"
|
strval = "str(strval.unwrap())"
|
||||||
if isOptional:
|
if isOptional:
|
||||||
strval = "Some(%s)" % strval
|
strval = "Some(%s)" % strval
|
||||||
conversionCode = (
|
conversionCode = (
|
||||||
|
@ -1114,7 +1114,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
" if result.is_err() {\n"
|
" if result.is_err() {\n"
|
||||||
"%(handleInvalidEnumValueCode)s"
|
"%(handleInvalidEnumValueCode)s"
|
||||||
" }\n"
|
" }\n"
|
||||||
" let index = result.get();\n"
|
" let index = result.unwrap();\n"
|
||||||
" ${declName} = cast::transmute(index); //XXXjdm need some range checks up in here\n"
|
" ${declName} = cast::transmute(index); //XXXjdm need some range checks up in here\n"
|
||||||
"}" % { "enumtype" : enum,
|
"}" % { "enumtype" : enum,
|
||||||
"values" : enum + "Values::strings",
|
"values" : enum + "Values::strings",
|
||||||
|
@ -1511,7 +1511,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
wrappingCode = ("if %s.is_none() {\n" % (result) +
|
wrappingCode = ("if %s.is_none() {\n" % (result) +
|
||||||
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
|
CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
|
||||||
"}\n" +
|
"}\n" +
|
||||||
"let mut %s = %s.get();\n" % (result, result))
|
"let mut %s = %s.unwrap();\n" % (result, result))
|
||||||
else:
|
else:
|
||||||
wrappingCode = ""
|
wrappingCode = ""
|
||||||
if (not descriptor.interface.isExternal() and
|
if (not descriptor.interface.isExternal() and
|
||||||
|
@ -2746,10 +2746,10 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
|
||||||
}*/
|
}*/
|
||||||
/* Check to see whether the interface objects are already installed */
|
/* Check to see whether the interface objects are already installed */
|
||||||
let protoOrIfaceArray: *mut *JSObject = cast::transmute(GetProtoOrIfaceArray(aGlobal));
|
let protoOrIfaceArray: *mut *JSObject = cast::transmute(GetProtoOrIfaceArray(aGlobal));
|
||||||
let cachedObject: *JSObject = *protoOrIfaceArray.offset(%s as uint);
|
let cachedObject: *JSObject = *protoOrIfaceArray.offset(%s as int);
|
||||||
if cachedObject.is_null() {
|
if cachedObject.is_null() {
|
||||||
let tmp: *JSObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
|
let tmp: *JSObject = CreateInterfaceObjects(aCx, aGlobal, aReceiver);
|
||||||
*protoOrIfaceArray.offset(%s as uint) = tmp;
|
*protoOrIfaceArray.offset(%s as int) = tmp;
|
||||||
tmp
|
tmp
|
||||||
} else {
|
} else {
|
||||||
cachedObject
|
cachedObject
|
||||||
|
@ -3623,7 +3623,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
||||||
templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_mut_unsafe_ptr(&mut (*desc).value)',
|
templateValues = {'jsvalRef': '(*desc).value', 'jsvalPtr': 'ptr::to_mut_unsafe_ptr(&mut (*desc).value)',
|
||||||
'obj': 'proxy', 'successCode': fillDescriptor}
|
'obj': 'proxy', 'successCode': fillDescriptor}
|
||||||
get = ("if index.is_some() {\n" +
|
get = ("if index.is_some() {\n" +
|
||||||
" let index = index.get();\n" +
|
" let index = index.unwrap();\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
|
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define() + "\n" +
|
||||||
"}\n") % (self.descriptor.concreteType)
|
"}\n") % (self.descriptor.concreteType)
|
||||||
|
@ -3632,7 +3632,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
||||||
setOrIndexedGet += "if set != 0 {\n"
|
setOrIndexedGet += "if set != 0 {\n"
|
||||||
if indexedSetter:
|
if indexedSetter:
|
||||||
setOrIndexedGet += (" if index.is_some() {\n" +
|
setOrIndexedGet += (" if index.is_some() {\n" +
|
||||||
" let index = index.get();\n")
|
" let index = index.unwrap();\n")
|
||||||
if not 'IndexedCreator' in self.descriptor.operations:
|
if not 'IndexedCreator' in self.descriptor.operations:
|
||||||
# FIXME need to check that this is a 'supported property index'
|
# FIXME need to check that this is a 'supported property index'
|
||||||
assert False
|
assert False
|
||||||
|
@ -3677,7 +3677,7 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
|
||||||
" if strval.is_err() {\n" +
|
" if strval.is_err() {\n" +
|
||||||
" return 0;\n" +
|
" return 0;\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" let name = str(strval.get());\n" +
|
" let name = str(strval.unwrap());\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
|
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
|
||||||
|
@ -3721,7 +3721,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
||||||
raise TypeError("Can't handle creator that's different from the setter")
|
raise TypeError("Can't handle creator that's different from the setter")
|
||||||
set += ("let index = GetArrayIndexFromId(cx, id);\n" +
|
set += ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
"if index.is_some() {\n" +
|
"if index.is_some() {\n" +
|
||||||
" let index = index.get();\n" +
|
" let index = index.unwrap();\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
|
CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
|
||||||
" return 1;\n" +
|
" return 1;\n" +
|
||||||
|
@ -3746,7 +3746,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
||||||
" if strval.is_err() {\n" +
|
" if strval.is_err() {\n" +
|
||||||
" return 0;\n" +
|
" return 0;\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" let name = str(strval.get());\n" +
|
" let name = str(strval.unwrap());\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
|
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + "\n" +
|
||||||
|
@ -3762,7 +3762,7 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
|
||||||
" if strval.is_err() {\n" +
|
" if strval.is_err() {\n" +
|
||||||
" return 0;\n" +
|
" return 0;\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" let name = str(strval.get());\n" +
|
" let name = str(strval.unwrap());\n" +
|
||||||
" let this: %%s = UnwrapProxy(proxy);\n" +
|
" let this: %%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
|
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
|
||||||
" if (found) {\n"
|
" if (found) {\n"
|
||||||
|
@ -3787,7 +3787,7 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
|
||||||
if indexedGetter:
|
if indexedGetter:
|
||||||
indexed = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
indexed = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
"if index.is_some() {\n" +
|
"if index.is_some() {\n" +
|
||||||
" let index = index.get();\n" +
|
" let index = index.unwrap();\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
|
CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" +
|
||||||
" *bp = found as JSBool;\n" +
|
" *bp = found as JSBool;\n" +
|
||||||
|
@ -3808,7 +3808,7 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
|
||||||
" if strval.is_err() {\n" +
|
" if strval.is_err() {\n" +
|
||||||
" return 0;\n" +
|
" return 0;\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" let name = str(strval.get());\n" +
|
" let name = str(strval.unwrap());\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" let this: *%s = UnwrapProxy(proxy);\n" +
|
" let this: *%s = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
|
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
|
||||||
|
@ -3861,7 +3861,7 @@ if expando.is_not_null() {
|
||||||
if indexedGetter:
|
if indexedGetter:
|
||||||
getIndexedOrExpando = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
getIndexedOrExpando = ("let index = GetArrayIndexFromId(cx, id);\n" +
|
||||||
"if index.is_some() {\n" +
|
"if index.is_some() {\n" +
|
||||||
" let index = index.get();\n" +
|
" let index = index.unwrap();\n" +
|
||||||
" let this = UnwrapProxy(proxy);\n" +
|
" let this = UnwrapProxy(proxy);\n" +
|
||||||
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define())
|
CGIndenter(CGProxyIndexedGetter(self.descriptor, templateValues)).define())
|
||||||
getIndexedOrExpando += """
|
getIndexedOrExpando += """
|
||||||
|
@ -3935,7 +3935,7 @@ class CGDOMJSProxyHandler_obj_toString(CGAbstractExternMethod):
|
||||||
JSString* jsresult;
|
JSString* jsresult;
|
||||||
return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;"""
|
return xpc_qsStringToJsstring(cx, result, &jsresult) ? jsresult : NULL;"""
|
||||||
|
|
||||||
return """ do str::as_c_str("%s") |s| {
|
return """ do "%s".to_c_str().with_ref |s| {
|
||||||
_obj_toString(cx, s)
|
_obj_toString(cx, s)
|
||||||
}""" % self.descriptor.name
|
}""" % self.descriptor.name
|
||||||
|
|
||||||
|
@ -4461,9 +4461,9 @@ class CGDictionary(CGThing):
|
||||||
# NOTE: jsids are per-runtime, so don't use them in workers
|
# NOTE: jsids are per-runtime, so don't use them in workers
|
||||||
if True or self.workers: #XXXjdm hack until 'static mut' exists for global jsids
|
if True or self.workers: #XXXjdm hack until 'static mut' exists for global jsids
|
||||||
propName = member.identifier.name
|
propName = member.identifier.name
|
||||||
propCheck = ('str::as_c_str("%s", |s| { JS_HasProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&found)) })' %
|
propCheck = ('"%s".to_c_str().with_ref(|s| { JS_HasProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&found)) })' %
|
||||||
propName)
|
propName)
|
||||||
propGet = ('str::as_c_str("%s", |s| { JS_GetProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&temp)) })' %
|
propGet = ('"%s".to_c_str().with_ref(|s| { JS_GetProperty(cx, RUST_JSVAL_TO_OBJECT(val), s, ptr::to_unsafe_ptr(&temp)) })' %
|
||||||
propName)
|
propName)
|
||||||
else:
|
else:
|
||||||
propId = self.makeIdName(member.identifier.name);
|
propId = self.makeIdName(member.identifier.name);
|
||||||
|
|
|
@ -21,8 +21,6 @@ use std::libc::c_uint;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
use std::result;
|
|
||||||
use std::str;
|
|
||||||
use js::glue::*;
|
use js::glue::*;
|
||||||
use js::jsapi::*;
|
use js::jsapi::*;
|
||||||
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
|
use js::jsapi::{JSContext, JSVal, JSObject, JSBool, JSFreeOp, JSPropertySpec};
|
||||||
|
@ -49,14 +47,14 @@ pub extern fn trace(tracer: *mut JSTracer, obj: *JSObject) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
error!("tracing %s", name);
|
error!("tracing %s", name);
|
||||||
let mut node = node.get();
|
let mut node = node.unwrap();
|
||||||
let cache = node.get_wrappercache();
|
let cache = node.get_wrappercache();
|
||||||
let wrapper = cache.get_wrapper();
|
let wrapper = cache.get_wrapper();
|
||||||
assert!(wrapper.is_not_null());
|
assert!(wrapper.is_not_null());
|
||||||
unsafe {
|
unsafe {
|
||||||
(*tracer).debugPrinter = ptr::null();
|
(*tracer).debugPrinter = ptr::null();
|
||||||
(*tracer).debugPrintIndex = -1;
|
(*tracer).debugPrintIndex = -1;
|
||||||
do str::as_c_str(name) |name| {
|
do name.to_c_str().with_ref |name| {
|
||||||
(*tracer).debugPrintArg = name as *libc::c_void;
|
(*tracer).debugPrintArg = name as *libc::c_void;
|
||||||
JS_CallTracer(cast::transmute(tracer), wrapper, JSTRACE_OBJECT as u32);
|
JS_CallTracer(cast::transmute(tracer), wrapper, JSTRACE_OBJECT as u32);
|
||||||
}
|
}
|
||||||
|
@ -194,14 +192,14 @@ extern fn setAttribute(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
if strval.is_err() {
|
if strval.is_err() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arg0 = str(strval.get());
|
arg0 = str(strval.unwrap());
|
||||||
|
|
||||||
let arg1: DOMString;
|
let arg1: DOMString;
|
||||||
let strval = jsval_to_str(cx, (*argv.offset(1)));
|
let strval = jsval_to_str(cx, (*argv.offset(1)));
|
||||||
if strval.is_err() {
|
if strval.is_err() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arg1 = str(strval.get());
|
arg1 = str(strval.unwrap());
|
||||||
|
|
||||||
do node.as_mut_element |elem| {
|
do node.as_mut_element |elem| {
|
||||||
elem.set_attr(&arg0, &arg1);
|
elem.set_attr(&arg0, &arg1);
|
||||||
|
@ -211,7 +209,6 @@ extern fn setAttribute(cx: *JSContext, argc: c_uint, vp: *JSVal) -> JSBool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
||||||
|
@ -241,7 +238,6 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
||||||
|
@ -275,7 +271,7 @@ extern fn getTagName(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
|
|
||||||
let node = unwrap(obj);
|
let node = unwrap(obj);
|
||||||
do node.with_imm_element |elem| {
|
do node.with_imm_element |elem| {
|
||||||
let s = str(copy elem.tag_name);
|
let s = str(elem.tag_name.clone());
|
||||||
*vp = domstring_to_jsval(cx, &s);
|
*vp = domstring_to_jsval(cx, &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,9 +291,9 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
|
||||||
//XXXjdm the parent should probably be the node parent instead of the global
|
//XXXjdm the parent should probably be the node parent instead of the global
|
||||||
//TODO error checking
|
//TODO error checking
|
||||||
let compartment = utils::get_compartment(cx);
|
let compartment = utils::get_compartment(cx);
|
||||||
let obj = result::unwrap(compartment.new_object_with_proto(~"GenericElementInstance",
|
let obj = compartment.new_object_with_proto(~"GenericElementInstance",
|
||||||
proto,
|
proto,
|
||||||
compartment.global_obj.ptr));
|
compartment.global_obj.ptr).unwrap();
|
||||||
|
|
||||||
let cache = node.get_wrappercache();
|
let cache = node.get_wrappercache();
|
||||||
assert!(cache.get_wrapper().is_null());
|
assert!(cache.get_wrapper().is_null());
|
||||||
|
|
|
@ -97,7 +97,6 @@ macro_rules! generate_element(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject {
|
pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> *JSObject {
|
||||||
match node.type_id() {
|
match node.type_id() {
|
||||||
ElementNodeTypeId(HTMLElementTypeId) => generate_element!(HTMLElement),
|
ElementNodeTypeId(HTMLElementTypeId) => generate_element!(HTMLElement),
|
||||||
|
@ -138,7 +137,6 @@ pub unsafe fn unwrap(obj: *JSObject) -> AbstractNode<ScriptView> {
|
||||||
AbstractNode::from_raw(raw)
|
AbstractNode::from_raw(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
extern fn getFirstChild(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn getFirstChild(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
||||||
|
@ -160,7 +158,6 @@ extern fn getFirstChild(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut JSVal) -> JSBool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
let obj = JS_THIS_OBJECT(cx, cast::transmute(vp));
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub extern fn defineProperty(cx: *JSContext, proxy: *JSObject, id: jsid,
|
||||||
|
|
||||||
pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = str::raw::from_buf(className as *u8);
|
let name = str::raw::from_c_str(className);
|
||||||
let nchars = "[object ]".len() + name.len();
|
let nchars = "[object ]".len() + name.len();
|
||||||
let chars: *mut jschar = cast::transmute(JS_malloc(cx, (nchars + 1) as u64 * (size_of::<jschar>() as u64)));
|
let chars: *mut jschar = cast::transmute(JS_malloc(cx, (nchars + 1) as u64 * (size_of::<jschar>() as u64)));
|
||||||
if chars.is_null() {
|
if chars.is_null() {
|
||||||
|
@ -76,10 +76,10 @@ pub fn _obj_toString(cx: *JSContext, className: *libc::c_char) -> *JSString {
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = ~"[object " + name + "]";
|
let result = ~"[object " + name + "]";
|
||||||
for result.iter().enumerate().advance |(i, c)| {
|
for (i, c) in result.iter().enumerate() {
|
||||||
*chars.offset(i) = c as jschar;
|
*chars.offset(i as int) = c as jschar;
|
||||||
}
|
}
|
||||||
*chars.offset(nchars) = 0;
|
*chars.offset(nchars as int) = 0;
|
||||||
let jsstr = JS_NewUCString(cx, cast::transmute(chars), nchars as u64);
|
let jsstr = JS_NewUCString(cx, cast::transmute(chars), nchars as u64);
|
||||||
if jsstr.is_null() {
|
if jsstr.is_null() {
|
||||||
JS_free(cx, cast::transmute(chars));
|
JS_free(cx, cast::transmute(chars));
|
||||||
|
|
|
@ -16,7 +16,6 @@ use js::rust::{Compartment, jsobj};
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::libc;
|
use std::libc;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
extern fn finalize_text(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
debug!("text finalize: %?!", obj as uint);
|
debug!("text finalize: %?!", obj as uint);
|
||||||
|
@ -79,9 +78,9 @@ pub fn create(cx: *JSContext, node: &mut AbstractNode<ScriptView>) -> jsobj {
|
||||||
//XXXjdm the parent should probably be the node parent instead of the global
|
//XXXjdm the parent should probably be the node parent instead of the global
|
||||||
//TODO error checking
|
//TODO error checking
|
||||||
let compartment = utils::get_compartment(cx);
|
let compartment = utils::get_compartment(cx);
|
||||||
let obj = result::unwrap(compartment.new_object_with_proto(instance,
|
let obj = compartment.new_object_with_proto(instance,
|
||||||
proto,
|
proto,
|
||||||
compartment.global_obj.ptr));
|
compartment.global_obj.ptr).unwrap();
|
||||||
|
|
||||||
let cache = node.get_wrappercache();
|
let cache = node.get_wrappercache();
|
||||||
assert!(cache.get_wrapper().is_null());
|
assert!(cache.get_wrapper().is_null());
|
||||||
|
|
|
@ -13,9 +13,7 @@ use std::hashmap::HashMap;
|
||||||
use std::libc;
|
use std::libc;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::ptr::{null, to_unsafe_ptr};
|
use std::ptr::{null, to_unsafe_ptr};
|
||||||
use std::result;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::uint;
|
|
||||||
use std::unstable::intrinsics;
|
use std::unstable::intrinsics;
|
||||||
use js::glue::*;
|
use js::glue::*;
|
||||||
use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
use js::glue::{DefineFunctionWithReserved, GetObjectJSClass, RUST_OBJECT_TO_JSVAL};
|
||||||
|
@ -85,7 +83,7 @@ extern fn InterfaceObjectToString(cx: *JSContext, _argc: uint, vp: *mut JSVal) -
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = jsval_to_str(cx, *v).get();
|
let name = jsval_to_str(cx, *v).unwrap();
|
||||||
let retval = str(~"function " + name + "() {\n [native code]\n}");
|
let retval = str(~"function " + name + "() {\n [native code]\n}");
|
||||||
*vp = domstring_to_jsval(cx, &retval);
|
*vp = domstring_to_jsval(cx, &retval);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -204,7 +202,7 @@ pub fn jsval_to_str(cx: *JSContext, v: JSVal) -> Result<~str, ()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let strbuf = JS_EncodeString(cx, jsstr);
|
let strbuf = JS_EncodeString(cx, jsstr);
|
||||||
let buf = str::raw::from_buf(strbuf as *u8);
|
let buf = str::raw::from_c_str(strbuf);
|
||||||
JS_free(cx, strbuf as *libc::c_void);
|
JS_free(cx, strbuf as *libc::c_void);
|
||||||
Ok(buf)
|
Ok(buf)
|
||||||
}
|
}
|
||||||
|
@ -216,10 +214,10 @@ pub unsafe fn domstring_to_jsval(cx: *JSContext, string: &DOMString) -> JSVal {
|
||||||
JSVAL_NULL
|
JSVAL_NULL
|
||||||
}
|
}
|
||||||
&str(ref s) => {
|
&str(ref s) => {
|
||||||
str::as_buf(*s, |buf, len| {
|
do s.as_imm_buf |buf, len| {
|
||||||
let cbuf = cast::transmute(buf);
|
let cbuf = cast::transmute(buf);
|
||||||
RUST_STRING_TO_JSVAL(JS_NewStringCopyN(cx, cbuf, len as libc::size_t))
|
RUST_STRING_TO_JSVAL(JS_NewStringCopyN(cx, cbuf, len as libc::size_t))
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,13 +320,13 @@ pub fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: @mut
|
||||||
compartment.register_class(prototype_jsclass(name.to_owned()));
|
compartment.register_class(prototype_jsclass(name.to_owned()));
|
||||||
|
|
||||||
//TODO error checking
|
//TODO error checking
|
||||||
let obj = result::unwrap(
|
let obj = (
|
||||||
match proto {
|
match proto {
|
||||||
Some(s) => compartment.new_object_with_proto(name.to_owned(),
|
Some(s) => compartment.new_object_with_proto(name.to_owned(),
|
||||||
s,
|
s,
|
||||||
compartment.global_obj.ptr),
|
compartment.global_obj.ptr),
|
||||||
None => compartment.new_object(name.to_owned(), null(), compartment.global_obj.ptr)
|
None => compartment.new_object(name.to_owned(), null(), compartment.global_obj.ptr)
|
||||||
});
|
}).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
compartment.define_property(name.to_owned(), RUST_OBJECT_TO_JSVAL(obj.ptr),
|
compartment.define_property(name.to_owned(), RUST_OBJECT_TO_JSVAL(obj.ptr),
|
||||||
|
@ -392,6 +390,7 @@ pub struct JSNativeHolder {
|
||||||
propertyHooks: *NativePropertyHooks
|
propertyHooks: *NativePropertyHooks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub enum ConstantVal {
|
pub enum ConstantVal {
|
||||||
IntVal(i32),
|
IntVal(i32),
|
||||||
UintVal(u32),
|
UintVal(u32),
|
||||||
|
@ -401,6 +400,7 @@ pub enum ConstantVal {
|
||||||
VoidVal
|
VoidVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct ConstantSpec {
|
pub struct ConstantSpec {
|
||||||
name: *libc::c_char,
|
name: *libc::c_char,
|
||||||
value: ConstantVal
|
value: ConstantVal
|
||||||
|
@ -454,7 +454,7 @@ pub fn CreateInterfaceObjects2(cx: *JSContext, global: *JSObject, receiver: *JSO
|
||||||
|
|
||||||
let mut interface = ptr::null();
|
let mut interface = ptr::null();
|
||||||
if constructorClass.is_not_null() || constructor.is_not_null() {
|
if constructorClass.is_not_null() || constructor.is_not_null() {
|
||||||
interface = do str::as_c_str(name) |s| {
|
interface = do name.to_c_str().with_ref |s| {
|
||||||
CreateInterfaceObject(cx, global, receiver, constructorClass,
|
CreateInterfaceObject(cx, global, receiver, constructorClass,
|
||||||
constructor, ctorNargs, proto,
|
constructor, ctorNargs, proto,
|
||||||
staticMethods, constants, s)
|
staticMethods, constants, s)
|
||||||
|
@ -506,7 +506,7 @@ fn CreateInterfaceObject(cx: *JSContext, global: *JSObject, receiver: *JSObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
if constructorClass.is_not_null() {
|
if constructorClass.is_not_null() {
|
||||||
let toString = do str::as_c_str("toString") |s| {
|
let toString = do "toString".to_c_str().with_ref |s| {
|
||||||
DefineFunctionWithReserved(cx, constructor, s,
|
DefineFunctionWithReserved(cx, constructor, s,
|
||||||
InterfaceObjectToString,
|
InterfaceObjectToString,
|
||||||
0, 0)
|
0, 0)
|
||||||
|
@ -666,7 +666,7 @@ impl WrapperCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn WrapNewBindingObject(cx: *JSContext, scope: *JSObject,
|
pub fn WrapNewBindingObject(cx: *JSContext, scope: *JSObject,
|
||||||
mut value: @mut CacheableWrapper,
|
value: @mut CacheableWrapper,
|
||||||
vp: *mut JSVal) -> bool {
|
vp: *mut JSVal) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let cache = value.get_wrappercache();
|
let cache = value.get_wrappercache();
|
||||||
|
@ -765,7 +765,7 @@ pub fn XrayResolveProperty(cx: *JSContext,
|
||||||
unsafe {
|
unsafe {
|
||||||
match attributes {
|
match attributes {
|
||||||
Some(attrs) => {
|
Some(attrs) => {
|
||||||
for attrs.iter().advance |&elem| {
|
for &elem in attrs.iter() {
|
||||||
let (attr, attr_id) = elem;
|
let (attr, attr_id) = elem;
|
||||||
if attr_id == JSID_VOID || attr_id != id {
|
if attr_id == JSID_VOID || attr_id != id {
|
||||||
loop;
|
loop;
|
||||||
|
@ -815,20 +815,18 @@ fn InternJSString(cx: *JSContext, chars: *libc::c_char) -> Option<jsid> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn InitIds(cx: *JSContext, specs: &[JSPropertySpec], ids: &mut [jsid]) -> bool {
|
pub fn InitIds(cx: *JSContext, specs: &[JSPropertySpec], ids: &mut [jsid]) -> bool {
|
||||||
let mut rval = true;
|
for (i, spec) in specs.iter().enumerate() {
|
||||||
for specs.iter().enumerate().advance |(i, spec)| {
|
|
||||||
if spec.name.is_null() == true {
|
if spec.name.is_null() == true {
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
match InternJSString(cx, spec.name) {
|
match InternJSString(cx, spec.name) {
|
||||||
Some(id) => ids[i] = id,
|
Some(id) => ids[i] = id,
|
||||||
None => {
|
None => {
|
||||||
rval = false;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rval
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DerivedWrapper {
|
pub trait DerivedWrapper {
|
||||||
|
@ -853,6 +851,7 @@ impl DerivedWrapper for AbstractNode<ScriptView> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(ToStr)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
FailureUnknown
|
FailureUnknown
|
||||||
}
|
}
|
||||||
|
@ -877,12 +876,12 @@ pub fn FindEnumStringIndex(cx: *JSContext,
|
||||||
if chars.is_null() {
|
if chars.is_null() {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
for values.iter().enumerate().advance |(i, value)| {
|
for (i, value) in values.iter().enumerate() {
|
||||||
if value.length != length as uint {
|
if value.length != length as uint {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
let mut equal = true;
|
let mut equal = true;
|
||||||
for uint::iterate(0, length as uint) |j| {
|
for j in range(0, length as int) {
|
||||||
if value.value[j] as u16 != *chars.offset(j) {
|
if value.value[j] as u16 != *chars.offset(j) {
|
||||||
equal = false;
|
equal = false;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -23,7 +23,7 @@ impl CharacterData {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Data(&self) -> DOMString {
|
pub fn Data(&self) -> DOMString {
|
||||||
copy self.data
|
self.data.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn SetData(&mut self, arg: &DOMString, _rv: &mut ErrorResult) {
|
pub fn SetData(&mut self, arg: &DOMString, _rv: &mut ErrorResult) {
|
||||||
|
|
|
@ -10,7 +10,6 @@ use js::jsapi::{JSObject, JSContext, JSVal};
|
||||||
use js::glue::RUST_OBJECT_TO_JSVAL;
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::f32;
|
|
||||||
|
|
||||||
pub struct ClientRect {
|
pub struct ClientRect {
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
|
@ -54,11 +53,11 @@ impl ClientRect {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Width(&self) -> f32 {
|
pub fn Width(&self) -> f32 {
|
||||||
f32::abs(self.right - self.left)
|
(self.right - self.left).abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Height(&self) -> f32 {
|
pub fn Height(&self) -> f32 {
|
||||||
f32::abs(self.bottom - self.top)
|
(self.bottom - self.top).abs()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use dom::htmltitleelement::HTMLTitleElement;
|
||||||
|
|
||||||
use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot, JSObject, JSContext, JSVal};
|
use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot, JSObject, JSContext, JSVal};
|
||||||
use js::glue::RUST_OBJECT_TO_JSVAL;
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -115,7 +115,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WrappableDocument for Document {
|
impl WrappableDocument for Document {
|
||||||
pub fn init_wrapper(@mut self, cx: *JSContext) {
|
fn init_wrapper(@mut self, cx: *JSContext) {
|
||||||
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
|
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -270,11 +270,11 @@ impl Document {
|
||||||
fail!("no SVG document yet")
|
fail!("no SVG document yet")
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let _ = for self.root.traverse_preorder |node| {
|
let _ = for node in self.root.traverse_preorder() {
|
||||||
if node.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
if node.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
for node.children().advance |child| {
|
for child in node.children() {
|
||||||
if child.is_text() {
|
if child.is_text() {
|
||||||
do child.with_imm_text() |text| {
|
do child.with_imm_text() |text| {
|
||||||
let s = text.parent.Data();
|
let s = text.parent.Data();
|
||||||
|
@ -299,17 +299,17 @@ impl Document {
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let (_scope, cx) = self.get_scope_and_cx();
|
let (_scope, cx) = self.get_scope_and_cx();
|
||||||
let _ = for self.root.traverse_preorder |node| {
|
let _ = for node in self.root.traverse_preorder() {
|
||||||
if node.type_id() != ElementNodeTypeId(HTMLHeadElementTypeId) {
|
if node.type_id() != ElementNodeTypeId(HTMLHeadElementTypeId) {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
let mut has_title = false;
|
let mut has_title = false;
|
||||||
for node.children().advance |child| {
|
for child in node.children() {
|
||||||
if child.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
if child.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
has_title = true;
|
has_title = true;
|
||||||
for child.children().advance |title_child| {
|
for title_child in child.children() {
|
||||||
child.remove_child(title_child);
|
child.remove_child(title_child);
|
||||||
}
|
}
|
||||||
let new_text = unsafe {
|
let new_text = unsafe {
|
||||||
|
@ -427,7 +427,7 @@ impl Document {
|
||||||
|
|
||||||
pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection {
|
pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection {
|
||||||
let mut elements = ~[];
|
let mut elements = ~[];
|
||||||
let _ = for self.root.traverse_preorder |child| {
|
let _ = for child in self.root.traverse_preorder() {
|
||||||
if child.is_element() {
|
if child.is_element() {
|
||||||
do child.with_imm_element |elem| {
|
do child.with_imm_element |elem| {
|
||||||
if callback(elem) {
|
if callback(elem) {
|
||||||
|
@ -441,7 +441,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content_changed(&self) {
|
pub fn content_changed(&self) {
|
||||||
for self.window.iter().advance |window| {
|
for window in self.window.iter() {
|
||||||
window.content_changed()
|
window.content_changed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ use js::jsapi::{JSContext, JSObject};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::str::eq_slice;
|
use std::str::eq_slice;
|
||||||
use extra::net::url;
|
use std::FromStr;
|
||||||
|
|
||||||
pub struct Element {
|
pub struct Element {
|
||||||
parent: Node<ScriptView>,
|
parent: Node<ScriptView>,
|
||||||
|
@ -252,7 +252,7 @@ impl<'self> Element {
|
||||||
|
|
||||||
pub fn get_attr(&'self self, name: &str) -> Option<&'self str> {
|
pub fn get_attr(&'self self, name: &str) -> Option<&'self str> {
|
||||||
// FIXME: Need an each() that links lifetimes in Rust.
|
// FIXME: Need an each() that links lifetimes in Rust.
|
||||||
for self.attrs.iter().advance |attr| {
|
for attr in self.attrs.iter() {
|
||||||
if eq_slice(attr.name, name) {
|
if eq_slice(attr.name, name) {
|
||||||
let val: &str = attr.value;
|
let val: &str = attr.value;
|
||||||
return Some(val);
|
return Some(val);
|
||||||
|
@ -265,7 +265,7 @@ impl<'self> Element {
|
||||||
let name = name.to_str();
|
let name = name.to_str();
|
||||||
let value_cell = Cell::new(value.to_str());
|
let value_cell = Cell::new(value.to_str());
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
for self.attrs.mut_iter().advance |attr| {
|
for attr in self.attrs.mut_iter() {
|
||||||
if eq_slice(attr.name, name) {
|
if eq_slice(attr.name, name) {
|
||||||
attr.value = value_cell.take().clone();
|
attr.value = value_cell.take().clone();
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -279,7 +279,7 @@ impl<'self> Element {
|
||||||
if "style" == name {
|
if "style" == name {
|
||||||
self.style_attribute = Some(
|
self.style_attribute = Some(
|
||||||
Stylesheet::from_attribute(
|
Stylesheet::from_attribute(
|
||||||
url::from_str("http://www.example.com/").unwrap(),
|
FromStr::from_str("http://www.example.com/").unwrap(),
|
||||||
value.get_ref()));
|
value.get_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,8 +290,8 @@ impl<'self> Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
|
fn get_scope_and_cx(&self) -> (*JSObject, *JSContext) {
|
||||||
let doc = self.parent.owner_doc.get();
|
let doc = self.parent.owner_doc.unwrap();
|
||||||
let win = doc.with_base(|doc| doc.window.get());
|
let win = doc.with_base(|doc| doc.window.unwrap());
|
||||||
let cx = unsafe {(*win.page).js_info.get_ref().js_compartment.cx.ptr};
|
let cx = unsafe {(*win.page).js_info.get_ref().js_compartment.cx.ptr};
|
||||||
let cache = win.get_wrappercache();
|
let cache = win.get_wrappercache();
|
||||||
let scope = cache.get_wrapper();
|
let scope = cache.get_wrapper();
|
||||||
|
@ -419,7 +419,7 @@ impl Element {
|
||||||
debug!("no document");
|
debug!("no document");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}.get();
|
}.unwrap();
|
||||||
|
|
||||||
ClientRectList::new(rects, cx, scope)
|
ClientRectList::new(rects, cx, scope)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Type(&self) -> DOMString {
|
pub fn Type(&self) -> DOMString {
|
||||||
copy self.type_
|
self.type_.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetTarget(&self) -> Option<@mut EventTarget> {
|
pub fn GetTarget(&self) -> Option<@mut EventTarget> {
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl FormData {
|
||||||
pub fn Append(&mut self, name: &DOMString, value: @mut Blob, filename: Option<DOMString>) {
|
pub fn Append(&mut self, name: &DOMString, value: @mut Blob, filename: Option<DOMString>) {
|
||||||
let blob = BlobData {
|
let blob = BlobData {
|
||||||
blob: value,
|
blob: value,
|
||||||
name: filename.get_or_default(str(~"default"))
|
name: filename.unwrap_or_default(str(~"default"))
|
||||||
};
|
};
|
||||||
self.data.insert(name.to_str(), blob);
|
self.data.insert(name.to_str(), blob);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use dom::window::Window;
|
||||||
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
|
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeNodeRef;
|
||||||
|
|
||||||
use std::libc;
|
use std::libc;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -43,7 +43,7 @@ impl HTMLDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WrappableDocument for HTMLDocument {
|
impl WrappableDocument for HTMLDocument {
|
||||||
pub fn init_wrapper(@mut self, cx: *JSContext) {
|
fn init_wrapper(@mut self, cx: *JSContext) {
|
||||||
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
|
self.wrap_object_shared(cx, ptr::null()); //XXXjdm a proper scope would be nice
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ impl HTMLDocument {
|
||||||
|
|
||||||
pub fn GetHead(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetHead(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
let mut headNode: Option<AbstractNode<ScriptView>> = None;
|
let mut headNode: Option<AbstractNode<ScriptView>> = None;
|
||||||
let _ = for self.parent.root.traverse_preorder |child| {
|
let _ = for child in self.parent.root.traverse_preorder() {
|
||||||
if child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) {
|
if child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) {
|
||||||
headNode = Some(child);
|
headNode = Some(child);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -11,7 +11,7 @@ use geom::size::Size2D;
|
||||||
use servo_msg::constellation_msg::SubpageId;
|
use servo_msg::constellation_msg::SubpageId;
|
||||||
|
|
||||||
use std::comm::ChanOne;
|
use std::comm::ChanOne;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
pub struct HTMLIFrameElement {
|
pub struct HTMLIFrameElement {
|
||||||
parent: HTMLElement,
|
parent: HTMLElement,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use dom::bindings::utils::{DOMString, null_string, ErrorResult};
|
use dom::bindings::utils::{DOMString, null_string, ErrorResult};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
pub struct HTMLImageElement {
|
pub struct HTMLImageElement {
|
||||||
parent: HTMLElement,
|
parent: HTMLElement,
|
||||||
|
|
|
@ -20,11 +20,10 @@ use dom::window::Window;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cast::transmute;
|
use std::cast::transmute;
|
||||||
use std::libc::c_void;
|
use std::libc::c_void;
|
||||||
use std::uint;
|
|
||||||
use js::jsapi::{JSObject, JSContext};
|
use js::jsapi::{JSObject, JSContext};
|
||||||
use js::rust::Compartment;
|
use js::rust::Compartment;
|
||||||
use netsurfcss::util::VoidPtrLike;
|
use netsurfcss::util::VoidPtrLike;
|
||||||
use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
use servo_util::tree::{TreeNode, TreeNodeRef};
|
||||||
|
|
||||||
//
|
//
|
||||||
// The basic Node structure
|
// The basic Node structure
|
||||||
|
@ -177,41 +176,39 @@ impl<View> Clone for AbstractNode<View> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<View> TreeNode<AbstractNode<View>> for Node<View> {
|
|
||||||
fn parent_node(&self) -> Option<AbstractNode<View>> {
|
|
||||||
self.parent_node
|
|
||||||
}
|
|
||||||
fn first_child(&self) -> Option<AbstractNode<View>> {
|
|
||||||
self.first_child
|
|
||||||
}
|
|
||||||
fn last_child(&self) -> Option<AbstractNode<View>> {
|
|
||||||
self.last_child
|
|
||||||
}
|
|
||||||
fn prev_sibling(&self) -> Option<AbstractNode<View>> {
|
|
||||||
self.prev_sibling
|
|
||||||
}
|
|
||||||
fn next_sibling(&self) -> Option<AbstractNode<View>> {
|
|
||||||
self.next_sibling
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent_node(&mut self, new_parent_node: Option<AbstractNode<View>>) {
|
|
||||||
self.parent_node = new_parent_node
|
|
||||||
}
|
|
||||||
fn set_first_child(&mut self, new_first_child: Option<AbstractNode<View>>) {
|
|
||||||
self.first_child = new_first_child
|
|
||||||
}
|
|
||||||
fn set_last_child(&mut self, new_last_child: Option<AbstractNode<View>>) {
|
|
||||||
self.last_child = new_last_child
|
|
||||||
}
|
|
||||||
fn set_prev_sibling(&mut self, new_prev_sibling: Option<AbstractNode<View>>) {
|
|
||||||
self.prev_sibling = new_prev_sibling
|
|
||||||
}
|
|
||||||
fn set_next_sibling(&mut self, new_next_sibling: Option<AbstractNode<View>>) {
|
|
||||||
self.next_sibling = new_next_sibling
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
|
impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
|
||||||
|
fn parent_node(node: &Node<View>) -> Option<AbstractNode<View>> {
|
||||||
|
node.parent_node
|
||||||
|
}
|
||||||
|
fn first_child(node: &Node<View>) -> Option<AbstractNode<View>> {
|
||||||
|
node.first_child
|
||||||
|
}
|
||||||
|
fn last_child(node: &Node<View>) -> Option<AbstractNode<View>> {
|
||||||
|
node.last_child
|
||||||
|
}
|
||||||
|
fn prev_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
|
||||||
|
node.prev_sibling
|
||||||
|
}
|
||||||
|
fn next_sibling(node: &Node<View>) -> Option<AbstractNode<View>> {
|
||||||
|
node.next_sibling
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent_node(node: &mut Node<View>, new_parent_node: Option<AbstractNode<View>>) {
|
||||||
|
node.parent_node = new_parent_node
|
||||||
|
}
|
||||||
|
fn set_first_child(node: &mut Node<View>, new_first_child: Option<AbstractNode<View>>) {
|
||||||
|
node.first_child = new_first_child
|
||||||
|
}
|
||||||
|
fn set_last_child(node: &mut Node<View>, new_last_child: Option<AbstractNode<View>>) {
|
||||||
|
node.last_child = new_last_child
|
||||||
|
}
|
||||||
|
fn set_prev_sibling(node: &mut Node<View>, new_prev_sibling: Option<AbstractNode<View>>) {
|
||||||
|
node.prev_sibling = new_prev_sibling
|
||||||
|
}
|
||||||
|
fn set_next_sibling(node: &mut Node<View>, new_next_sibling: Option<AbstractNode<View>>) {
|
||||||
|
node.next_sibling = new_next_sibling
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: The duplication between `with_base` and `with_mut_base` is ugly.
|
// FIXME: The duplication between `with_base` and `with_mut_base` is ugly.
|
||||||
fn with_base<R>(&self, callback: &fn(&Node<View>) -> R) -> R {
|
fn with_base<R>(&self, callback: &fn(&Node<View>) -> R) -> R {
|
||||||
self.transmute(callback)
|
self.transmute(callback)
|
||||||
|
@ -222,6 +219,8 @@ impl<View> TreeNodeRef<Node<View>> for AbstractNode<View> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<View> TreeNode<AbstractNode<View>> for Node<View> { }
|
||||||
|
|
||||||
impl<'self, View> AbstractNode<View> {
|
impl<'self, View> AbstractNode<View> {
|
||||||
// Unsafe accessors
|
// Unsafe accessors
|
||||||
|
|
||||||
|
@ -250,7 +249,7 @@ impl<'self, View> AbstractNode<View> {
|
||||||
/// allowed to call this. This is wildly unsafe and is therefore marked as such.
|
/// allowed to call this. This is wildly unsafe and is therefore marked as such.
|
||||||
pub unsafe fn unsafe_layout_data<T>(self) -> @mut T {
|
pub unsafe fn unsafe_layout_data<T>(self) -> @mut T {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
transmute(base.layout_data.get())
|
transmute(base.layout_data.unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Returns true if this node has layout data and false otherwise.
|
/// Returns true if this node has layout data and false otherwise.
|
||||||
|
@ -438,7 +437,7 @@ impl<'self, View> AbstractNode<View> {
|
||||||
/// Dumps the node tree, for debugging, with indentation.
|
/// Dumps the node tree, for debugging, with indentation.
|
||||||
pub fn dump_indent(&self, indent: uint) {
|
pub fn dump_indent(&self, indent: uint) {
|
||||||
let mut s = ~"";
|
let mut s = ~"";
|
||||||
for uint::range(0u, indent) |_i| {
|
for _ in range(0, indent) {
|
||||||
s.push_str(" ");
|
s.push_str(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +445,7 @@ impl<'self, View> AbstractNode<View> {
|
||||||
debug!("%s", s);
|
debug!("%s", s);
|
||||||
|
|
||||||
// FIXME: this should have a pure version?
|
// FIXME: this should have a pure version?
|
||||||
for self.each_child() |kid| {
|
for kid in self.children() {
|
||||||
kid.dump_indent(indent + 1u)
|
kid.dump_indent(indent + 1u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -464,7 +463,7 @@ impl<'self, View> AbstractNode<View> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
|
impl<View> Iterator<AbstractNode<View>> for AbstractNodeChildrenIterator<View> {
|
||||||
pub fn next(&mut self) -> Option<AbstractNode<View>> {
|
fn next(&mut self) -> Option<AbstractNode<View>> {
|
||||||
let node = self.current_node;
|
let node = self.current_node;
|
||||||
self.current_node = self.current_node.chain(|node| node.next_sibling());
|
self.current_node = self.current_node.chain(|node| node.next_sibling());
|
||||||
node
|
node
|
||||||
|
@ -483,14 +482,14 @@ impl Node<ScriptView> {
|
||||||
|
|
||||||
pub fn add_to_doc(&mut self, doc: AbstractDocument) {
|
pub fn add_to_doc(&mut self, doc: AbstractDocument) {
|
||||||
self.owner_doc = Some(doc);
|
self.owner_doc = Some(doc);
|
||||||
let mut node = self.first_child;
|
let mut cur_node = self.first_child;
|
||||||
while node.is_some() {
|
while cur_node.is_some() {
|
||||||
for node.get().traverse_preorder |node| {
|
for node in cur_node.unwrap().traverse_preorder() {
|
||||||
do node.with_mut_base |node_base| {
|
do node.with_mut_base |node_base| {
|
||||||
node_base.owner_doc = Some(doc);
|
node_base.owner_doc = Some(doc);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
node = node.get().next_sibling();
|
cur_node = cur_node.unwrap().next_sibling();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,13 @@ use js::{JSVAL_NULL, JSPROP_ENUMERATE};
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::comm::Chan;
|
use std::comm::SharedChan;
|
||||||
use std::int;
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::int;
|
||||||
|
use std::rt::rtio::RtioTimer;
|
||||||
|
use std::rt::io::timer::Timer;
|
||||||
use js::jsapi::JSVal;
|
use js::jsapi::JSVal;
|
||||||
use extra::timer;
|
|
||||||
use extra::uv_global_loop;
|
|
||||||
|
|
||||||
pub enum TimerControlMsg {
|
pub enum TimerControlMsg {
|
||||||
TimerMessage_Fire(~TimerData),
|
TimerMessage_Fire(~TimerData),
|
||||||
|
@ -38,7 +38,7 @@ pub struct Window {
|
||||||
script_chan: ScriptChan,
|
script_chan: ScriptChan,
|
||||||
compositor: @ScriptListener,
|
compositor: @ScriptListener,
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
timer_chan: Chan<TimerControlMsg>,
|
timer_chan: SharedChan<TimerControlMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
|
@ -68,7 +68,7 @@ impl Window {
|
||||||
|
|
||||||
pub fn Document(&self) -> AbstractDocument {
|
pub fn Document(&self) -> AbstractDocument {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*self.page).frame.get().document
|
(*self.page).frame.unwrap().document
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,18 +142,19 @@ impl BindingObject for Window {
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn SetTimeout(&self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 {
|
pub fn SetTimeout(&self, _cx: *JSContext, callback: JSVal, timeout: i32) -> i32 {
|
||||||
let timeout = int::max(0, timeout) as uint;
|
let timeout = int::max(0, timeout) as u64;
|
||||||
|
|
||||||
// Post a delayed message to the per-window timer task; it will dispatch it
|
// Post a delayed message to the per-window timer task; it will dispatch it
|
||||||
// to the relevant script handler that will deal with it.
|
// to the relevant script handler that will deal with it.
|
||||||
let data = ~TimerData {
|
let tm = Timer::new().unwrap();
|
||||||
|
let chan = self.timer_chan.clone();
|
||||||
|
do spawn {
|
||||||
|
tm.sleep(timeout);
|
||||||
|
chan.send(TimerMessage_Fire(~TimerData {
|
||||||
funval: callback,
|
funval: callback,
|
||||||
args: ~[]
|
args: ~[]
|
||||||
};
|
}));
|
||||||
timer::delayed_send(&uv_global_loop::get(),
|
}
|
||||||
timeout,
|
|
||||||
&self.timer_chan,
|
|
||||||
TimerMessage_Fire(data));
|
|
||||||
return 0; //TODO return handle into list of active timers
|
return 0; //TODO return handle into list of active timers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +183,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timer_chan
|
SharedChan::new(timer_chan)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::task;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use newcss::util::DataStream;
|
use newcss::util::DataStream;
|
||||||
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
use servo_net::resource_task::{ResourceTask, ProgressMsg, Load, Payload, Done};
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
/// Where a style sheet comes from.
|
/// Where a style sheet comes from.
|
||||||
pub enum StylesheetProvenance {
|
pub enum StylesheetProvenance {
|
||||||
|
@ -28,8 +28,8 @@ pub fn spawn_css_parser(provenance: StylesheetProvenance,
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
let url = do provenance_cell.with_ref |p| {
|
let url = do provenance_cell.with_ref |p| {
|
||||||
match *p {
|
match *p {
|
||||||
UrlProvenance(ref the_url) => copy *the_url,
|
UrlProvenance(ref the_url) => (*the_url).clone(),
|
||||||
InlineProvenance(ref the_url, _) => copy *the_url
|
InlineProvenance(ref the_url, _) => (*the_url).clone()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -54,19 +54,18 @@ use newcss::stylesheet::Stylesheet;
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::comm::{Chan, Port, SharedChan};
|
use std::comm::{Port, SharedChan};
|
||||||
use std::str::eq_slice;
|
use std::str::eq_slice;
|
||||||
use std::result;
|
|
||||||
use std::task;
|
use std::task;
|
||||||
|
use std::from_str::FromStr;
|
||||||
use hubbub::hubbub;
|
use hubbub::hubbub;
|
||||||
use servo_msg::constellation_msg::SubpageId;
|
use servo_msg::constellation_msg::SubpageId;
|
||||||
use servo_net::image_cache_task::ImageCacheTask;
|
use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::image_cache_task;
|
use servo_net::image_cache_task;
|
||||||
use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
|
use servo_net::resource_task::{Done, Load, Payload, ResourceTask};
|
||||||
use servo_util::tree::TreeUtils;
|
use servo_util::tree::TreeNodeRef;
|
||||||
use servo_util::url::make_url;
|
use servo_util::url::make_url;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use extra::net::url;
|
|
||||||
use extra::future::{Future, from_port};
|
use extra::future::{Future, from_port};
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
||||||
|
@ -167,7 +166,7 @@ fn css_link_listener(to_parent: SharedChan<HtmlDiscoveryMessage>,
|
||||||
|
|
||||||
// Send the sheets back in order
|
// Send the sheets back in order
|
||||||
// FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these
|
// FIXME: Shouldn't wait until after we've recieved CSSTaskExit to start sending these
|
||||||
for result_vec.iter().advance |port| {
|
for port in result_vec.iter() {
|
||||||
to_parent.send(HtmlDiscoveredStyle(port.recv()));
|
to_parent.send(HtmlDiscoveredStyle(port.recv()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,7 +184,7 @@ fn js_script_listener(to_parent: SharedChan<HtmlDiscoveryMessage>,
|
||||||
do task::spawn {
|
do task::spawn {
|
||||||
let (input_port, input_chan) = comm::stream();
|
let (input_port, input_chan) = comm::stream();
|
||||||
// TODO: change copy to move once we can move into closures
|
// TODO: change copy to move once we can move into closures
|
||||||
resource_task.send(Load(copy url, input_chan));
|
resource_task.send(Load(url.clone(), input_chan));
|
||||||
|
|
||||||
let mut buf = ~[];
|
let mut buf = ~[];
|
||||||
loop {
|
loop {
|
||||||
|
@ -273,7 +272,6 @@ fn build_element_from_tag(cx: *JSContext, tag: &str) -> AbstractNode<ScriptView>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
pub fn parse_html(cx: *JSContext,
|
pub fn parse_html(cx: *JSContext,
|
||||||
url: Url,
|
url: Url,
|
||||||
resource_task: ResourceTask,
|
resource_task: ResourceTask,
|
||||||
|
@ -348,7 +346,7 @@ pub fn parse_html(cx: *JSContext,
|
||||||
|
|
||||||
debug!("-- attach attrs");
|
debug!("-- attach attrs");
|
||||||
do node.as_mut_element |element| {
|
do node.as_mut_element |element| {
|
||||||
for tag.attributes.iter().advance |attr| {
|
for attr in tag.attributes.iter() {
|
||||||
element.set_attr(&str(attr.name.clone()), &str(attr.value.clone()));
|
element.set_attr(&str(attr.name.clone()), &str(attr.value.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,7 +375,7 @@ pub fn parse_html(cx: *JSContext,
|
||||||
let iframe_chan = iframe_chan.take();
|
let iframe_chan = iframe_chan.take();
|
||||||
let elem = &mut iframe_element.parent.parent;
|
let elem = &mut iframe_element.parent.parent;
|
||||||
let src_opt = elem.get_attr("src").map(|x| x.to_str());
|
let src_opt = elem.get_attr("src").map(|x| x.to_str());
|
||||||
for src_opt.iter().advance |src| {
|
for src in src_opt.iter() {
|
||||||
let iframe_url = make_url(src.clone(), Some(url2.clone()));
|
let iframe_url = make_url(src.clone(), Some(url2.clone()));
|
||||||
iframe_element.frame = Some(iframe_url.clone());
|
iframe_element.frame = Some(iframe_url.clone());
|
||||||
|
|
||||||
|
@ -404,7 +402,7 @@ pub fn parse_html(cx: *JSContext,
|
||||||
None => {}
|
None => {}
|
||||||
Some(src) => {
|
Some(src) => {
|
||||||
let img_url = make_url(src, Some(url2.clone()));
|
let img_url = make_url(src, Some(url2.clone()));
|
||||||
image_element.image = Some(copy img_url);
|
image_element.image = Some(img_url.clone());
|
||||||
// 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>
|
||||||
// tag.
|
// tag.
|
||||||
|
@ -475,7 +473,6 @@ pub fn parse_html(cx: *JSContext,
|
||||||
},
|
},
|
||||||
complete_script: |script| {
|
complete_script: |script| {
|
||||||
// A little function for holding this lint attr
|
// A little function for holding this lint attr
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
fn complete_script(script: hubbub::NodeDataPtr,
|
fn complete_script(script: hubbub::NodeDataPtr,
|
||||||
url: Url,
|
url: Url,
|
||||||
js_chan: SharedChan<JSMessage>) {
|
js_chan: SharedChan<JSMessage>) {
|
||||||
|
@ -500,12 +497,12 @@ pub fn parse_html(cx: *JSContext,
|
||||||
// We've reached the end of a <style> so we can submit all the text to the parser.
|
// We've reached the end of a <style> so we can submit all the text to the parser.
|
||||||
unsafe {
|
unsafe {
|
||||||
let style: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(style);
|
let style: AbstractNode<ScriptView> = NodeWrapping::from_hubbub_node(style);
|
||||||
let url = url::from_str("http://example.com/"); // FIXME
|
let url = FromStr::from_str("http://example.com/"); // FIXME
|
||||||
let url_cell = Cell::new(url);
|
let url_cell = Cell::new(url);
|
||||||
|
|
||||||
let mut data = ~[];
|
let mut data = ~[];
|
||||||
debug!("iterating over children %?", style.first_child());
|
debug!("iterating over children %?", style.first_child());
|
||||||
for style.children().advance |child| {
|
for child in style.children() {
|
||||||
debug!("child = %?", child);
|
debug!("child = %?", child);
|
||||||
do child.with_imm_text() |text| {
|
do child.with_imm_text() |text| {
|
||||||
data.push(text.parent.data.to_str()); // FIXME: Bad copy.
|
data.push(text.parent.data.to_str()); // FIXME: Bad copy.
|
||||||
|
@ -513,7 +510,7 @@ pub fn parse_html(cx: *JSContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("data = %?", data);
|
debug!("data = %?", data);
|
||||||
let provenance = InlineProvenance(result::unwrap(url_cell.take()), data.concat());
|
let provenance = InlineProvenance(url_cell.take().unwrap(), data.concat());
|
||||||
css_chan3.send(CSSTaskNewFile(provenance));
|
css_chan3.send(CSSTaskNewFile(provenance));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ use geom::size::Size2D;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use gfx::geometry::Au;
|
use gfx::geometry::Au;
|
||||||
use newcss::stylesheet::Stylesheet;
|
use newcss::stylesheet::Stylesheet;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
|
|
||||||
/// Asynchronous messages that script can send to layout.
|
/// Asynchronous messages that script can send to layout.
|
||||||
///
|
///
|
||||||
|
@ -62,7 +62,7 @@ impl DocumentDamageLevel {
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): This could be refactored to use `max` and the `Ord` trait, and this
|
/// FIXME(pcwalton): This could be refactored to use `max` and the `Ord` trait, and this
|
||||||
/// function removed.
|
/// function removed.
|
||||||
fn add(&mut self, new_damage: DocumentDamageLevel) {
|
pub fn add(&mut self, new_damage: DocumentDamageLevel) {
|
||||||
match (*self, new_damage) {
|
match (*self, new_damage) {
|
||||||
(ReflowDocumentDamage, new_damage) => *self = new_damage,
|
(ReflowDocumentDamage, new_damage) => *self = new_damage,
|
||||||
(MatchSelectorsDocumentDamage, _) => *self = MatchSelectorsDocumentDamage,
|
(MatchSelectorsDocumentDamage, _) => *self = MatchSelectorsDocumentDamage,
|
||||||
|
|
|
@ -25,11 +25,9 @@ use servo_msg::constellation_msg::{PipelineId, SubpageId, RendererReadyMsg, Resi
|
||||||
use servo_msg::constellation_msg::{LoadIframeUrlMsg};
|
use servo_msg::constellation_msg::{LoadIframeUrlMsg};
|
||||||
use servo_msg::constellation_msg;
|
use servo_msg::constellation_msg;
|
||||||
|
|
||||||
use newcss::stylesheet::Stylesheet;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::comm;
|
use std::comm;
|
||||||
use std::comm::{Port, SharedChan, Select2};
|
use std::comm::{Port, SharedChan};
|
||||||
use std::io::read_whole_file;
|
use std::io::read_whole_file;
|
||||||
use std::ptr::null;
|
use std::ptr::null;
|
||||||
use std::task::{SingleThreaded, task};
|
use std::task::{SingleThreaded, task};
|
||||||
|
@ -50,8 +48,7 @@ use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::tree::TreeNodeRef;
|
use servo_util::tree::TreeNodeRef;
|
||||||
use servo_util::url::make_url;
|
use servo_util::url::make_url;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use extra::net::url;
|
|
||||||
use extra::future::{from_value, Future};
|
use extra::future::{from_value, Future};
|
||||||
|
|
||||||
/// Messages used to control the script task.
|
/// Messages used to control the script task.
|
||||||
|
@ -162,7 +159,7 @@ impl PageTree {
|
||||||
|
|
||||||
pub fn find<'a> (&'a mut self, id: PipelineId) -> Option<&'a mut PageTree> {
|
pub fn find<'a> (&'a mut self, id: PipelineId) -> Option<&'a mut PageTree> {
|
||||||
if self.page.id == id { return Some(self); }
|
if self.page.id == id { return Some(self); }
|
||||||
for self.inner.mut_iter().advance |page_tree| {
|
for page_tree in self.inner.mut_iter() {
|
||||||
let found = page_tree.find(id);
|
let found = page_tree.find(id);
|
||||||
if found.is_some() { return found; }
|
if found.is_some() { return found; }
|
||||||
}
|
}
|
||||||
|
@ -181,7 +178,7 @@ impl<'self> Iterator<@mut Page> for PageTreeIterator<'self> {
|
||||||
if !self.stack.is_empty() {
|
if !self.stack.is_empty() {
|
||||||
let next = self.stack.pop();
|
let next = self.stack.pop();
|
||||||
{
|
{
|
||||||
for next.inner.mut_iter().advance |child| {
|
for child in next.inner.mut_iter() {
|
||||||
self.stack.push(child);
|
self.stack.push(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,7 +263,7 @@ impl Page {
|
||||||
// Send new document and relevant styles to layout.
|
// Send new document and relevant styles to layout.
|
||||||
let reflow = ~Reflow {
|
let reflow = ~Reflow {
|
||||||
document_root: do frame.document.with_base |doc| { doc.root },
|
document_root: do frame.document.with_base |doc| { doc.root },
|
||||||
url: copy self.url.get_ref().first(),
|
url: self.url.get_ref().first().clone(),
|
||||||
goal: goal,
|
goal: goal,
|
||||||
window_size: self.window_size.get(),
|
window_size: self.window_size.get(),
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
|
@ -485,20 +482,20 @@ impl ScriptTask {
|
||||||
|
|
||||||
/// Handles a request to execute a script.
|
/// Handles a request to execute a script.
|
||||||
fn handle_execute_msg(&mut self, id: PipelineId, url: Url) {
|
fn handle_execute_msg(&mut self, id: PipelineId, url: Url) {
|
||||||
debug!("script: Received url `%s` to execute", url::to_str(&url));
|
debug!("script: Received url `%s` to execute", url.to_str());
|
||||||
|
|
||||||
let page_tree = self.page_tree.find(id).expect("ScriptTask: received fire timer msg for a
|
let page_tree = self.page_tree.find(id).expect("ScriptTask: received fire timer msg for a
|
||||||
pipeline ID not associated with this script task. This is a bug.");
|
pipeline ID not associated with this script task. This is a bug.");
|
||||||
let js_info = page_tree.page.js_info.get_ref();
|
let js_info = page_tree.page.js_info.get_ref();
|
||||||
|
|
||||||
match read_whole_file(&Path(url.path)) {
|
match read_whole_file(&Path(url.path)) {
|
||||||
Err(msg) => println(fmt!("Error opening %s: %s", url::to_str(&url), msg)),
|
Err(msg) => println(fmt!("Error opening %s: %s", url.to_str(), msg)),
|
||||||
|
|
||||||
Ok(bytes) => {
|
Ok(bytes) => {
|
||||||
js_info.js_compartment.define_functions(debug_fns);
|
js_info.js_compartment.define_functions(debug_fns);
|
||||||
js_info.js_context.evaluate_script(js_info.js_compartment.global_obj,
|
js_info.js_context.evaluate_script(js_info.js_compartment.global_obj,
|
||||||
bytes,
|
bytes,
|
||||||
copy url.path,
|
url.path.clone(),
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -549,16 +546,16 @@ impl ScriptTask {
|
||||||
fn handle_resize_inactive_msg(&mut self, new_size: Size2D<uint>) {
|
fn handle_resize_inactive_msg(&mut self, new_size: Size2D<uint>) {
|
||||||
self.page_tree.page.window_size = from_value(new_size);
|
self.page_tree.page.window_size = from_value(new_size);
|
||||||
let last_loaded_url = replace(&mut self.page_tree.page.url, None);
|
let last_loaded_url = replace(&mut self.page_tree.page.url, None);
|
||||||
for last_loaded_url.iter().advance |last_loaded_url| {
|
for url in last_loaded_url.iter() {
|
||||||
self.page_tree.page.url = Some((last_loaded_url.first(), true));
|
self.page_tree.page.url = Some((url.first(), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a request to exit the script task and shut down layout.
|
/// Handles a request to exit the script task and shut down layout.
|
||||||
fn handle_exit_msg(&mut self) {
|
fn handle_exit_msg(&mut self) {
|
||||||
for self.page_tree.iter().advance |page| {
|
for page in self.page_tree.iter() {
|
||||||
page.join_layout();
|
page.join_layout();
|
||||||
do page.frame.get().document.with_mut_base |doc| {
|
do page.frame.unwrap().document.with_mut_base |doc| {
|
||||||
doc.teardown();
|
doc.teardown();
|
||||||
}
|
}
|
||||||
page.layout_chan.send(layout_interface::ExitMsg);
|
page.layout_chan.send(layout_interface::ExitMsg);
|
||||||
|
@ -574,10 +571,10 @@ impl ScriptTask {
|
||||||
message for a layout channel that is not associated with this script task. This
|
message for a layout channel that is not associated with this script task. This
|
||||||
is a bug.").page;
|
is a bug.").page;
|
||||||
let last_loaded_url = replace(&mut page.url, None);
|
let last_loaded_url = replace(&mut page.url, None);
|
||||||
for last_loaded_url.iter().advance |last_loaded_url| {
|
for loaded in last_loaded_url.iter() {
|
||||||
let (ref last_loaded_url, needs_reflow) = *last_loaded_url;
|
let (ref loaded, needs_reflow) = *loaded;
|
||||||
if *last_loaded_url == url {
|
if *loaded == url {
|
||||||
page.url = Some((last_loaded_url.clone(), false));
|
page.url = Some((loaded.clone(), false));
|
||||||
if needs_reflow {
|
if needs_reflow {
|
||||||
page.reflow_all(ReflowForDisplay, self.chan.clone(), self.compositor);
|
page.reflow_all(ReflowForDisplay, self.chan.clone(), self.compositor);
|
||||||
}
|
}
|
||||||
|
@ -661,7 +658,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
// Receive the JavaScript scripts.
|
// Receive the JavaScript scripts.
|
||||||
assert!(js_scripts.is_some());
|
assert!(js_scripts.is_some());
|
||||||
let js_scripts = js_scripts.swap_unwrap();
|
let js_scripts = js_scripts.take_unwrap();
|
||||||
debug!("js_scripts: %?", js_scripts);
|
debug!("js_scripts: %?", js_scripts);
|
||||||
|
|
||||||
// Perform the initial reflow.
|
// Perform the initial reflow.
|
||||||
|
@ -677,7 +674,7 @@ impl ScriptTask {
|
||||||
js_info.js_compartment.define_functions(debug_fns);
|
js_info.js_compartment.define_functions(debug_fns);
|
||||||
|
|
||||||
// Evaluate every script in the document.
|
// Evaluate every script in the document.
|
||||||
for js_scripts.iter().advance |bytes| {
|
for bytes in js_scripts.iter() {
|
||||||
let _ = js_info.js_context.evaluate_script(js_info.js_compartment.global_obj,
|
let _ = js_info.js_context.evaluate_script(js_info.js_compartment.global_obj,
|
||||||
bytes.clone(),
|
bytes.clone(),
|
||||||
~"???",
|
~"???",
|
||||||
|
@ -757,10 +754,10 @@ impl ScriptTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn load_url_from_element(&self, page: @mut Page, element: &Element) {
|
fn load_url_from_element(&self, page: @mut Page, element: &Element) {
|
||||||
// if the node's element is "a," load url from href attr
|
// if the node's element is "a," load url from href attr
|
||||||
let href = element.get_attr("href");
|
let attr = element.get_attr("href");
|
||||||
for href.iter().advance |href| {
|
for href in attr.iter() {
|
||||||
debug!("ScriptTask: clicked on link to %s", *href);
|
debug!("ScriptTask: clicked on link to %s", *href);
|
||||||
let current_url = do page.url.map |&(ref url, _)| {
|
let current_url = do page.url.map |&(ref url, _)| {
|
||||||
url.clone()
|
url.clone()
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use std::uint;
|
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
use std::iterator;
|
||||||
|
|
||||||
enum RangeRelation {
|
enum RangeRelation {
|
||||||
OverlapsBegin(/* overlap */ uint),
|
OverlapsBegin(/* overlap */ uint),
|
||||||
|
@ -15,6 +15,7 @@ enum RangeRelation {
|
||||||
EntirelyAfter
|
EntirelyAfter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
pub struct Range {
|
pub struct Range {
|
||||||
priv off: uint,
|
priv off: uint,
|
||||||
priv len: uint
|
priv len: uint
|
||||||
|
@ -35,13 +36,8 @@ impl Range {
|
||||||
pub fn length(&self) -> uint { self.len }
|
pub fn length(&self) -> uint { self.len }
|
||||||
pub fn end(&self) -> uint { self.off + self.len }
|
pub fn end(&self) -> uint { self.off + self.len }
|
||||||
|
|
||||||
pub fn eachi(&self, callback: &fn(uint) -> bool) -> bool {
|
pub fn eachi(&self) -> iterator::Range<uint> {
|
||||||
for uint::range(self.off, self.off + self.len) |i| {
|
range(self.off, self.off + self.len)
|
||||||
if !callback(i) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, i: uint) -> bool {
|
pub fn contains(&self, i: uint) -> bool {
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl ProfilerChan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq, Clone)]
|
||||||
pub enum ProfilerCategory {
|
pub enum ProfilerCategory {
|
||||||
CompositingCategory,
|
CompositingCategory,
|
||||||
LayoutQueryCategory,
|
LayoutQueryCategory,
|
||||||
|
@ -70,7 +70,7 @@ impl ProfilerCategory {
|
||||||
|
|
||||||
// enumeration of all ProfilerCategory types
|
// enumeration of all ProfilerCategory types
|
||||||
// TODO(tkuehn): is there a better way to ensure proper order of categories?
|
// TODO(tkuehn): is there a better way to ensure proper order of categories?
|
||||||
priv fn empty_buckets() -> ProfilerBuckets {
|
fn empty_buckets() -> ProfilerBuckets {
|
||||||
let buckets = [
|
let buckets = [
|
||||||
(CompositingCategory, ~[]),
|
(CompositingCategory, ~[]),
|
||||||
(LayoutQueryCategory, ~[]),
|
(LayoutQueryCategory, ~[]),
|
||||||
|
@ -92,8 +92,8 @@ impl ProfilerCategory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that the order of the buckets matches the order of the enum categories
|
// ensure that the order of the buckets matches the order of the enum categories
|
||||||
priv fn check_order(vec: &ProfilerBuckets) {
|
fn check_order(vec: &ProfilerBuckets) {
|
||||||
for vec.iter().advance |&(category, _)| {
|
for &(category, _) in vec.iter() {
|
||||||
if category != vec[category as uint].first() {
|
if category != vec[category as uint].first() {
|
||||||
fail!("Enum category does not match bucket index. This is a bug.");
|
fail!("Enum category does not match bucket index. This is a bug.");
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ impl Profiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn handle_msg(&mut self, msg: ProfilerMsg) {
|
fn handle_msg(&mut self, msg: ProfilerMsg) {
|
||||||
match msg {
|
match msg {
|
||||||
TimeMsg(category, t) => match self.buckets[category as uint] {
|
TimeMsg(category, t) => match self.buckets[category as uint] {
|
||||||
//TODO(tkuehn): would be nice to have tuple.second_mut()
|
//TODO(tkuehn): would be nice to have tuple.second_mut()
|
||||||
|
@ -151,11 +151,11 @@ impl Profiler {
|
||||||
self.last_msg = Some(msg);
|
self.last_msg = Some(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
priv fn print_buckets(&mut self) {
|
fn print_buckets(&mut self) {
|
||||||
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
println(fmt!("%31s %15s %15s %15s %15s %15s",
|
||||||
"_category_", "_mean (ms)_", "_median (ms)_",
|
"_category_", "_mean (ms)_", "_median (ms)_",
|
||||||
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
"_min (ms)_", "_max (ms)_", "_bucket size_"));
|
||||||
for self.buckets.mut_iter().advance |bucket| {
|
for bucket in self.buckets.mut_iter() {
|
||||||
let (category, data) = match *bucket {
|
let (category, data) = match *bucket {
|
||||||
(category, ref mut data) => (category, data),
|
(category, ref mut data) => (category, data),
|
||||||
};
|
};
|
||||||
|
@ -163,7 +163,7 @@ impl Profiler {
|
||||||
let data_len = data.len();
|
let data_len = data.len();
|
||||||
if data_len > 0 {
|
if data_len > 0 {
|
||||||
let (mean, median, &min, &max) =
|
let (mean, median, &min, &max) =
|
||||||
(data.iter().transform(|&x|x).sum() / (data_len as float),
|
(data.iter().map(|&x|x).sum() / (data_len as float),
|
||||||
data[data_len / 2],
|
data[data_len / 2],
|
||||||
data.iter().min().unwrap(),
|
data.iter().min().unwrap(),
|
||||||
data.iter().max().unwrap());
|
data.iter().max().unwrap());
|
||||||
|
|
|
@ -4,204 +4,293 @@
|
||||||
|
|
||||||
//! Helper functions for garbage collected doubly-linked trees.
|
//! Helper functions for garbage collected doubly-linked trees.
|
||||||
|
|
||||||
/// The basic trait. This function is meant to encapsulate a clonable reference to a tree node.
|
// Macros to make add_child etc. less painful to write.
|
||||||
pub trait TreeNodeRef<N> : Clone {
|
// Code outside this module should instead implement TreeNode
|
||||||
|
// and use its default methods.
|
||||||
|
macro_rules! get(
|
||||||
|
($node:expr, $fun:ident) => (
|
||||||
|
TreeNodeRef::$fun::<Node,Self>($node)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
macro_rules! set(
|
||||||
|
($node:expr, $fun:ident, $val:expr) => (
|
||||||
|
TreeNodeRef::$fun::<Node,Self>($node, $val)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
pub struct ChildIterator<Ref> {
|
||||||
|
priv current: Option<Ref>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Node, Ref: TreeNodeRef<Node>> Iterator<Ref> for ChildIterator<Ref> {
|
||||||
|
fn next(&mut self) -> Option<Ref> {
|
||||||
|
if self.current.is_none() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Do we need two clones here?
|
||||||
|
let x = self.current.get_ref().clone();
|
||||||
|
self.current = x.with_base(|n| TreeNodeRef::next_sibling::<Node, Ref>(n));
|
||||||
|
Some(x.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Do this without precomputing a vector of refs.
|
||||||
|
// Easy for preorder; harder for postorder.
|
||||||
|
pub struct TreeIterator<Ref> {
|
||||||
|
priv nodes: ~[Ref],
|
||||||
|
priv index: uint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ref> TreeIterator<Ref> {
|
||||||
|
fn new(nodes: ~[Ref]) -> TreeIterator<Ref> {
|
||||||
|
TreeIterator {
|
||||||
|
nodes: nodes,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Ref: Clone> Iterator<Ref> for TreeIterator<Ref> {
|
||||||
|
fn next(&mut self) -> Option<Ref> {
|
||||||
|
if self.index >= self.nodes.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let v = self.nodes[self.index].clone();
|
||||||
|
self.index += 1;
|
||||||
|
Some(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A type implementing TreeNodeRef<Node> is a clonable reference to an underlying
|
||||||
|
/// node type Node.
|
||||||
|
///
|
||||||
|
/// We have to define both ref and node operations in the same trait, which makes
|
||||||
|
/// the latter more annoying to call (as static methods). But we provide non-static
|
||||||
|
/// proxies in trait TreeNode below.
|
||||||
|
pub trait TreeNodeRef<Node>: Clone {
|
||||||
|
|
||||||
|
// Fundamental operations on refs.
|
||||||
|
|
||||||
/// Borrows this node as immutable.
|
/// Borrows this node as immutable.
|
||||||
fn with_base<R>(&self, callback: &fn(&N) -> R) -> R;
|
fn with_base<R>(&self, callback: &fn(&Node) -> R) -> R;
|
||||||
|
|
||||||
/// Borrows this node as mutable.
|
/// Borrows this node as mutable.
|
||||||
fn with_mut_base<R>(&self, callback: &fn(&mut N) -> R) -> R;
|
fn with_mut_base<R>(&self, callback: &fn(&mut Node) -> R) -> R;
|
||||||
}
|
|
||||||
|
|
||||||
|
// Fundamental operations on nodes.
|
||||||
|
|
||||||
/// The contents of a tree node.
|
|
||||||
pub trait TreeNode<NR> {
|
|
||||||
/// Returns the parent of this node.
|
/// Returns the parent of this node.
|
||||||
fn parent_node(&self) -> Option<NR>;
|
fn parent_node(node: &Node) -> Option<Self>;
|
||||||
|
|
||||||
/// Returns the first child of this node.
|
/// Returns the first child of this node.
|
||||||
fn first_child(&self) -> Option<NR>;
|
fn first_child(node: &Node) -> Option<Self>;
|
||||||
|
|
||||||
/// Returns the last child of this node.
|
/// Returns the last child of this node.
|
||||||
fn last_child(&self) -> Option<NR>;
|
fn last_child(node: &Node) -> Option<Self>;
|
||||||
|
|
||||||
/// Returns the previous sibling of this node.
|
/// Returns the previous sibling of this node.
|
||||||
fn prev_sibling(&self) -> Option<NR>;
|
fn prev_sibling(node: &Node) -> Option<Self>;
|
||||||
|
|
||||||
/// Returns the next sibling of this node.
|
/// Returns the next sibling of this node.
|
||||||
fn next_sibling(&self) -> Option<NR>;
|
fn next_sibling(node: &Node) -> Option<Self>;
|
||||||
|
|
||||||
/// Sets the parent of this node.
|
/// Sets the parent of this node.
|
||||||
fn set_parent_node(&mut self, new_parent: Option<NR>);
|
fn set_parent_node(node: &mut Node, new_parent: Option<Self>);
|
||||||
|
|
||||||
/// Sets the first child of this node.
|
/// Sets the first child of this node.
|
||||||
fn set_first_child(&mut self, new_first_child: Option<NR>);
|
fn set_first_child(node: &mut Node, new_first_child: Option<Self>);
|
||||||
|
|
||||||
/// Sets the last child of this node.
|
/// Sets the last child of this node.
|
||||||
fn set_last_child(&mut self, new_last_child: Option<NR>);
|
fn set_last_child(node: &mut Node, new_last_child: Option<Self>);
|
||||||
|
|
||||||
/// Sets the previous sibling of this node.
|
/// Sets the previous sibling of this node.
|
||||||
fn set_prev_sibling(&mut self, new_prev_sibling: Option<NR>);
|
fn set_prev_sibling(node: &mut Node, new_prev_sibling: Option<Self>);
|
||||||
|
|
||||||
/// Sets the next sibling of this node.
|
/// Sets the next sibling of this node.
|
||||||
fn set_next_sibling(&mut self, new_next_sibling: Option<NR>);
|
fn set_next_sibling(node: &mut Node, new_next_sibling: Option<Self>);
|
||||||
}
|
|
||||||
|
|
||||||
|
// The tree utilities, operating on refs mostly.
|
||||||
|
|
||||||
/// A set of helper functions useful for operating on trees.
|
|
||||||
pub trait TreeUtils {
|
|
||||||
/// Returns true if this node is disconnected from the tree or has no children.
|
/// Returns true if this node is disconnected from the tree or has no children.
|
||||||
fn is_leaf(&self) -> bool;
|
fn is_leaf(&self) -> bool {
|
||||||
|
do self.with_base |this_node| {
|
||||||
|
(get!(this_node, first_child)).is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds a new child to the end of this node's list of children.
|
/// Adds a new child to the end of this node's list of children.
|
||||||
///
|
///
|
||||||
/// Fails unless `new_child` is disconnected from the tree.
|
/// Fails unless `new_child` is disconnected from the tree.
|
||||||
fn add_child(&self, new_child: Self);
|
fn add_child(&self, new_child: Self) {
|
||||||
|
do self.with_mut_base |this_node| {
|
||||||
|
do new_child.with_mut_base |new_child_node| {
|
||||||
|
assert!((get!(new_child_node, parent_node)).is_none());
|
||||||
|
assert!((get!(new_child_node, prev_sibling)).is_none());
|
||||||
|
assert!((get!(new_child_node, next_sibling)).is_none());
|
||||||
|
|
||||||
|
match get!(this_node, last_child) {
|
||||||
|
None => set!(this_node, set_first_child, Some(new_child.clone())),
|
||||||
|
Some(last_child) => {
|
||||||
|
do last_child.with_mut_base |last_child_node| {
|
||||||
|
assert!((get!(last_child_node, next_sibling)).is_none());
|
||||||
|
set!(last_child_node, set_next_sibling, Some(new_child.clone()));
|
||||||
|
set!(new_child_node, set_prev_sibling, Some(last_child.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set!(this_node, set_last_child, Some(new_child.clone()));
|
||||||
|
set!(new_child_node, set_parent_node, Some((*self).clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes the given child from this node's list of children.
|
/// Removes the given child from this node's list of children.
|
||||||
///
|
///
|
||||||
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
|
/// Fails unless `child` is a child of this node. (FIXME: This is not yet checked.)
|
||||||
fn remove_child(&self, child: Self);
|
fn remove_child(&self, child: Self) {
|
||||||
|
do self.with_mut_base |this_node| {
|
||||||
|
do child.with_mut_base |child_node| {
|
||||||
|
assert!((get!(child_node, parent_node)).is_some());
|
||||||
|
|
||||||
|
match get!(child_node, prev_sibling) {
|
||||||
|
None => set!(this_node, set_first_child, get!(child_node, next_sibling)),
|
||||||
|
Some(prev_sibling) => {
|
||||||
|
do prev_sibling.with_mut_base |prev_sibling_node| {
|
||||||
|
set!(prev_sibling_node, set_next_sibling, get!(child_node, next_sibling));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match get!(child_node, next_sibling) {
|
||||||
|
None => set!(this_node, set_last_child, get!(child_node, prev_sibling)),
|
||||||
|
Some(next_sibling) => {
|
||||||
|
do next_sibling.with_mut_base |next_sibling_node| {
|
||||||
|
set!(next_sibling_node, set_prev_sibling, get!(child_node, prev_sibling));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set!(child_node, set_prev_sibling, None);
|
||||||
|
set!(child_node, set_next_sibling, None);
|
||||||
|
set!(child_node, set_parent_node, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterates over all children of this node.
|
/// Iterates over all children of this node.
|
||||||
fn each_child(&self, callback: &fn(Self) -> bool) -> bool;
|
fn children(&self) -> ChildIterator<Self> {
|
||||||
|
ChildIterator {
|
||||||
|
current: self.with_base(|n| get!(n, first_child)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterates over this node and all its descendants, in preorder.
|
/// Iterates over this node and all its descendants, in preorder.
|
||||||
fn traverse_preorder(&self, callback: &fn(Self) -> bool) -> bool;
|
fn traverse_preorder(&self) -> TreeIterator<Self> {
|
||||||
|
self.traverse_preorder_prune(|_| false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterates over this node and all its descendants, in postorder.
|
/// Iterates over this node and all its descendants, in postorder.
|
||||||
fn traverse_postorder(&self, callback: &fn(Self) -> bool) -> bool;
|
fn traverse_postorder(&self) -> TreeIterator<Self> {
|
||||||
|
self.traverse_postorder_prune(|_| false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Like traverse_preorder but calls 'prune' first on each node. If it returns true then we
|
/// Like traverse_preorder but calls 'prune' first on each node. If it returns true then we
|
||||||
/// skip the whole subtree but continue iterating.
|
/// skip the whole subtree but continue iterating.
|
||||||
///
|
fn traverse_preorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
|
||||||
/// 'prune' is a separate function a) for compatibility with the 'for' protocol,
|
let mut nodes = ~[];
|
||||||
/// b) so that the postorder version can still prune before traversing.
|
gather(self, &mut nodes, false, prune);
|
||||||
fn traverse_preorder_prune(&self, prune: &fn(&Self) -> bool, callback: &fn(Self) -> bool) -> bool;
|
TreeIterator::new(nodes)
|
||||||
|
}
|
||||||
|
|
||||||
/// Like traverse_postorder but calls 'prune' first on each node. If it returns true then we
|
/// Like traverse_postorder but calls 'prune' first on each node. If it returns true then we
|
||||||
/// skip the whole subtree but continue iterating.
|
/// skip the whole subtree but continue iterating.
|
||||||
///
|
///
|
||||||
/// NB: 'prune' is called *before* traversing children, even though this is a
|
/// NB: 'prune' is called *before* traversing children, even though this is a
|
||||||
/// postorder traversal.
|
/// postorder traversal.
|
||||||
fn traverse_postorder_prune(&self, prune: &fn(&Self) -> bool, callback: &fn(Self) -> bool) -> bool;
|
fn traverse_postorder_prune(&self, prune: &fn(&Self) -> bool) -> TreeIterator<Self> {
|
||||||
}
|
let mut nodes = ~[];
|
||||||
|
gather(self, &mut nodes, true, prune);
|
||||||
impl<NR:TreeNodeRef<N>,N:TreeNode<NR>> TreeUtils for NR {
|
TreeIterator::new(nodes)
|
||||||
fn is_leaf(&self) -> bool {
|
|
||||||
do self.with_base |this_node| {
|
|
||||||
this_node.first_child().is_none()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_child(&self, new_child: NR) {
|
fn gather<Node, Ref: TreeNodeRef<Node>>(cur: &Ref, refs: &mut ~[Ref],
|
||||||
do self.with_mut_base |this_node| {
|
postorder: bool, prune: &fn(&Ref) -> bool) {
|
||||||
do new_child.with_mut_base |new_child_node| {
|
|
||||||
assert!(new_child_node.parent_node().is_none());
|
|
||||||
assert!(new_child_node.prev_sibling().is_none());
|
|
||||||
assert!(new_child_node.next_sibling().is_none());
|
|
||||||
|
|
||||||
match this_node.last_child() {
|
|
||||||
None => this_node.set_first_child(Some(new_child.clone())),
|
|
||||||
Some(last_child) => {
|
|
||||||
do last_child.with_mut_base |last_child_node| {
|
|
||||||
assert!(last_child_node.next_sibling().is_none());
|
|
||||||
last_child_node.set_next_sibling(Some(new_child.clone()));
|
|
||||||
new_child_node.set_prev_sibling(Some(last_child.clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this_node.set_last_child(Some(new_child.clone()));
|
|
||||||
new_child_node.set_parent_node(Some((*self).clone()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_child(&self, child: NR) {
|
|
||||||
do self.with_mut_base |this_node| {
|
|
||||||
do child.with_mut_base |child_node| {
|
|
||||||
assert!(child_node.parent_node().is_some());
|
|
||||||
|
|
||||||
match child_node.prev_sibling() {
|
|
||||||
None => this_node.set_first_child(child_node.next_sibling()),
|
|
||||||
Some(prev_sibling) => {
|
|
||||||
do prev_sibling.with_mut_base |prev_sibling_node| {
|
|
||||||
prev_sibling_node.set_next_sibling(child_node.next_sibling());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match child_node.next_sibling() {
|
|
||||||
None => this_node.set_last_child(child_node.prev_sibling()),
|
|
||||||
Some(next_sibling) => {
|
|
||||||
do next_sibling.with_mut_base |next_sibling_node| {
|
|
||||||
next_sibling_node.set_prev_sibling(child_node.prev_sibling());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
child_node.set_prev_sibling(None);
|
|
||||||
child_node.set_next_sibling(None);
|
|
||||||
child_node.set_parent_node(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn each_child(&self, callback: &fn(NR) -> bool) -> bool {
|
|
||||||
let mut maybe_current = self.with_base(|n| n.first_child());
|
|
||||||
while !maybe_current.is_none() {
|
|
||||||
let current = maybe_current.get_ref().clone();
|
|
||||||
if !callback(current.clone()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
maybe_current = current.with_base(|n| n.next_sibling());
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn traverse_preorder_prune(&self, prune: &fn(&NR) -> bool, callback: &fn(NR) -> bool) -> bool {
|
|
||||||
// prune shouldn't mutate, so don't clone
|
// prune shouldn't mutate, so don't clone
|
||||||
if prune(self) {
|
if prune(cur) {
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !callback((*self).clone()) {
|
if !postorder {
|
||||||
return false;
|
refs.push(cur.clone());
|
||||||
}
|
}
|
||||||
|
for kid in cur.children() {
|
||||||
for self.each_child |kid| {
|
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
||||||
if !kid.traverse_preorder_prune(|a| prune(a), |a| callback(a)) {
|
gather(&kid, refs, postorder, |a| prune(a))
|
||||||
return false;
|
}
|
||||||
|
if postorder {
|
||||||
|
refs.push(cur.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
|
||||||
|
/// Access the fields of a node without a static TreeNodeRef method call.
|
||||||
|
/// If you make an impl TreeNodeRef<Node> for Ref then you should also make
|
||||||
|
/// impl TreeNode<Ref> for Node with an empty body.
|
||||||
|
pub trait TreeNode<Ref: TreeNodeRef<Self>> {
|
||||||
|
/// Returns the parent of this node.
|
||||||
|
fn parent_node(&self) -> Option<Ref> {
|
||||||
|
TreeNodeRef::parent_node::<Self,Ref>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_postorder_prune(&self, prune: &fn(&NR) -> bool, callback: &fn(NR) -> bool) -> bool {
|
/// Returns the first child of this node.
|
||||||
// prune shouldn't mutate, so don't clone
|
fn first_child(&self) -> Option<Ref> {
|
||||||
if prune(self) {
|
TreeNodeRef::first_child::<Self,Ref>(self)
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for self.each_child |kid| {
|
/// Returns the last child of this node.
|
||||||
// FIXME: Work around rust#2202. We should be able to pass the callback directly.
|
fn last_child(&self) -> Option<Ref> {
|
||||||
if !kid.traverse_postorder_prune(|a| prune(a), |a| callback(a)) {
|
TreeNodeRef::last_child::<Self,Ref>(self)
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback((*self).clone())
|
/// Returns the previous sibling of this node.
|
||||||
|
fn prev_sibling(&self) -> Option<Ref> {
|
||||||
|
TreeNodeRef::prev_sibling::<Self,Ref>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_preorder(&self, callback: &fn(NR) -> bool) -> bool {
|
/// Returns the next sibling of this node.
|
||||||
self.traverse_preorder_prune(|_| false, callback)
|
fn next_sibling(&self) -> Option<Ref> {
|
||||||
|
TreeNodeRef::next_sibling::<Self,Ref>(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn traverse_postorder(&self, callback: &fn(NR) -> bool) -> bool {
|
/// Sets the parent of this node.
|
||||||
self.traverse_postorder_prune(|_| false, callback)
|
fn set_parent_node(&mut self, new_parent: Option<Ref>) {
|
||||||
}
|
TreeNodeRef::set_parent_node::<Self,Ref>(self, new_parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the first child of this node.
|
||||||
|
fn set_first_child(&mut self, new_first_child: Option<Ref>) {
|
||||||
|
TreeNodeRef::set_first_child::<Self,Ref>(self, new_first_child)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the last child of this node.
|
||||||
|
fn set_last_child(&mut self, new_last_child: Option<Ref>) {
|
||||||
|
TreeNodeRef::set_last_child::<Self,Ref>(self, new_last_child)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the previous sibling of this node.
|
||||||
|
fn set_prev_sibling(&mut self, new_prev_sibling: Option<Ref>) {
|
||||||
|
TreeNodeRef::set_prev_sibling::<Self,Ref>(self, new_prev_sibling)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the next sibling of this node.
|
||||||
|
fn set_next_sibling(&mut self, new_next_sibling: Option<Ref>) {
|
||||||
|
TreeNodeRef::set_next_sibling::<Self,Ref>(self, new_next_sibling)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use extra::net::url;
|
use extra::url;
|
||||||
use extra::net::url::Url;
|
use extra::url::Url;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::os;
|
use std::os;
|
||||||
use std::result;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a URL object from a string. Does various helpful browsery things like
|
Create a URL object from a string. Does various helpful browsery things like
|
||||||
|
@ -17,10 +16,9 @@ Create a URL object from a string. Does various helpful browsery things like
|
||||||
is based off the current url
|
is based off the current url
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#[allow(non_implicitly_copyable_typarams)]
|
|
||||||
pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
||||||
let schm = url::get_scheme(str_url);
|
let schm = url::get_scheme(str_url);
|
||||||
let str_url = if result::is_err(&schm) {
|
let str_url = if schm.is_err() {
|
||||||
if current_url.is_none() {
|
if current_url.is_none() {
|
||||||
// Assume we've been given a file path. If it's absolute just return
|
// Assume we've been given a file path. If it's absolute just return
|
||||||
// it, otherwise make it absolute with the cwd.
|
// it, otherwise make it absolute with the cwd.
|
||||||
|
@ -30,7 +28,7 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
||||||
~"file://" + os::getcwd().push(str_url).to_str()
|
~"file://" + os::getcwd().push(str_url).to_str()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let current_url = current_url.get();
|
let current_url = current_url.unwrap();
|
||||||
debug!("make_url: current_url: %?", current_url);
|
debug!("make_url: current_url: %?", current_url);
|
||||||
if str_url.starts_with("//") {
|
if str_url.starts_with("//") {
|
||||||
current_url.scheme + ":" + str_url
|
current_url.scheme + ":" + str_url
|
||||||
|
@ -41,11 +39,11 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
||||||
str_url.trim_left_chars(&'/')
|
str_url.trim_left_chars(&'/')
|
||||||
} else {
|
} else {
|
||||||
let mut path = ~[];
|
let mut path = ~[];
|
||||||
for current_url.path.split_iter('/').advance |p| {
|
for p in current_url.path.split_iter('/') {
|
||||||
path.push(p.to_str());
|
path.push(p.to_str());
|
||||||
}
|
}
|
||||||
let path = path.init();
|
let path = path.init();
|
||||||
let mut path = path.iter().transform(|x| copy *x).collect::<~[~str]>();
|
let mut path = path.iter().map(|x| (*x).clone()).collect::<~[~str]>();
|
||||||
path.push(str_url);
|
path.push(str_url);
|
||||||
let path = path.connect("/");
|
let path = path.connect("/");
|
||||||
|
|
||||||
|
@ -57,7 +55,7 @@ pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Need to handle errors
|
// FIXME: Need to handle errors
|
||||||
url::from_str(str_url).get()
|
url::from_str(str_url).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
mod make_url_tests {
|
mod make_url_tests {
|
||||||
|
@ -119,6 +117,6 @@ mod make_url_tests {
|
||||||
|
|
||||||
pub type UrlMap<T> = @mut HashMap<Url, T>;
|
pub type UrlMap<T> = @mut HashMap<Url, T>;
|
||||||
|
|
||||||
pub fn url_map<T: Copy>() -> UrlMap<T> {
|
pub fn url_map<T: Clone + 'static>() -> UrlMap<T> {
|
||||||
@mut HashMap::new()
|
@mut HashMap::new()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 78f84af79eb653fde2d50621fc3631043fa6fa9e
|
Subproject commit af20d6eea6eb4efe31f7f883e8d7073b2bd692a1
|
|
@ -1 +1 @@
|
||||||
Subproject commit 980254dd840772c8ee5f37056e7bd9f4d93d5377
|
Subproject commit 9621863ca3147412e78782122873d316b8a0f73d
|
|
@ -1 +1 @@
|
||||||
Subproject commit 641af36389a7592ef0faea2488ec08bd144e9bfe
|
Subproject commit 4e8043abbf103805fd6bb3708e111a4220d4280b
|
|
@ -1 +1 @@
|
||||||
Subproject commit 23bb17289846dd9486f633c0b5187c7ba333d943
|
Subproject commit 25495d9a80f11fdde4fa3cc6bcb3c0ea7462e0bb
|
|
@ -1 +1 @@
|
||||||
Subproject commit 77e9ed24ca7bb0f9a0b33d7fd888de2905dddcd4
|
Subproject commit c5dafee99adea0a31acea07dce09d4f81271a14a
|
|
@ -1 +1 @@
|
||||||
Subproject commit bf9d0ebf3e0283f8bdb505d29d93de9631f7877c
|
Subproject commit 479bccc6f323bc698856f3dc5a9ab93f4ffc8958
|
|
@ -1 +1 @@
|
||||||
Subproject commit 313e26f9202b44d09043485671bc903786c328e7
|
Subproject commit d0c3681561eb83b85773207e44bd2c22aa8445d2
|
|
@ -1 +1 @@
|
||||||
Subproject commit f155846fe043f9060fa05be696c203180e7371f7
|
Subproject commit 0679efa35b682863d25ac19fdb520c35f9a364a5
|
|
@ -1 +1 @@
|
||||||
Subproject commit 68875af396cb583e670dd5caad99431dac62f8db
|
Subproject commit c3a603bb641539bb2b7f3c159fd8ea3de045db8f
|
|
@ -1 +1 @@
|
||||||
Subproject commit c6774cb3ebdb20b1736fa3e8b5e8348fefbc987f
|
Subproject commit 44aec67e955dbbd7a56fa19f1e1705653a1a5dd6
|
|
@ -1 +1 @@
|
||||||
Subproject commit 789c7a43e28629ea0b568ce7d9a7ca8a0a975d34
|
Subproject commit 9ed02f7f0c4b704adb3ae60426bbc1b124e1a995
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3dc9f508b8517e4efddffb4703e3a5e9d63d4f25
|
Subproject commit 77921ee3f243ab90944ec44131ec98d20bc9551f
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5b9a447946b736802a0791eb1c24687849ad3984
|
Subproject commit fb352cf57ca59c16816a96408a3b3f6d4eaead00
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8999e447127c8674cdf130a2bd1759d9f94cd6ad
|
Subproject commit 028080a6cf41e66f7d426f0887b05aea1b4e445e
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 8f253edf62cfadfa18edb773aebd74bd62647ce4
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4d576047b5b94d98669080f3ac25efa053024d7e
|
Subproject commit ca00f10d255757d4f112a68b17f37afdc5462147
|
|
@ -1 +1 @@
|
||||||
Subproject commit 077de218a9c64608c60c536ef1e87de461852015
|
Subproject commit b99f72ccde8ca973add1246426540849ffc50792
|
|
@ -1 +1 @@
|
||||||
Subproject commit 177277d4aaeb56913f2eb04670679cae078cf70b
|
Subproject commit a23bb2fa8a8c86f24d7dd6af9e3dcab2f2f1d2b0
|
|
@ -1 +1 @@
|
||||||
Subproject commit d72f06f51220083111487940f19ad36d6ae17bd2
|
Subproject commit be68b4032793167f714deebaf438e89301db9871
|
|
@ -1 +1 @@
|
||||||
Subproject commit e83cca0e287db58a27ee77947a8d4dc3617a6ed0
|
Subproject commit ec61bd34561ec6dd22d792713d385f7480863d38
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8f7e491c675f46386adee39508eaa3ddb0f672ee
|
Subproject commit 1d014441ff8100e79521de42cb25300ed4092372
|
|
@ -1 +1 @@
|
||||||
Subproject commit a96c9f10677b0448e4ef69b5ad847da971758eb9
|
Subproject commit bd06cd169cf68de03438f6ab9ab87bc62243774e
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue