aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/gfx/display_list.rs3
-rw-r--r--src/components/gfx/font.rs20
-rw-r--r--src/components/gfx/gfx.rs1
-rw-r--r--src/components/gfx/platform/android/font.rs8
-rw-r--r--src/components/gfx/platform/linux/font.rs8
-rw-r--r--src/components/gfx/platform/macos/font.rs8
-rw-r--r--src/components/gfx/text/glyph.rs257
-rw-r--r--src/components/gfx/text/shaping/harfbuzz.rs20
-rw-r--r--src/components/gfx/text/text_run.rs45
-rw-r--r--src/components/gfx/text/util.rs12
-rw-r--r--src/components/main/constellation.rs39
-rw-r--r--src/components/main/css/matching.rs12
-rw-r--r--src/components/main/css/node_util.rs4
-rw-r--r--src/components/main/layout/box_.rs24
-rw-r--r--src/components/main/layout/construct.rs8
-rw-r--r--src/components/main/layout/extra.rs2
-rw-r--r--src/components/main/layout/inline.rs96
-rw-r--r--src/components/main/layout/text.rs55
-rw-r--r--src/components/main/layout/util.rs7
-rw-r--r--src/components/main/layout/wrapper.rs2
-rw-r--r--src/components/main/pipeline.rs32
-rw-r--r--[-rwxr-xr-x]src/components/main/servo.rs2
-rw-r--r--src/components/net/http_loader.rs8
-rw-r--r--src/components/script/dom/element.rs14
-rw-r--r--src/components/script/dom/htmliframeelement.rs55
-rw-r--r--src/components/script/dom/node.rs9
-rw-r--r--src/components/script/dom/window.rs4
-rw-r--r--src/components/script/html/hubbub_html_parser.rs56
-rw-r--r--src/components/script/script.rs1
-rw-r--r--src/components/script/script_task.rs252
-rw-r--r--src/components/util/range.rs175
-rw-r--r--src/components/util/url.rs6
32 files changed, 706 insertions, 539 deletions
diff --git a/src/components/gfx/display_list.rs b/src/components/gfx/display_list.rs
index 0a831f732d0..63ea5596e3c 100644
--- a/src/components/gfx/display_list.rs
+++ b/src/components/gfx/display_list.rs
@@ -16,6 +16,7 @@
use color::Color;
use render_context::RenderContext;
+use text::glyph::CharIndex;
use text::TextRun;
use collections::deque::Deque;
@@ -395,7 +396,7 @@ pub struct TextDisplayItem {
pub text_run: Arc<~TextRun>,
/// The range of text within the text run.
- pub range: Range<int>,
+ pub range: Range<CharIndex>,
/// The color of the text.
pub text_color: Color,
diff --git a/src/components/gfx/font.rs b/src/components/gfx/font.rs
index c5628e079d2..4470b1a372a 100644
--- a/src/components/gfx/font.rs
+++ b/src/components/gfx/font.rs
@@ -23,7 +23,7 @@ use servo_util::geometry::Au;
use platform::font_context::FontContextHandle;
use platform::font::{FontHandle, FontTable};
use render_context::RenderContext;
-use text::glyph::{GlyphStore, GlyphIndex};
+use text::glyph::{CharIndex, GlyphStore, GlyphId};
use text::shaping::ShaperMethods;
use text::{Shaper, TextRun};
@@ -45,8 +45,8 @@ pub trait FontHandleMethods {
fn clone_with_style(&self, fctx: &FontContextHandle, style: &UsedFontStyle)
-> Result<FontHandle, ()>;
- fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex>;
- fn glyph_h_advance(&self, GlyphIndex) -> Option<FractionalPixel>;
+ fn glyph_index(&self, codepoint: char) -> Option<GlyphId>;
+ fn glyph_h_advance(&self, GlyphId) -> Option<FractionalPixel>;
fn get_metrics(&self) -> FontMetrics;
fn get_table_for_tag(&self, FontTableTag) -> Option<FontTable>;
}
@@ -330,7 +330,7 @@ impl Font {
pub fn draw_text_into_context(&mut self,
rctx: &RenderContext,
run: &~TextRun,
- range: &Range<int>,
+ range: &Range<CharIndex>,
baseline_origin: Point2D<Au>,
color: Color) {
use libc::types::common::c99::{uint16_t, uint32_t};
@@ -353,7 +353,7 @@ impl Font {
let mut origin = baseline_origin.clone();
let mut azglyphs = vec!();
- azglyphs.reserve(range.length() as uint);
+ azglyphs.reserve(range.length().to_uint());
for (glyphs, _offset, slice_range) in run.iter_slices_for_range(range) {
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(&slice_range) {
@@ -361,7 +361,7 @@ impl Font {
let glyph_offset = glyph.offset().unwrap_or(Zero::zero());
let azglyph = struct__AzGlyph {
- mIndex: glyph.index() as uint32_t,
+ mIndex: glyph.id() as uint32_t,
mPosition: struct__AzPoint {
x: (origin.x + glyph_offset.x).to_nearest_px() as AzFloat,
y: (origin.y + glyph_offset.y).to_nearest_px() as AzFloat
@@ -391,7 +391,7 @@ impl Font {
}
}
- pub fn measure_text(&self, run: &TextRun, range: &Range<int>) -> RunMetrics {
+ pub fn measure_text(&self, run: &TextRun, range: &Range<CharIndex>) -> RunMetrics {
// TODO(Issue #199): alter advance direction for RTL
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
let mut advance = Au(0);
@@ -405,7 +405,7 @@ impl Font {
pub fn measure_text_for_slice(&self,
glyphs: &GlyphStore,
- slice_range: &Range<int>)
+ slice_range: &Range<CharIndex>)
-> RunMetrics {
let mut advance = Au(0);
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
@@ -430,11 +430,11 @@ impl Font {
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<GlyphId> {
self.handle.glyph_index(codepoint)
}
- pub fn glyph_h_advance(&mut self, glyph: GlyphIndex) -> FractionalPixel {
+ pub fn glyph_h_advance(&mut self, glyph: GlyphId) -> FractionalPixel {
let handle = &self.handle;
self.glyph_advance_cache.find_or_create(&glyph, |glyph| {
match handle.glyph_h_advance(*glyph) {
diff --git a/src/components/gfx/gfx.rs b/src/components/gfx/gfx.rs
index dd331b66589..f88a4b6e61b 100644
--- a/src/components/gfx/gfx.rs
+++ b/src/components/gfx/gfx.rs
@@ -23,6 +23,7 @@ extern crate png;
#[phase(syntax)]
extern crate servo_macros = "macros";
extern crate servo_net = "net";
+#[phase(syntax, link)]
extern crate servo_util = "util";
extern crate servo_msg = "msg";
extern crate style;
diff --git a/src/components/gfx/platform/android/font.rs b/src/components/gfx/platform/android/font.rs
index b8a4f110cc4..4c5f5245384 100644
--- a/src/components/gfx/platform/android/font.rs
+++ b/src/components/gfx/platform/android/font.rs
@@ -9,7 +9,7 @@ use font::{FontTableTag, FractionalPixel, SpecifiedFontStyle, UsedFontStyle};
use servo_util::geometry::Au;
use servo_util::geometry;
use platform::font_context::FontContextHandle;
-use text::glyph::GlyphIndex;
+use text::glyph::GlyphId;
use text::util::{float_to_fixed, fixed_to_float};
use style::computed_values::font_weight;
@@ -174,12 +174,12 @@ impl FontHandleMethods for FontHandle {
}
fn glyph_index(&self,
- codepoint: char) -> Option<GlyphIndex> {
+ codepoint: char) -> Option<GlyphId> {
assert!(self.face.is_not_null());
unsafe {
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
return if idx != 0 as FT_UInt {
- Some(idx as GlyphIndex)
+ Some(idx as GlyphId)
} else {
debug!("Invalid codepoint: {}", codepoint);
None
@@ -188,7 +188,7 @@ impl FontHandleMethods for FontHandle {
}
fn glyph_h_advance(&self,
- glyph: GlyphIndex) -> Option<FractionalPixel> {
+ glyph: GlyphId) -> Option<FractionalPixel> {
assert!(self.face.is_not_null());
unsafe {
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
diff --git a/src/components/gfx/platform/linux/font.rs b/src/components/gfx/platform/linux/font.rs
index 94527b3b35d..c5b704ac9bb 100644
--- a/src/components/gfx/platform/linux/font.rs
+++ b/src/components/gfx/platform/linux/font.rs
@@ -9,7 +9,7 @@ use font::{FontTableTag, FractionalPixel, SpecifiedFontStyle, UsedFontStyle};
use servo_util::geometry::Au;
use servo_util::geometry;
use platform::font_context::FontContextHandle;
-use text::glyph::GlyphIndex;
+use text::glyph::GlyphId;
use text::util::{float_to_fixed, fixed_to_float};
use style::computed_values::font_weight;
@@ -174,12 +174,12 @@ impl FontHandleMethods for FontHandle {
}
fn glyph_index(&self,
- codepoint: char) -> Option<GlyphIndex> {
+ codepoint: char) -> Option<GlyphId> {
assert!(self.face.is_not_null());
unsafe {
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
return if idx != 0 as FT_UInt {
- Some(idx as GlyphIndex)
+ Some(idx as GlyphId)
} else {
debug!("Invalid codepoint: {}", codepoint);
None
@@ -188,7 +188,7 @@ impl FontHandleMethods for FontHandle {
}
fn glyph_h_advance(&self,
- glyph: GlyphIndex) -> Option<FractionalPixel> {
+ glyph: GlyphId) -> Option<FractionalPixel> {
assert!(self.face.is_not_null());
unsafe {
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
diff --git a/src/components/gfx/platform/macos/font.rs b/src/components/gfx/platform/macos/font.rs
index 5441415b653..48f0d318b2c 100644
--- a/src/components/gfx/platform/macos/font.rs
+++ b/src/components/gfx/platform/macos/font.rs
@@ -14,7 +14,7 @@ use font::{FractionalPixel, SpecifiedFontStyle};
use servo_util::geometry::{Au, px_to_pt};
use servo_util::geometry;
use platform::macos::font_context::FontContextHandle;
-use text::glyph::GlyphIndex;
+use text::glyph::GlyphId;
use style::computed_values::font_weight;
use core_foundation::base::CFIndex;
@@ -125,7 +125,7 @@ impl FontHandleMethods for FontHandle {
return FontHandle::new_from_CTFont(fctx, new_font);
}
- fn glyph_index(&self, codepoint: char) -> Option<GlyphIndex> {
+ fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
let characters: [UniChar, ..1] = [codepoint as UniChar];
let glyphs: [CGGlyph, ..1] = [0 as CGGlyph];
let count: CFIndex = 1;
@@ -140,10 +140,10 @@ impl FontHandleMethods for FontHandle {
}
assert!(glyphs[0] != 0); // FIXME: error handling
- return Some(glyphs[0] as GlyphIndex);
+ return Some(glyphs[0] as GlyphId);
}
- fn glyph_h_advance(&self, glyph: GlyphIndex) -> Option<FractionalPixel> {
+ fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
let glyphs = [glyph as CGGlyph];
let advance = self.ctfont.get_advances_for_glyphs(kCTFontDefaultOrientation,
&glyphs[0],
diff --git a/src/components/gfx/text/glyph.rs b/src/components/gfx/text/glyph.rs
index 1eb04c81b36..62bf4fb9f05 100644
--- a/src/components/gfx/text/glyph.rs
+++ b/src/components/gfx/text/glyph.rs
@@ -3,7 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use servo_util::vec::*;
-use servo_util::range::Range;
+use servo_util::range;
+use servo_util::range::{Range, RangeIndex, EachIndex};
use servo_util::geometry::Au;
use std::cmp::{Ord, Eq};
@@ -11,7 +12,6 @@ use std::num::{NumCast, Zero};
use std::mem;
use std::u16;
use std::slice;
-use std::iter;
use geom::point::Point2D;
/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
@@ -24,13 +24,13 @@ use geom::point::Point2D;
/// in DetailedGlyphStore.
#[deriving(Clone)]
struct GlyphEntry {
- value: u32
+ value: u32,
}
impl GlyphEntry {
fn new(value: u32) -> GlyphEntry {
GlyphEntry {
- value: value
+ value: value,
}
}
@@ -39,15 +39,15 @@ impl GlyphEntry {
}
// Creates a GlyphEntry for the common case
- fn simple(index: GlyphIndex, advance: Au) -> GlyphEntry {
- assert!(is_simple_glyph_id(index));
+ fn simple(id: GlyphId, advance: Au) -> GlyphEntry {
+ assert!(is_simple_glyph_id(id));
assert!(is_simple_advance(advance));
- let index_mask = index as u32;
+ let id_mask = id as u32;
let Au(advance) = advance;
let advance_mask = (advance as u32) << GLYPH_ADVANCE_SHIFT;
- GlyphEntry::new(index_mask | advance_mask | FLAG_IS_SIMPLE_GLYPH)
+ GlyphEntry::new(id_mask | advance_mask | FLAG_IS_SIMPLE_GLYPH)
}
// Create a GlyphEntry for uncommon case; should be accompanied by
@@ -83,15 +83,15 @@ impl GlyphEntry {
}
}
-/// The index of a particular glyph within a font
-pub type GlyphIndex = u32;
+/// The id of a particular glyph within a font
+pub type GlyphId = u32;
// TODO: unify with bit flags?
#[deriving(Eq)]
pub enum BreakType {
BreakTypeNone,
BreakTypeNormal,
- BreakTypeHyphen
+ BreakTypeHyphen,
}
static BREAK_TYPE_NONE: u8 = 0x0;
@@ -100,12 +100,12 @@ static BREAK_TYPE_HYPHEN: u8 = 0x2;
fn break_flag_to_enum(flag: u8) -> BreakType {
if (flag & BREAK_TYPE_NORMAL) != 0 {
- return BreakTypeNormal;
+ BreakTypeNormal
+ } else if (flag & BREAK_TYPE_HYPHEN) != 0 {
+ BreakTypeHyphen
+ } else {
+ BreakTypeNone
}
- if (flag & BREAK_TYPE_HYPHEN) != 0 {
- return BreakTypeHyphen;
- }
- BreakTypeNone
}
fn break_enum_to_flag(e: BreakType) -> u8 {
@@ -151,8 +151,8 @@ static FLAG_CHAR_IS_NEWLINE: u32 = 0x00000010;
//static FLAG_CHAR_IS_LOW_SURROGATE: u32 = 0x00000020;
//static CHAR_IDENTITY_FLAGS_MASK: u32 = 0x00000038;
-fn is_simple_glyph_id(glyphId: GlyphIndex) -> bool {
- ((glyphId as u32) & GLYPH_ID_MASK) == glyphId
+fn is_simple_glyph_id(id: GlyphId) -> bool {
+ ((id as u32) & GLYPH_ID_MASK) == id
}
fn is_simple_advance(advance: Au) -> bool {
@@ -171,7 +171,7 @@ impl GlyphEntry {
NumCast::from((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT).unwrap()
}
- fn index(&self) -> GlyphIndex {
+ fn id(&self) -> GlyphId {
self.value & GLYPH_ID_MASK
}
@@ -253,19 +253,19 @@ impl GlyphEntry {
// correspond to one character, or the glyph's data couldn't be packed.
#[deriving(Clone)]
struct DetailedGlyph {
- index: GlyphIndex,
+ id: GlyphId,
// glyph's advance, in the text's direction (RTL or RTL)
advance: Au,
// glyph's offset from the font's em-box (from top-left)
- offset: Point2D<Au>
+ offset: Point2D<Au>,
}
impl DetailedGlyph {
- fn new(index: GlyphIndex, advance: Au, offset: Point2D<Au>) -> DetailedGlyph {
+ fn new(id: GlyphId, advance: Au, offset: Point2D<Au>) -> DetailedGlyph {
DetailedGlyph {
- index: index,
+ id: id,
advance: advance,
- offset: offset
+ offset: offset,
}
}
}
@@ -273,9 +273,9 @@ impl DetailedGlyph {
#[deriving(Eq, Clone)]
struct DetailedGlyphRecord {
// source string offset/GlyphEntry offset in the TextRun
- entry_offset: int,
+ entry_offset: CharIndex,
// offset into the detailed glyphs buffer
- detail_offset: int
+ detail_offset: int,
}
impl Ord for DetailedGlyphRecord {
@@ -312,14 +312,14 @@ impl<'a> DetailedGlyphStore {
DetailedGlyphStore {
detail_buffer: vec!(), // TODO: default size?
detail_lookup: vec!(),
- lookup_is_sorted: false
+ lookup_is_sorted: false,
}
}
- fn add_detailed_glyphs_for_entry(&mut self, entry_offset: int, glyphs: &[DetailedGlyph]) {
+ fn add_detailed_glyphs_for_entry(&mut self, entry_offset: CharIndex, glyphs: &[DetailedGlyph]) {
let entry = DetailedGlyphRecord {
entry_offset: entry_offset,
- detail_offset: self.detail_buffer.len() as int
+ detail_offset: self.detail_buffer.len() as int,
};
debug!("Adding entry[off={}] for detailed glyphs: {:?}", entry_offset, glyphs);
@@ -340,7 +340,7 @@ impl<'a> DetailedGlyphStore {
self.lookup_is_sorted = false;
}
- fn get_detailed_glyphs_for_entry(&'a self, entry_offset: int, count: u16)
+ fn get_detailed_glyphs_for_entry(&'a self, entry_offset: CharIndex, count: u16)
-> &'a [DetailedGlyph] {
debug!("Requesting detailed glyphs[n={}] for entry[off={}]", count, entry_offset);
@@ -355,7 +355,7 @@ impl<'a> DetailedGlyphStore {
let key = DetailedGlyphRecord {
entry_offset: entry_offset,
- detail_offset: 0 // unused
+ detail_offset: 0, // unused
};
// FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred.
@@ -371,7 +371,7 @@ impl<'a> DetailedGlyphStore {
}
fn get_detailed_glyph_with_index(&'a self,
- entry_offset: int,
+ entry_offset: CharIndex,
detail_offset: u16)
-> &'a DetailedGlyph {
assert!((detail_offset as uint) <= self.detail_buffer.len());
@@ -379,7 +379,7 @@ impl<'a> DetailedGlyphStore {
let key = DetailedGlyphRecord {
entry_offset: entry_offset,
- detail_offset: 0 // unused
+ detail_offset: 0, // unused
};
// FIXME: This is a workaround for borrow of self.detail_lookup not getting inferred.
@@ -423,7 +423,7 @@ impl<'a> DetailedGlyphStore {
// This struct is used by GlyphStore clients to provide new glyph data.
// It should be allocated on the stack and passed by reference to GlyphStore.
pub struct GlyphData {
- index: GlyphIndex,
+ id: GlyphId,
advance: Au,
offset: Point2D<Au>,
is_missing: bool,
@@ -432,7 +432,7 @@ pub struct GlyphData {
}
impl GlyphData {
- pub fn new(index: GlyphIndex,
+ pub fn new(id: GlyphId,
advance: Au,
offset: Option<Point2D<Au>>,
is_missing: bool,
@@ -441,11 +441,11 @@ impl GlyphData {
-> GlyphData {
let offset = match offset {
None => Zero::zero(),
- Some(o) => o
+ Some(o) => o,
};
GlyphData {
- index: index,
+ id: id,
advance: advance,
offset: offset,
is_missing: is_missing,
@@ -460,16 +460,16 @@ impl GlyphData {
// Rather than eagerly assembling and copying glyph data, it only retrieves
// values as they are needed from the GlyphStore, using provided offsets.
pub enum GlyphInfo<'a> {
- SimpleGlyphInfo(&'a GlyphStore, int),
- DetailGlyphInfo(&'a GlyphStore, int, u16)
+ SimpleGlyphInfo(&'a GlyphStore, CharIndex),
+ DetailGlyphInfo(&'a GlyphStore, CharIndex, u16),
}
impl<'a> GlyphInfo<'a> {
- pub fn index(self) -> GlyphIndex {
+ pub fn id(self) -> GlyphId {
match self {
- SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i as uint).index(),
+ SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i.to_uint()).id(),
DetailGlyphInfo(store, entry_i, detail_j) => {
- store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).index
+ store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).id
}
}
}
@@ -478,7 +478,7 @@ impl<'a> GlyphInfo<'a> {
// FIXME: Resolution conflicts with IteratorUtil trait so adding trailing _
pub fn advance(self) -> Au {
match self {
- SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i as uint).advance(),
+ SimpleGlyphInfo(store, entry_i) => store.entry_buffer.get(entry_i.to_uint()).advance(),
DetailGlyphInfo(store, entry_i, detail_j) => {
store.detail_store.get_detailed_glyph_with_index(entry_i, detail_j).advance
}
@@ -495,17 +495,43 @@ impl<'a> GlyphInfo<'a> {
}
}
-// Public data structure and API for storing and retrieving glyph data
+/// Stores the glyph data belonging to a text run.
+///
+/// Simple glyphs are stored inline in the `entry_buffer`, detailed glyphs are
+/// stored as pointers into the `detail_store`.
+///
+/// ~~~
+/// +- GlyphStore --------------------------------+
+/// | +---+---+---+---+---+---+---+ |
+/// | entry_buffer: | | s | | s | | s | s | | d = detailed
+/// | +-|-+---+-|-+---+-|-+---+---+ | s = simple
+/// | | | | |
+/// | | +---+-------+ |
+/// | | | |
+/// | +-V-+-V-+ |
+/// | detail_store: | d | d | |
+/// | +---+---+ |
+/// +---------------------------------------------+
+/// ~~~
pub struct GlyphStore {
// TODO(pcwalton): Allocation of this buffer is expensive. Consider a small-vector
// optimization.
+ /// A buffer of glyphs within the text run, in the order in which they
+ /// appear in the input text
entry_buffer: Vec<GlyphEntry>,
-
+ /// A store of the detailed glyph data. Detailed glyphs contained in the
+ /// `entry_buffer` point to locations in this data structure.
detail_store: DetailedGlyphStore,
is_whitespace: bool,
}
+range_index! {
+ #[doc = "An index that refers to a character in a text run. This could \
+ point to the middle of a glyph."]
+ struct CharIndex(int)
+}
+
impl<'a> GlyphStore {
// Initializes the glyph store, but doesn't actually shape anything.
// Use the set_glyph, set_glyphs() methods to store glyph data.
@@ -519,8 +545,8 @@ impl<'a> GlyphStore {
}
}
- pub fn char_len(&self) -> int {
- self.entry_buffer.len() as int
+ pub fn char_len(&self) -> CharIndex {
+ CharIndex(self.entry_buffer.len() as int)
}
pub fn is_whitespace(&self) -> bool {
@@ -531,32 +557,32 @@ impl<'a> GlyphStore {
self.detail_store.ensure_sorted();
}
- pub fn add_glyph_for_char_index(&mut self, i: int, data: &GlyphData) {
+ pub fn add_glyph_for_char_index(&mut self, i: CharIndex, data: &GlyphData) {
fn glyph_is_compressible(data: &GlyphData) -> bool {
- is_simple_glyph_id(data.index)
+ is_simple_glyph_id(data.id)
&& is_simple_advance(data.advance)
&& data.offset.is_zero()
&& data.cluster_start // others are stored in detail buffer
}
assert!(data.ligature_start); // can't compress ligature continuation glyphs.
- assert!(i < self.entry_buffer.len() as int);
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
let entry = match (data.is_missing, glyph_is_compressible(data)) {
(true, _) => GlyphEntry::missing(1),
- (false, true) => GlyphEntry::simple(data.index, data.advance),
+ (false, true) => GlyphEntry::simple(data.id, data.advance),
(false, false) => {
- let glyph = [DetailedGlyph::new(data.index, data.advance, data.offset)];
+ let glyph = [DetailedGlyph::new(data.id, data.advance, data.offset)];
self.detail_store.add_detailed_glyphs_for_entry(i, glyph);
GlyphEntry::complex(data.cluster_start, data.ligature_start, 1)
}
- }.adapt_character_flags_of_entry(*self.entry_buffer.get(i as uint));
+ }.adapt_character_flags_of_entry(*self.entry_buffer.get(i.to_uint()));
- *self.entry_buffer.get_mut(i as uint) = entry;
+ *self.entry_buffer.get_mut(i.to_uint()) = entry;
}
- pub fn add_glyphs_for_char_index(&mut self, i: int, data_for_glyphs: &[GlyphData]) {
- assert!(i < self.entry_buffer.len() as int);
+ pub fn add_glyphs_for_char_index(&mut self, i: CharIndex, data_for_glyphs: &[GlyphData]) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
assert!(data_for_glyphs.len() > 0);
let glyph_count = data_for_glyphs.len() as int;
@@ -566,7 +592,7 @@ impl<'a> GlyphStore {
true => GlyphEntry::missing(glyph_count),
false => {
let glyphs_vec = slice::from_fn(glyph_count as uint, |i| {
- DetailedGlyph::new(data_for_glyphs[i].index,
+ DetailedGlyph::new(data_for_glyphs[i].id,
data_for_glyphs[i].advance,
data_for_glyphs[i].offset)
});
@@ -576,115 +602,116 @@ impl<'a> GlyphStore {
first_glyph_data.ligature_start,
glyph_count)
}
- }.adapt_character_flags_of_entry(*self.entry_buffer.get(i as uint));
+ }.adapt_character_flags_of_entry(*self.entry_buffer.get(i.to_uint()));
debug!("Adding multiple glyphs[idx={}, count={}]: {:?}", i, glyph_count, entry);
- *self.entry_buffer.get_mut(i as uint) = entry;
+ *self.entry_buffer.get_mut(i.to_uint()) = entry;
}
// used when a character index has no associated glyph---for example, a ligature continuation.
- pub fn add_nonglyph_for_char_index(&mut self, i: int, cluster_start: bool, ligature_start: bool) {
- assert!(i < self.entry_buffer.len() as int);
+ pub fn add_nonglyph_for_char_index(&mut self, i: CharIndex, cluster_start: bool, ligature_start: bool) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
debug!("adding spacer for chracter without associated glyph[idx={}]", i);
- *self.entry_buffer.get_mut(i as uint) = entry;
+ *self.entry_buffer.get_mut(i.to_uint()) = entry;
}
- pub fn iter_glyphs_for_char_index(&'a self, i: int) -> GlyphIterator<'a> {
- self.iter_glyphs_for_char_range(&Range::new(i as int, 1))
+ pub fn iter_glyphs_for_char_index(&'a self, i: CharIndex) -> GlyphIterator<'a> {
+ self.iter_glyphs_for_char_range(&Range::new(i, CharIndex(1)))
}
#[inline]
- pub fn iter_glyphs_for_char_range(&'a self, rang: &Range<int>) -> GlyphIterator<'a> {
- if rang.begin() >= self.entry_buffer.len() as int {
+ pub fn iter_glyphs_for_char_range(&'a self, rang: &Range<CharIndex>) -> GlyphIterator<'a> {
+ if rang.begin() >= CharIndex(self.entry_buffer.len() as int) {
fail!("iter_glyphs_for_range: range.begin beyond length!");
}
- if rang.end() > self.entry_buffer.len() as int {
+ if rang.end() > CharIndex(self.entry_buffer.len() as int) {
fail!("iter_glyphs_for_range: range.end beyond length!");
}
GlyphIterator {
store: self,
char_index: rang.begin(),
- char_range: rang.eachi(),
- glyph_range: None
+ char_range: rang.each_index(),
+ glyph_range: None,
}
}
// getter methods
- pub fn char_is_space(&self, i: int) -> bool {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).char_is_space()
+ pub fn char_is_space(&self, i: CharIndex) -> bool {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).char_is_space()
}
- pub fn char_is_tab(&self, i: int) -> bool {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).char_is_tab()
+ pub fn char_is_tab(&self, i: CharIndex) -> bool {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).char_is_tab()
}
- pub fn char_is_newline(&self, i: int) -> bool {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).char_is_newline()
+ pub fn char_is_newline(&self, i: CharIndex) -> bool {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).char_is_newline()
}
- pub fn is_ligature_start(&self, i: int) -> bool {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).is_ligature_start()
+ pub fn is_ligature_start(&self, i: CharIndex) -> bool {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).is_ligature_start()
}
- pub fn is_cluster_start(&self, i: int) -> bool {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).is_cluster_start()
+ pub fn is_cluster_start(&self, i: CharIndex) -> bool {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).is_cluster_start()
}
- pub fn can_break_before(&self, i: int) -> BreakType {
- assert!(i < self.entry_buffer.len() as int);
- self.entry_buffer.get(i as uint).can_break_before()
+ pub fn can_break_before(&self, i: CharIndex) -> BreakType {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ self.entry_buffer.get(i.to_uint()).can_break_before()
}
// setter methods
- pub fn set_char_is_space(&mut self, i: int) {
- assert!(i < self.entry_buffer.len() as int);
- let entry = *self.entry_buffer.get(i as uint);
- *self.entry_buffer.get_mut(i as uint) = entry.set_char_is_space();
+ pub fn set_char_is_space(&mut self, i: CharIndex) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ let entry = *self.entry_buffer.get(i.to_uint());
+ *self.entry_buffer.get_mut(i.to_uint()) = entry.set_char_is_space();
}
- pub fn set_char_is_tab(&mut self, i: int) {
- assert!(i < self.entry_buffer.len() as int);
- let entry = *self.entry_buffer.get(i as uint);
- *self.entry_buffer.get_mut(i as uint) = entry.set_char_is_tab();
+ pub fn set_char_is_tab(&mut self, i: CharIndex) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ let entry = *self.entry_buffer.get(i.to_uint());
+ *self.entry_buffer.get_mut(i.to_uint()) = entry.set_char_is_tab();
}
- pub fn set_char_is_newline(&mut self, i: int) {
- assert!(i < self.entry_buffer.len() as int);
- let entry = *self.entry_buffer.get(i as uint);
- *self.entry_buffer.get_mut(i as uint) = entry.set_char_is_newline();
+ pub fn set_char_is_newline(&mut self, i: CharIndex) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ let entry = *self.entry_buffer.get(i.to_uint());
+ *self.entry_buffer.get_mut(i.to_uint()) = entry.set_char_is_newline();
}
- pub fn set_can_break_before(&mut self, i: int, t: BreakType) {
- assert!(i < self.entry_buffer.len() as int);
- let entry = *self.entry_buffer.get(i as uint);
- *self.entry_buffer.get_mut(i as uint) = entry.set_can_break_before(t);
+ pub fn set_can_break_before(&mut self, i: CharIndex, t: BreakType) {
+ assert!(i < CharIndex(self.entry_buffer.len() as int));
+ let entry = *self.entry_buffer.get(i.to_uint());
+ *self.entry_buffer.get_mut(i.to_uint()) = entry.set_can_break_before(t);
}
}
+/// An iterator over the glyphs in a character range in a `GlyphStore`.
pub struct GlyphIterator<'a> {
store: &'a GlyphStore,
- char_index: int,
- char_range: iter::Range<int>,
- glyph_range: Option<iter::Range<int>>,
+ char_index: CharIndex,
+ char_range: EachIndex<int, CharIndex>,
+ glyph_range: Option<EachIndex<int, CharIndex>>,
}
impl<'a> GlyphIterator<'a> {
// Slow path when there is a glyph range.
#[inline(never)]
- fn next_glyph_range(&mut self) -> Option<(int, GlyphInfo<'a>)> {
+ fn next_glyph_range(&mut self) -> Option<(CharIndex, GlyphInfo<'a>)> {
match self.glyph_range.get_mut_ref().next() {
Some(j) => Some((self.char_index,
- DetailGlyphInfo(self.store, self.char_index, j as u16))),
+ DetailGlyphInfo(self.store, self.char_index, j.get() as u16 /* ??? */))),
None => {
// No more glyphs for current character. Try to get another.
self.glyph_range = None;
@@ -695,15 +722,15 @@ impl<'a> GlyphIterator<'a> {
// Slow path when there is a complex glyph.
#[inline(never)]
- fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: int)
- -> Option<(int, GlyphInfo<'a>)> {
+ fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: CharIndex)
+ -> Option<(CharIndex, GlyphInfo<'a>)> {
let glyphs = self.store.detail_store.get_detailed_glyphs_for_entry(i, entry.glyph_count());
- self.glyph_range = Some(range(0, glyphs.len() as int));
+ self.glyph_range = Some(range::each_index(CharIndex(0), CharIndex(glyphs.len() as int)));
self.next()
}
}
-impl<'a> Iterator<(int, GlyphInfo<'a>)> for GlyphIterator<'a> {
+impl<'a> Iterator<(CharIndex, GlyphInfo<'a>)> for GlyphIterator<'a> {
// I tried to start with something simpler and apply FlatMap, but the
// inability to store free variables in the FlatMap struct was problematic.
//
@@ -711,7 +738,7 @@ impl<'a> Iterator<(int, GlyphInfo<'a>)> for GlyphIterator<'a> {
// slow paths, which should not be inlined, are `next_glyph_range()` and
// `next_complex_glyph()`.
#[inline(always)]
- fn next(&mut self) -> Option<(int, GlyphInfo<'a>)> {
+ fn next(&mut self) -> Option<(CharIndex, GlyphInfo<'a>)> {
// Would use 'match' here but it borrows contents in a way that
// interferes with mutation.
if self.glyph_range.is_some() {
@@ -721,8 +748,8 @@ impl<'a> Iterator<(int, GlyphInfo<'a>)> for GlyphIterator<'a> {
match self.char_range.next() {
Some(i) => {
self.char_index = i;
- assert!(i < self.store.entry_buffer.len() as int);
- let entry = self.store.entry_buffer.get(i as uint);
+ assert!(i < CharIndex(self.store.entry_buffer.len() as int));
+ let entry = self.store.entry_buffer.get(i.to_uint());
if entry.is_simple() {
Some((self.char_index, SimpleGlyphInfo(self.store, i)))
} else {
diff --git a/src/components/gfx/text/shaping/harfbuzz.rs b/src/components/gfx/text/shaping/harfbuzz.rs
index fc07de9422d..4a5111b9839 100644
--- a/src/components/gfx/text/shaping/harfbuzz.rs
+++ b/src/components/gfx/text/shaping/harfbuzz.rs
@@ -6,7 +6,7 @@ extern crate harfbuzz;
use font::{Font, FontHandleMethods, FontTableMethods, FontTableTag};
use platform::font::FontTable;
-use text::glyph::{GlyphStore, GlyphIndex, GlyphData};
+use text::glyph::{CharIndex, GlyphStore, GlyphId, GlyphData};
use text::shaping::ShaperMethods;
use text::util::{float_to_fixed, fixed_to_float};
@@ -55,7 +55,7 @@ pub struct ShapedGlyphData {
pub struct ShapedGlyphEntry {
cluster: int,
- codepoint: GlyphIndex,
+ codepoint: GlyphId,
advance: Au,
offset: Option<Point2D<Au>>,
}
@@ -125,7 +125,7 @@ impl ShapedGlyphData {
ShapedGlyphEntry {
cluster: (*glyph_info_i).cluster as int,
- codepoint: (*glyph_info_i).codepoint as GlyphIndex,
+ codepoint: (*glyph_info_i).codepoint as GlyphId,
advance: x_advance,
offset: offset,
}
@@ -229,7 +229,7 @@ impl Shaper {
// GlyphStore records are indexed by character, not byte offset.
// so, we must be careful to increment this when saving glyph entries.
- let mut char_idx = 0;
+ let mut char_idx = CharIndex(0);
assert!(glyph_count <= char_max);
@@ -316,7 +316,7 @@ impl Shaper {
// extend glyph range to max glyph index covered by char_span,
// in cases where one char made several glyphs and left some unassociated chars.
let mut max_glyph_idx = glyph_span.end();
- for i in char_byte_span.eachi() {
+ for i in char_byte_span.each_index() {
if byteToGlyph[i as uint] > NO_GLYPH {
max_glyph_idx = cmp::max(byteToGlyph[i as uint] as int + 1, max_glyph_idx);
}
@@ -340,7 +340,7 @@ impl Shaper {
probably doesn't work.");
let mut all_glyphs_are_within_cluster: bool = true;
- for j in glyph_span.eachi() {
+ for j in glyph_span.each_index() {
let loc = glyph_data.byte_offset_of_glyph(j);
if !char_byte_span.contains(loc) {
all_glyphs_are_within_cluster = false;
@@ -414,7 +414,7 @@ impl Shaper {
// collect all glyphs to be assigned to the first character.
let mut datas = vec!();
- for glyph_i in glyph_span.eachi() {
+ for glyph_i in glyph_span.each_index() {
let shape = glyph_data.get_entry_for_glyph(glyph_i, &mut y_pos);
datas.push(GlyphData::new(shape.codepoint,
shape.advance,
@@ -435,7 +435,7 @@ impl Shaper {
drop(range.ch);
i = range.next as int;
if i >= covered_byte_span.end() { break; }
- char_idx += 1;
+ char_idx = char_idx + CharIndex(1);
glyphs.add_nonglyph_for_char_index(char_idx, false, false);
}
}
@@ -445,7 +445,7 @@ impl Shaper {
glyph_span.reset(end, 0);
let end = char_byte_span.end();; // FIXME: borrow checker workaround
char_byte_span.reset(end, 0);
- char_idx += 1;
+ char_idx = char_idx + CharIndex(1);
}
// this must be called after adding all glyph data; it sorts the
@@ -485,7 +485,7 @@ extern fn glyph_h_advance_func(_: *hb_font_t,
assert!(font.is_not_null());
unsafe {
- let advance = (*font).glyph_h_advance(glyph as GlyphIndex);
+ let advance = (*font).glyph_h_advance(glyph as GlyphId);
Shaper::float_to_fixed(advance)
}
}
diff --git a/src/components/gfx/text/text_run.rs b/src/components/gfx/text/text_run.rs
index e4ff683f6d6..a61769cdacf 100644
--- a/src/components/gfx/text/text_run.rs
+++ b/src/components/gfx/text/text_run.rs
@@ -8,7 +8,7 @@ use servo_util::range::Range;
use std::slice::Items;
use style::computed_values::text_decoration;
use sync::Arc;
-use text::glyph::GlyphStore;
+use text::glyph::{CharIndex, GlyphStore};
/// A text run.
#[deriving(Clone)]
@@ -18,19 +18,20 @@ pub struct TextRun {
pub font_metrics: FontMetrics,
pub font_style: FontStyle,
pub decoration: text_decoration::T,
+ // An Arc pointing to a Vec of Arcs?! Wat.
pub glyphs: Arc<Vec<Arc<GlyphStore>>>,
}
pub struct SliceIterator<'a> {
glyph_iter: Items<'a, Arc<GlyphStore>>,
- range: Range<int>,
- offset: int,
+ range: Range<CharIndex>,
+ offset: CharIndex,
}
-impl<'a> Iterator<(&'a GlyphStore, int, Range<int>)> for SliceIterator<'a> {
+impl<'a> Iterator<(&'a GlyphStore, CharIndex, Range<CharIndex>)> for SliceIterator<'a> {
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
#[inline(always)]
- fn next(&mut self) -> Option<(&'a GlyphStore, int, Range<int>)> {
+ fn next(&mut self) -> Option<(&'a GlyphStore, CharIndex, Range<CharIndex>)> {
loop {
let slice_glyphs = self.glyph_iter.next();
if slice_glyphs.is_none() {
@@ -40,10 +41,10 @@ impl<'a> Iterator<(&'a GlyphStore, int, Range<int>)> for SliceIterator<'a> {
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().unwrap()));
+ char_range.shift_by(-self.offset);
let old_offset = self.offset;
- self.offset += slice_glyphs.char_len();
+ self.offset = self.offset + slice_glyphs.char_len();
if !char_range.is_empty() {
return Some((&**slice_glyphs, old_offset, char_range))
}
@@ -52,24 +53,24 @@ impl<'a> Iterator<(&'a GlyphStore, int, Range<int>)> for SliceIterator<'a> {
}
pub struct LineIterator<'a> {
- range: Range<int>,
- clump: Option<Range<int>>,
+ range: Range<CharIndex>,
+ clump: Option<Range<CharIndex>>,
slices: SliceIterator<'a>,
}
-impl<'a> Iterator<Range<int>> for LineIterator<'a> {
- fn next(&mut self) -> Option<Range<int>> {
+impl<'a> Iterator<Range<CharIndex>> for LineIterator<'a> {
+ fn next(&mut self) -> Option<Range<CharIndex>> {
// 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().unwrap());
+ c.extend_by(slice_range.length());
}
(false, None) => {
let mut c = slice_range;
- c.shift_by(offset.to_int().unwrap());
+ c.shift_by(offset);
self.clump = Some(c);
}
(true, None) => { /* chomp whitespace */ }
@@ -165,8 +166,8 @@ impl<'a> TextRun {
glyphs
}
- pub fn char_len(&self) -> int {
- self.glyphs.iter().fold(0, |len, slice_glyphs| {
+ pub fn char_len(&self) -> CharIndex {
+ self.glyphs.iter().fold(CharIndex(0), |len, slice_glyphs| {
len + slice_glyphs.char_len()
})
}
@@ -175,14 +176,14 @@ impl<'a> TextRun {
&*self.glyphs
}
- pub fn range_is_trimmable_whitespace(&self, range: &Range<int>) -> bool {
+ pub fn range_is_trimmable_whitespace(&self, range: &Range<CharIndex>) -> bool {
for (slice_glyphs, _, _) in self.iter_slices_for_range(range) {
if !slice_glyphs.is_whitespace() { return false; }
}
true
}
- pub fn metrics_for_range(&self, range: &Range<int>) -> RunMetrics {
+ pub fn metrics_for_range(&self, range: &Range<CharIndex>) -> RunMetrics {
// TODO(Issue #199): alter advance direction for RTL
// TODO(Issue #98): using inter-char and inter-word spacing settings when measuring text
let mut advance = Au(0);
@@ -194,14 +195,14 @@ impl<'a> TextRun {
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
}
- pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<int>) -> RunMetrics {
+ pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<CharIndex>) -> RunMetrics {
let mut advance = Au(0);
for (_i, glyph) in glyphs.iter_glyphs_for_char_range(slice_range) {
advance = advance + glyph.advance();
}
RunMetrics::new(advance, self.font_metrics.ascent, self.font_metrics.descent)
}
- pub fn min_width_for_range(&self, range: &Range<int>) -> Au {
+ pub fn min_width_for_range(&self, range: &Range<CharIndex>) -> Au {
let mut max_piece_width = Au(0);
debug!("iterating outer range {:?}", range);
for (_, offset, slice_range) in self.iter_slices_for_range(range) {
@@ -212,15 +213,15 @@ impl<'a> TextRun {
max_piece_width
}
- pub fn iter_slices_for_range(&'a self, range: &Range<int>) -> SliceIterator<'a> {
+ pub fn iter_slices_for_range(&'a self, range: &Range<CharIndex>) -> SliceIterator<'a> {
SliceIterator {
glyph_iter: self.glyphs.iter(),
range: *range,
- offset: 0,
+ offset: CharIndex(0),
}
}
- pub fn iter_natural_lines_for_range(&'a self, range: &Range<int>) -> LineIterator<'a> {
+ pub fn iter_natural_lines_for_range(&'a self, range: &Range<CharIndex>) -> LineIterator<'a> {
LineIterator {
range: *range,
clump: None,
diff --git a/src/components/gfx/text/util.rs b/src/components/gfx/text/util.rs
index 6aaafe4b249..5c25a007337 100644
--- a/src/components/gfx/text/util.rs
+++ b/src/components/gfx/text/util.rs
@@ -2,6 +2,8 @@
* 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/. */
+use text::glyph::CharIndex;
+
#[deriving(Eq)]
pub enum CompressionMode {
CompressNone,
@@ -20,11 +22,13 @@ pub enum CompressionMode {
// * Issue #114: record skipped and kept chars for mapping original to new text
//
// * Untracked: various edge cases for bidi, CJK, etc.
-pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bool, new_line_pos: &mut Vec<int>) -> (~str, bool) {
+pub fn transform_text(text: &str, mode: CompressionMode,
+ incoming_whitespace: bool,
+ new_line_pos: &mut Vec<CharIndex>) -> (~str, bool) {
let mut out_str: ~str = "".to_owned();
let out_whitespace = match mode {
CompressNone | DiscardNewline => {
- let mut new_line_index = 0;
+ let mut new_line_index = CharIndex(0);
for ch in text.chars() {
if is_discardable_char(ch, mode) {
// TODO: record skipped char
@@ -36,11 +40,11 @@ pub fn transform_text(text: &str, mode: CompressionMode, incoming_whitespace: bo
// Save new-line's position for line-break
// This value is relative(not absolute)
new_line_pos.push(new_line_index);
- new_line_index = 0;
+ new_line_index = CharIndex(0);
}
if ch != '\n' {
- new_line_index += 1;
+ new_line_index = new_line_index + CharIndex(1);
}
out_str.push_char(ch);
}
diff --git a/src/components/main/constellation.rs b/src/components/main/constellation.rs
index 94c5d0e1039..fcd93ee238c 100644
--- a/src/components/main/constellation.rs
+++ b/src/components/main/constellation.rs
@@ -428,9 +428,9 @@ impl Constellation {
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
- self.opts.clone());
- let url = parse_url("about:failure", None);
- pipeline.load(url);
+ self.opts.clone(),
+ parse_url("about:failure", None));
+ pipeline.load();
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange{
@@ -455,8 +455,9 @@ impl Constellation {
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
- self.opts.clone());
- pipeline.load(url);
+ self.opts.clone(),
+ url);
+ pipeline.load();
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange {
@@ -548,14 +549,7 @@ impl Constellation {
// or a new url entered.
// Start by finding the frame trees matching the pipeline id,
// and add the new pipeline to their sub frames.
- let frame_trees: Vec<Rc<FrameTree>> = {
- let matching_navi_frames = self.navigation_context.find_all(source_pipeline_id);
- let matching_pending_frames = self.pending_frames.iter().filter_map(|frame_change| {
- frame_change.after.find(source_pipeline_id)
- });
- matching_navi_frames.move_iter().chain(matching_pending_frames).collect()
- };
-
+ let frame_trees = self.find_all(source_pipeline_id);
if frame_trees.is_empty() {
fail!("Constellation: source pipeline id of LoadIframeUrlMsg is not in
navigation context, nor is it in a pending frame. This should be
@@ -570,9 +564,7 @@ impl Constellation {
source Id of LoadIframeUrlMsg does have an associated pipeline in
constellation. This should be impossible.").clone();
- let source_url = source_pipeline.url.borrow().clone().expect("Constellation: LoadUrlIframeMsg's
- source's Url is None. There should never be a LoadUrlIframeMsg from a pipeline
- that was never given a url to load.");
+ let source_url = source_pipeline.url.clone();
let same_script = (source_url.host == url.host &&
source_url.port == url.port) && sandbox == IFrameUnsandboxed;
@@ -587,7 +579,8 @@ impl Constellation {
self.image_cache_task.clone(),
self.profiler_chan.clone(),
self.opts.clone(),
- source_pipeline.clone())
+ source_pipeline.clone(),
+ url)
} else {
debug!("Constellation: loading cross-origin iframe at {:?}", url);
// Create a new script task if not same-origin url's
@@ -599,11 +592,12 @@ impl Constellation {
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
- self.opts.clone())
+ self.opts.clone(),
+ url)
};
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
- pipeline.load(url);
+ pipeline.load();
let pipeline_wrapped = Rc::new(pipeline);
let rect = self.pending_sizes.pop(&(source_pipeline_id, subpage_id));
for frame_tree in frame_trees.iter() {
@@ -654,9 +648,10 @@ impl Constellation {
self.resource_task.clone(),
self.profiler_chan.clone(),
self.window_size,
- self.opts.clone());
+ self.opts.clone(),
+ url);
- pipeline.load(url);
+ pipeline.load();
let pipeline_wrapped = Rc::new(pipeline);
self.pending_frames.push(FrameChange{
@@ -706,7 +701,7 @@ impl Constellation {
};
for frame in destination_frame.iter() {
- frame.pipeline.reload();
+ frame.pipeline.load();
}
self.grant_paint_permission(destination_frame, constellation_msg::Navigate);
diff --git a/src/components/main/css/matching.rs b/src/components/main/css/matching.rs
index 082d468db3a..45dd79b9fbc 100644
--- a/src/components/main/css/matching.rs
+++ b/src/components/main/css/matching.rs
@@ -195,7 +195,7 @@ impl StyleSharingCandidate {
match *node.borrow_layout_data_unchecked() {
None => return None,
Some(ref layout_data_ref) => {
- match layout_data_ref.data.style {
+ match layout_data_ref.shared_data.style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -206,7 +206,7 @@ impl StyleSharingCandidate {
match *parent_node.borrow_layout_data_unchecked() {
None => return None,
Some(ref parent_layout_data_ref) => {
- match parent_layout_data_ref.data.style {
+ match parent_layout_data_ref.shared_data.style {
None => return None,
Some(ref data) => (*data).clone(),
}
@@ -394,7 +394,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
match parent_layout_data {
&Some(ref parent_layout_data_ref) => {
// Check parent style.
- let parent_style = parent_layout_data_ref.data.style.as_ref().unwrap();
+ let parent_style = parent_layout_data_ref.shared_data.style.as_ref().unwrap();
if !arc_ptr_eq(parent_style, &candidate.parent_style) {
return None
}
@@ -458,7 +458,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
Some(shared_style) => {
// Yay, cache hit. Share the style.
let mut layout_data_ref = self.mutate_layout_data();
- layout_data_ref.get_mut_ref().data.style = Some(shared_style);
+ layout_data_ref.get_mut_ref().shared_data.style = Some(shared_style);
return StyleWasShared(i)
}
None => {}
@@ -543,7 +543,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
match *parent_layout_data {
None => fail!("no parent data?!"),
Some(ref parent_layout_data) => {
- match parent_layout_data.data.style {
+ match parent_layout_data.shared_data.style {
None => fail!("parent hasn't been styled yet?!"),
Some(ref style) => Some(style),
}
@@ -558,7 +558,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
&Some(ref mut layout_data) => {
self.cascade_node_pseudo_element(parent_style,
applicable_declarations.normal.as_slice(),
- &mut layout_data.data.style,
+ &mut layout_data.shared_data.style,
initial_values,
applicable_declarations_cache,
applicable_declarations.normal_shareable);
diff --git a/src/components/main/css/node_util.rs b/src/components/main/css/node_util.rs
index 5c88632eb55..22cc7bc68a5 100644
--- a/src/components/main/css/node_util.rs
+++ b/src/components/main/css/node_util.rs
@@ -45,7 +45,7 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
Normal => {
cast::transmute_region(layout_data_ref.as_ref()
.unwrap()
- .data
+ .shared_data
.style
.as_ref()
.unwrap())
@@ -57,7 +57,7 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
/// Does this node have a computed style yet?
fn have_css_select_results(&self) -> bool {
let layout_data_ref = self.borrow_layout_data();
- layout_data_ref.get_ref().data.style.is_some()
+ layout_data_ref.get_ref().shared_data.style.is_some()
}
/// Get the description of how to account for recent style changes.
diff --git a/src/components/main/layout/box_.rs b/src/components/main/layout/box_.rs
index b96a28879cd..5b867e06bfc 100644
--- a/src/components/main/layout/box_.rs
+++ b/src/components/main/layout/box_.rs
@@ -28,6 +28,7 @@ use gfx::display_list::{LineDisplayItemClass, OpaqueNode, PseudoDisplayItemClass
use gfx::display_list::{SolidColorDisplayItem, SolidColorDisplayItemClass, StackingLevel};
use gfx::display_list::{TextDecorations, TextDisplayItem, TextDisplayItemClass};
use gfx::font::FontStyle;
+use gfx::text::glyph::CharIndex;
use gfx::text::text_run::TextRun;
use servo_msg::constellation_msg::{ConstellationChan, FrameRectMsg, PipelineId, SubpageId};
use servo_net::image::holder::{ImageHolder, LocalImageCacheHandle};
@@ -95,7 +96,7 @@ pub struct Box {
/// New-line chracter(\n)'s positions(relative, not absolute)
///
/// FIXME(#2260, pcwalton): This is very inefficient; remove.
- pub new_line_pos: Vec<int>,
+ pub new_line_pos: Vec<CharIndex>,
}
/// Info specific to the kind of box. Keep this enum small.
@@ -226,12 +227,12 @@ pub struct ScannedTextBoxInfo {
pub run: Arc<~TextRun>,
/// The range within the above text run that this represents.
- pub range: Range<int>,
+ pub range: Range<CharIndex>,
}
impl ScannedTextBoxInfo {
/// Creates the information specific to a scanned text box from a range and a text run.
- pub fn new(run: Arc<~TextRun>, range: Range<int>) -> ScannedTextBoxInfo {
+ pub fn new(run: Arc<~TextRun>, range: Range<CharIndex>) -> ScannedTextBoxInfo {
ScannedTextBoxInfo {
run: run,
range: range,
@@ -1108,7 +1109,8 @@ impl Box {
let cur_new_line_pos = new_line_pos.shift().unwrap();
let left_range = Range::new(text_box_info.range.begin(), cur_new_line_pos);
- let right_range = Range::new(text_box_info.range.begin() + cur_new_line_pos + 1, text_box_info.range.length() - (cur_new_line_pos + 1));
+ let right_range = Range::new(text_box_info.range.begin() + cur_new_line_pos + CharIndex(1),
+ text_box_info.range.length() - (cur_new_line_pos + CharIndex(1)));
// Left box is for left text of first founded new-line character.
let left_box = {
@@ -1120,7 +1122,7 @@ impl Box {
};
// Right box is for right text of first founded new-line character.
- let right_box = if right_range.length() > 0 {
+ let right_box = if right_range.length() > CharIndex(0) {
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), right_range);
let new_metrics = new_text_box_info.run.metrics_for_range(&right_range);
let mut new_box = self.transform(new_metrics.bounding_box.size, ScannedTextBox(new_text_box_info));
@@ -1145,8 +1147,8 @@ impl Box {
ScannedTextBox(ref text_box_info) => {
let mut pieces_processed_count: uint = 0;
let mut remaining_width: Au = max_width;
- let mut left_range = Range::new(text_box_info.range.begin(), 0);
- let mut right_range: Option<Range<int>> = None;
+ let mut left_range = Range::new(text_box_info.range.begin(), CharIndex(0));
+ let mut right_range: Option<Range<CharIndex>> = None;
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
avail_width={})",
@@ -1171,11 +1173,11 @@ impl Box {
if starts_line && pieces_processed_count == 0 && glyphs.is_whitespace() {
debug!("split_to_width: case=skipping leading trimmable whitespace");
- left_range.shift_by(slice_range.length() as int);
+ left_range.shift_by(slice_range.length());
} else {
debug!("split_to_width: case=enlarging span");
remaining_width = remaining_width - advance;
- left_range.extend_by(slice_range.length() as int);
+ left_range.extend_by(slice_range.length());
}
} else {
// The advance is more than the remaining width.
@@ -1212,7 +1214,7 @@ impl Box {
}
}
- let left_box = if left_range.length() > 0 {
+ let left_box = if left_range.length() > CharIndex(0) {
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(), left_range);
let mut new_metrics = new_text_box_info.run.metrics_for_range(&left_range);
new_metrics.bounding_box.size.height = self.border_box.size.height;
@@ -1222,7 +1224,7 @@ impl Box {
None
};
- let right_box = right_range.map_or(None, |range: Range<int>| {
+ let right_box = right_range.map_or(None, |range: Range<CharIndex>| {
let new_text_box_info = ScannedTextBoxInfo::new(text_box_info.run.clone(),
range);
let mut new_metrics = new_text_box_info.run.metrics_for_range(&range);
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index 10d68dd34d1..82aedb08417 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -30,7 +30,7 @@ use layout::floats::FloatKind;
use layout::flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow::{Descendants, AbsDescendants};
use layout::flow_list::{Rawlink};
-use layout::inline::{InlineBoxes, InlineFlow};
+use layout::inline::{FragmentIndex, InlineBoxes, InlineFlow};
use layout::table_wrapper::TableWrapperFlow;
use layout::table::TableFlow;
use layout::table_caption::TableCaptionFlow;
@@ -189,7 +189,7 @@ impl InlineBoxAccumulator {
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineBoxAccumulator {
let mut boxes = InlineBoxes::new();
- boxes.map.push(node.style().clone(), Range::new(0, 0));
+ boxes.map.push(node.style().clone(), Range::empty());
InlineBoxAccumulator {
boxes: boxes,
has_enclosing_range: true,
@@ -203,8 +203,8 @@ impl InlineBoxAccumulator {
} = self;
if has_enclosing_range {
- let len = boxes.len() as int;
- boxes.map.get_mut(0).range.extend_to(len);
+ let len = FragmentIndex(boxes.len() as int);
+ boxes.map.get_mut(FragmentIndex(0)).range.extend_to(len);
}
boxes
}
diff --git a/src/components/main/layout/extra.rs b/src/components/main/layout/extra.rs
index 387bbcd91e9..1692e36c420 100644
--- a/src/components/main/layout/extra.rs
+++ b/src/components/main/layout/extra.rs
@@ -6,6 +6,7 @@
use layout::util::{PrivateLayoutData, LayoutDataAccess, LayoutDataWrapper};
use layout::wrapper::LayoutNode;
+use script::dom::node::SharedLayoutData;
use script::layout_interface::LayoutChan;
/// Functionality useful for querying the layout-specific data on DOM nodes.
@@ -24,6 +25,7 @@ impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
None => {
*layout_data_ref = Some(LayoutDataWrapper {
chan: Some(chan),
+ shared_data: SharedLayoutData { style: None },
data: ~PrivateLayoutData::new(),
});
}
diff --git a/src/components/main/layout/inline.rs b/src/components/main/layout/inline.rs
index 060fd7f6344..e9ee308a3e4 100644
--- a/src/components/main/layout/inline.rs
+++ b/src/components/main/layout/inline.rs
@@ -20,7 +20,7 @@ use gfx::font::FontMetrics;
use gfx::font_context::FontContext;
use servo_util::geometry::Au;
use servo_util::geometry;
-use servo_util::range::Range;
+use servo_util::range::{Range, RangeIndex};
use std::iter::Enumerate;
use std::fmt;
use std::mem;
@@ -56,11 +56,15 @@ use sync::Arc;
/// left corner of the green zone is the same as that of the line, but
/// the green zone can be taller and wider than the line itself.
pub struct LineBox {
- pub range: Range<int>,
+ pub range: Range<BoxIndex>,
pub bounds: Rect<Au>,
pub green_zone: Size2D<Au>
}
+range_index! {
+ struct BoxIndex(int)
+}
+
struct LineboxScanner {
pub floats: Floats,
pub new_boxes: Vec<Box>,
@@ -99,7 +103,7 @@ impl LineboxScanner {
}
fn reset_linebox(&mut self) {
- self.pending_line.range.reset(0,0);
+ self.pending_line.range.reset(BoxIndex(0), BoxIndex(0));
self.pending_line.bounds = Rect(Point2D(Au::new(0), self.cur_y), Size2D(Au::new(0), Au::new(0)));
self.pending_line.green_zone = Size2D(Au::new(0), Au::new(0))
}
@@ -146,7 +150,7 @@ impl LineboxScanner {
}
}
- if self.pending_line.range.length() > 0 {
+ if self.pending_line.range.length() > BoxIndex(0) {
debug!("LineboxScanner: Partially full linebox {:u} left at end of scanning.",
self.lines.len());
self.flush_current_line();
@@ -193,7 +197,7 @@ impl LineboxScanner {
let first_box_size = first_box.border_box.size;
let splittable = first_box.can_split();
debug!("LineboxScanner: box size: {}, splittable: {}", first_box_size, splittable);
- let line_is_empty: bool = self.pending_line.range.length() == 0;
+ let line_is_empty: bool = self.pending_line.range.length() == BoxIndex(0);
// Initally, pretend a splittable box has 0 width.
// We will move it later if it has nonzero width
@@ -349,7 +353,7 @@ impl LineboxScanner {
/// Tries to append the given box to the line, splitting it if necessary. Returns false only if
/// we should break the line.
fn try_append_to_line(&mut self, in_box: Box, flow: &mut InlineFlow) -> bool {
- let line_is_empty = self.pending_line.range.length() == 0;
+ let line_is_empty = self.pending_line.range.length() == BoxIndex(0);
if line_is_empty {
let (line_bounds, _) = self.initial_line_placement(&in_box, self.cur_y, flow);
self.pending_line.bounds.origin = line_bounds.origin;
@@ -444,11 +448,11 @@ impl LineboxScanner {
fn push_box_to_line(&mut self, box_: Box) {
debug!("LineboxScanner: Pushing box {} to line {:u}", box_.debug_id(), self.lines.len());
- if self.pending_line.range.length() == 0 {
+ if self.pending_line.range.length() == BoxIndex(0) {
assert!(self.new_boxes.len() <= (u16::MAX as uint));
- self.pending_line.range.reset(self.new_boxes.len() as int, 0);
+ self.pending_line.range.reset(BoxIndex(self.new_boxes.len() as int), BoxIndex(0));
}
- self.pending_line.range.extend_by(1);
+ self.pending_line.range.extend_by(BoxIndex(1));
self.pending_line.bounds.size.width = self.pending_line.bounds.size.width +
box_.border_box.size.width;
self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height,
@@ -468,7 +472,10 @@ impl<'a> Iterator<(&'a Box, InlineFragmentContext<'a>)> for BoxIterator<'a> {
fn next(&mut self) -> Option<(&'a Box, InlineFragmentContext<'a>)> {
match self.iter.next() {
None => None,
- Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i as int))),
+ Some((i, fragment)) => Some((
+ fragment,
+ InlineFragmentContext::new(self.map, FragmentIndex(i as int)),
+ )),
}
}
}
@@ -484,7 +491,10 @@ impl<'a> Iterator<(&'a mut Box, InlineFragmentContext<'a>)> for MutBoxIterator<'
fn next(&mut self) -> Option<(&'a mut Box, InlineFragmentContext<'a>)> {
match self.iter.next() {
None => None,
- Some((i, fragment)) => Some((fragment, InlineFragmentContext::new(self.map, i as int))),
+ Some((i, fragment)) => Some((
+ fragment,
+ InlineFragmentContext::new(self.map, FragmentIndex(i as int)),
+ )),
}
}
}
@@ -518,7 +528,7 @@ impl InlineBoxes {
/// Pushes a new inline box.
pub fn push(&mut self, fragment: Box, style: Arc<ComputedValues>) {
- self.map.push(style, Range::new(self.boxes.len() as int, 1));
+ self.map.push(style, Range::new(FragmentIndex(self.boxes.len() as int), FragmentIndex(1)));
self.boxes.push(fragment)
}
@@ -528,7 +538,7 @@ impl InlineBoxes {
boxes: other_boxes,
map: other_map
} = other;
- let adjustment = self.boxes.len();
+ let adjustment = FragmentIndex(self.boxes.len() as int);
self.map.push_all(other_map, adjustment);
self.boxes.push_all_move(other_boxes);
}
@@ -713,8 +723,8 @@ impl InlineFlow {
text_align::right => slack_width,
};
- for i in line.range.eachi() {
- let box_ = boxes.get_mut(i as uint);
+ for i in line.range.each_index() {
+ let box_ = boxes.get_mut(i.to_uint());
let size = box_.border_box.size;
box_.border_box = Rect(Point2D(offset_x, box_.border_box.origin.y), size);
offset_x = offset_x + size.width;
@@ -844,8 +854,8 @@ impl Flow for InlineFlow {
let (mut largest_height_for_top_fragments, mut largest_height_for_bottom_fragments) =
(Au(0), Au(0));
- for box_i in line.range.eachi() {
- let fragment = self.boxes.boxes.get_mut(box_i as uint);
+ for box_i in line.range.each_index() {
+ let fragment = self.boxes.boxes.get_mut(box_i.to_uint());
let InlineMetrics {
height_above_baseline: mut height_above_baseline,
@@ -920,8 +930,8 @@ impl Flow for InlineFlow {
// Compute the final positions in the block direction of each fragment. Recall that
// `fragment.border_box.origin.y` was set to the distance from the baseline above.
- for box_i in line.range.eachi() {
- let fragment = self.boxes.get_mut(box_i as uint);
+ for box_i in line.range.each_index() {
+ let fragment = self.boxes.get_mut(box_i.to_uint());
match fragment.vertical_align() {
vertical_align::top => {
fragment.border_box.origin.y = fragment.border_box.origin.y +
@@ -971,18 +981,23 @@ impl fmt::Show for InlineFlow {
}
}
+range_index! {
+ #[doc = "The index of a DOM element into the flat list of fragments."]
+ struct FragmentIndex(int)
+}
+
/// Information that inline flows keep about a single nested element. This is used to recover the
/// DOM structure from the flat box list when it's needed.
pub struct FragmentRange {
/// The style of the DOM node that this range refers to.
pub style: Arc<ComputedValues>,
/// The range, in indices into the fragment list.
- pub range: Range<int>,
+ pub range: Range<FragmentIndex>,
}
impl FragmentRange {
/// Creates a new fragment range from the given values.
- fn new(style: Arc<ComputedValues>, range: Range<int>) -> FragmentRange {
+ fn new(style: Arc<ComputedValues>, range: Range<FragmentIndex>) -> FragmentRange {
FragmentRange {
style: style,
range: range,
@@ -1003,14 +1018,14 @@ impl FragmentRange {
struct FragmentFixupWorkItem {
style: Arc<ComputedValues>,
- new_start_index: int,
- old_end_index: int,
+ new_start_index: FragmentIndex,
+ old_end_index: FragmentIndex,
}
/// The type of an iterator over fragment ranges in the fragment map.
pub struct RangeIterator<'a> {
iter: Items<'a,FragmentRange>,
- index: int,
+ index: FragmentIndex,
seen_first: bool,
}
@@ -1053,13 +1068,13 @@ impl FragmentMap {
}
/// Adds the given node to the fragment map.
- pub fn push(&mut self, style: Arc<ComputedValues>, range: Range<int>) {
+ pub fn push(&mut self, style: Arc<ComputedValues>, range: Range<FragmentIndex>) {
self.list.push(FragmentRange::new(style, range))
}
/// Pushes the ranges in another fragment map onto the end of this one, adjusting indices as
/// necessary.
- fn push_all(&mut self, other: FragmentMap, adjustment: uint) {
+ fn push_all(&mut self, other: FragmentMap, adjustment: FragmentIndex) {
let FragmentMap {
list: other_list
} = other;
@@ -1070,19 +1085,19 @@ impl FragmentMap {
range: mut other_range
} = other_range;
- other_range.shift_by(adjustment as int);
+ other_range.shift_by(adjustment);
self.push(other_style, other_range)
}
}
/// Returns the range with the given index.
- pub fn get_mut<'a>(&'a mut self, index: int) -> &'a mut FragmentRange {
- &mut self.list.as_mut_slice()[index as uint]
+ pub fn get_mut<'a>(&'a mut self, index: FragmentIndex) -> &'a mut FragmentRange {
+ &mut self.list.as_mut_slice()[index.to_uint()]
}
/// Iterates over all ranges that contain the box with the given index, outermost first.
#[inline(always)]
- fn ranges_for_index<'a>(&'a self, index: int) -> RangeIterator<'a> {
+ fn ranges_for_index<'a>(&'a self, index: FragmentIndex) -> RangeIterator<'a> {
RangeIterator {
iter: self.list.as_slice().iter(),
index: index,
@@ -1108,12 +1123,13 @@ impl FragmentMap {
// FIXME(#2270, pcwalton): I don't think this will work if multiple old fragments
// correspond to the same node.
- for (old_fragment_index, old_fragment) in old_fragments.iter().enumerate() {
+ for (i, old_fragment) in old_fragments.iter().enumerate() {
+ let old_fragment_index = FragmentIndex(i as int);
// Find the start of the corresponding new fragment.
let new_fragment_start = match new_fragments_iter.peek() {
Some(&(index, new_fragment)) if new_fragment.node == old_fragment.node => {
// We found the start of the corresponding new fragment.
- index as int
+ FragmentIndex(index as int)
}
Some(_) | None => {
// The old fragment got deleted entirely.
@@ -1136,7 +1152,7 @@ impl FragmentMap {
match old_list_iter.peek() {
None => break,
Some(fragment_range) => {
- if fragment_range.range.begin() > old_fragment_index as int {
+ if fragment_range.range.begin() > old_fragment_index {
// We haven't gotten to the appropriate old fragment yet, so stop.
break
}
@@ -1163,7 +1179,7 @@ impl FragmentMap {
match worklist.as_slice().last() {
None => break,
Some(last_work_item) => {
- if last_work_item.old_end_index > old_fragment_index as int + 1 {
+ if last_work_item.old_end_index > old_fragment_index + FragmentIndex(1) {
// Haven't gotten to it yet.
break
}
@@ -1173,10 +1189,12 @@ impl FragmentMap {
let new_last_index = match new_fragments_iter.peek() {
None => {
// At the end.
- new_fragments.len()
+ FragmentIndex(new_fragments.len() as int)
}
- Some(&(index, _)) => index,
- } as int;
+ Some(&(index, _)) => {
+ FragmentIndex(index as int)
+ },
+ };
let FragmentFixupWorkItem {
style,
@@ -1194,11 +1212,11 @@ impl FragmentMap {
/// conveniently to various fragment functions.
pub struct InlineFragmentContext<'a> {
map: &'a FragmentMap,
- index: int,
+ index: FragmentIndex,
}
impl<'a> InlineFragmentContext<'a> {
- pub fn new<'a>(map: &'a FragmentMap, index: int) -> InlineFragmentContext<'a> {
+ pub fn new<'a>(map: &'a FragmentMap, index: FragmentIndex) -> InlineFragmentContext<'a> {
InlineFragmentContext {
map: map,
index: index,
diff --git a/src/components/main/layout/text.rs b/src/components/main/layout/text.rs
index f254d07d5a4..7f38a617efd 100644
--- a/src/components/main/layout/text.rs
+++ b/src/components/main/layout/text.rs
@@ -10,6 +10,7 @@ use layout::inline::InlineBoxes;
use gfx::font::{FontMetrics, FontStyle};
use gfx::font_context::FontContext;
+use gfx::text::glyph::CharIndex;
use gfx::text::text_run::TextRun;
use gfx::text::util::{CompressWhitespaceNewline, transform_text, CompressNone};
use servo_util::geometry::Au;
@@ -20,7 +21,7 @@ use style::computed_values::{font_family, line_height, white_space};
use sync::Arc;
struct NewLinePositions {
- new_line_pos: Vec<int>,
+ new_line_pos: Vec<CharIndex>,
}
// A helper function.
@@ -31,7 +32,7 @@ fn can_coalesce_text_nodes(boxes: &[Box], left_i: uint, right_i: uint) -> bool {
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextBox`es.
pub struct TextRunScanner {
- pub clump: Range<int>,
+ pub clump: Range<CharIndex>,
}
impl TextRunScanner {
@@ -63,11 +64,11 @@ impl TextRunScanner {
last_whitespace);
}
- self.clump.extend_by(1);
+ self.clump.extend_by(CharIndex(1));
}
// Handle remaining clumps.
- if self.clump.length() > 0 {
+ if self.clump.length() > CharIndex(0) {
drop(self.flush_clump_to_list(font_context,
old_boxes.as_slice(),
&mut new_boxes,
@@ -99,12 +100,12 @@ impl TextRunScanner {
out_boxes: &mut Vec<Box>,
last_whitespace: bool)
-> bool {
- assert!(self.clump.length() > 0);
+ assert!(self.clump.length() > CharIndex(0));
debug!("TextRunScanner: flushing boxes in range={}", self.clump);
- let is_singleton = self.clump.length() == 1;
+ let is_singleton = self.clump.length() == CharIndex(1);
- let is_text_clump = match in_boxes[self.clump.begin() as uint].specific {
+ let is_text_clump = match in_boxes[self.clump.begin().to_uint()].specific {
UnscannedTextBox(_) => true,
_ => false,
};
@@ -117,11 +118,11 @@ impl TextRunScanner {
(true, false) => {
// FIXME(pcwalton): Stop cloning boxes, as above.
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
- let new_box = in_boxes[self.clump.begin() as uint].clone();
+ let new_box = in_boxes[self.clump.begin().to_uint()].clone();
out_boxes.push(new_box)
},
(true, true) => {
- let old_box = &in_boxes[self.clump.begin() as uint];
+ let old_box = &in_boxes[self.clump.begin().to_uint()];
let text = match old_box.specific {
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
_ => fail!("Expected an unscanned text box!"),
@@ -156,11 +157,11 @@ impl TextRunScanner {
debug!("TextRunScanner: pushing single text box in range: {} ({})",
self.clump,
*text);
- let range = Range::new(0, run.char_len());
+ let range = Range::new(CharIndex(0), run.char_len());
let new_metrics = run.metrics_for_range(&range);
let new_text_box_info = ScannedTextBoxInfo::new(Arc::new(run), range);
let mut new_box = old_box.transform(new_metrics.bounding_box.size,
- ScannedTextBox(new_text_box_info));
+ ScannedTextBox(new_text_box_info));
new_box.new_line_pos = new_line_pos;
out_boxes.push(new_box)
}
@@ -169,7 +170,7 @@ impl TextRunScanner {
// TODO(#177): Text run creation must account for the renderability of text by
// font group fonts. This is probably achieved by creating the font group above
// and then letting `FontGroup` decide which `Font` to stick into the text run.
- let in_box = &in_boxes[self.clump.begin() as uint];
+ let in_box = &in_boxes[self.clump.begin().to_uint()];
let font_style = in_box.font_style();
let fontgroup = font_context.get_resolved_font_for_style(&font_style);
let decoration = in_box.text_decoration();
@@ -184,12 +185,12 @@ impl TextRunScanner {
// First, transform/compress text of all the nodes.
let mut last_whitespace_in_clump = new_whitespace;
- let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length() as uint, |i| {
+ let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length().to_uint(), |i| {
// TODO(#113): We should be passing the compression context between calls to
// `transform_text`, so that boxes starting and/or ending with whitespace can
// be compressed correctly with respect to the text run.
- let idx = i as int + self.clump.begin();
- let in_box = match in_boxes[idx as uint].specific {
+ let idx = CharIndex(i as int) + self.clump.begin();
+ let in_box = match in_boxes[idx.to_uint()].specific {
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
_ => fail!("Expected an unscanned text box!"),
};
@@ -210,20 +211,20 @@ impl TextRunScanner {
// Next, concatenate all of the transformed strings together, saving the new
// character indices.
let mut run_str: ~str = "".to_owned();
- let mut new_ranges: Vec<Range<int>> = vec![];
- let mut char_total = 0;
+ let mut new_ranges: Vec<Range<CharIndex>> = vec![];
+ let mut char_total = CharIndex(0);
for i in range(0, transformed_strs.len() as int) {
- let added_chars = transformed_strs.get(i as uint).char_len() as int;
+ let added_chars = CharIndex(transformed_strs.get(i as uint).char_len() as int);
new_ranges.push(Range::new(char_total, added_chars));
run_str.push_str(*transformed_strs.get(i as uint));
- char_total += added_chars;
+ char_total = char_total + added_chars;
}
// Now create the run.
// TextRuns contain a cycle which is usually resolved by the teardown
// sequence. If no clump takes ownership, however, it will leak.
let clump = self.clump;
- let run = if clump.length() != 0 && run_str.len() > 0 {
+ let run = if clump.length() != CharIndex(0) && run_str.len() > 0 {
Some(Arc::new(~TextRun::new(&mut *fontgroup.borrow().fonts.get(0).borrow_mut(),
run_str.clone(), decoration)))
} else {
@@ -232,27 +233,27 @@ impl TextRunScanner {
// Make new boxes with the run and adjusted text indices.
debug!("TextRunScanner: pushing box(es) in range: {}", self.clump);
- for i in clump.eachi() {
+ for i in clump.each_index() {
let logical_offset = i - self.clump.begin();
- let range = new_ranges.get(logical_offset as uint);
- if range.length() == 0 {
+ let range = new_ranges.get(logical_offset.to_uint());
+ if range.length() == CharIndex(0) {
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
- compression; {}", in_boxes[i as uint]);
+ compression; {}", in_boxes[i.to_uint()]);
continue
}
let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), *range);
let new_metrics = new_text_box_info.run.metrics_for_range(range);
- let mut new_box = in_boxes[i as uint].transform(new_metrics.bounding_box.size,
+ let mut new_box = in_boxes[i.to_uint()].transform(new_metrics.bounding_box.size,
ScannedTextBox(new_text_box_info));
- new_box.new_line_pos = new_line_positions.get(logical_offset as uint).new_line_pos.clone();
+ new_box.new_line_pos = new_line_positions.get(logical_offset.to_uint()).new_line_pos.clone();
out_boxes.push(new_box)
}
}
} // End of match.
let end = self.clump.end(); // FIXME: borrow checker workaround
- self.clump.reset(end, 0);
+ self.clump.reset(end, CharIndex(0));
new_whitespace
} // End of `flush_clump_to_list`.
diff --git a/src/components/main/layout/util.rs b/src/components/main/layout/util.rs
index 48c782d7f3a..85938d0b2b1 100644
--- a/src/components/main/layout/util.rs
+++ b/src/components/main/layout/util.rs
@@ -11,7 +11,7 @@ use gfx;
use libc::uintptr_t;
use script::dom::bindings::js::JS;
use script::dom::bindings::utils::Reflectable;
-use script::dom::node::Node;
+use script::dom::node::{Node, SharedLayoutData};
use script::layout_interface::{LayoutChan, UntrustedNodeAddress, TrustedNodeAddress};
use std::cast;
use std::cell::{Ref, RefMut};
@@ -21,9 +21,6 @@ use sync::Arc;
/// Data that layout associates with a node.
pub struct PrivateLayoutData {
- /// The results of CSS styling for this node.
- pub style: Option<Arc<ComputedValues>>,
-
/// The results of CSS styling for this node's `before` pseudo-element, if any.
pub before_style: Option<Arc<ComputedValues>>,
@@ -50,7 +47,6 @@ impl PrivateLayoutData {
pub fn new() -> PrivateLayoutData {
PrivateLayoutData {
before_style: None,
- style: None,
after_style: None,
restyle_damage: None,
flow_construction_result: NoConstructionResult,
@@ -63,6 +59,7 @@ impl PrivateLayoutData {
pub struct LayoutDataWrapper {
pub chan: Option<LayoutChan>,
+ pub shared_data: SharedLayoutData,
pub data: ~PrivateLayoutData,
}
diff --git a/src/components/main/layout/wrapper.rs b/src/components/main/layout/wrapper.rs
index 0b2bb795545..9f0d1e7bcae 100644
--- a/src/components/main/layout/wrapper.rs
+++ b/src/components/main/layout/wrapper.rs
@@ -561,7 +561,7 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
after_style.Box.get().display
}
Normal => {
- let after_style = node_layout_data_wrapper.data.style.get_ref();
+ let after_style = node_layout_data_wrapper.shared_data.style.get_ref();
after_style.Box.get().display
}
};
diff --git a/src/components/main/pipeline.rs b/src/components/main/pipeline.rs
index afe13126a38..2b17085e6a2 100644
--- a/src/components/main/pipeline.rs
+++ b/src/components/main/pipeline.rs
@@ -17,7 +17,6 @@ use servo_net::image_cache_task::ImageCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_util::opts::Opts;
use servo_util::time::ProfilerChan;
-use std::cell::RefCell;
use std::rc::Rc;
use url::Url;
@@ -31,7 +30,7 @@ pub struct Pipeline {
pub layout_shutdown_port: Receiver<()>,
pub render_shutdown_port: Receiver<()>,
/// The most recently loaded url
- pub url: RefCell<Option<Url>>,
+ pub url: Url,
}
/// The subset of the pipeline that is needed for layer composition.
@@ -52,7 +51,8 @@ impl Pipeline {
image_cache_task: ImageCacheTask,
profiler_chan: ProfilerChan,
opts: Opts,
- script_pipeline: Rc<Pipeline>)
+ script_pipeline: Rc<Pipeline>,
+ url: Url)
-> Pipeline {
let (layout_port, layout_chan) = LayoutChan::new();
let (render_port, render_chan) = RenderChan::new();
@@ -100,7 +100,8 @@ impl Pipeline {
layout_chan,
render_chan,
layout_shutdown_port,
- render_shutdown_port)
+ render_shutdown_port,
+ url)
}
pub fn create(id: PipelineId,
@@ -111,7 +112,8 @@ impl Pipeline {
resource_task: ResourceTask,
profiler_chan: ProfilerChan,
window_size: Size2D<uint>,
- opts: Opts)
+ opts: Opts,
+ url: Url)
-> Pipeline {
let (script_port, script_chan) = ScriptChan::new();
let (layout_port, layout_chan) = LayoutChan::new();
@@ -124,7 +126,8 @@ impl Pipeline {
layout_chan.clone(),
render_chan.clone(),
layout_shutdown_port,
- render_shutdown_port);
+ render_shutdown_port,
+ url);
let failure = Failure {
pipeline_id: id,
@@ -172,7 +175,8 @@ impl Pipeline {
layout_chan: LayoutChan,
render_chan: RenderChan,
layout_shutdown_port: Receiver<()>,
- render_shutdown_port: Receiver<()>)
+ render_shutdown_port: Receiver<()>,
+ url: Url)
-> Pipeline {
Pipeline {
id: id,
@@ -182,14 +186,13 @@ impl Pipeline {
render_chan: render_chan,
layout_shutdown_port: layout_shutdown_port,
render_shutdown_port: render_shutdown_port,
- url: RefCell::new(None),
+ url: url,
}
}
- pub fn load(&self, url: Url) {
- *self.url.borrow_mut() = Some(url.clone());
+ pub fn load(&self) {
let ScriptChan(ref chan) = self.script_chan;
- chan.send(LoadMsg(self.id, url));
+ chan.send(LoadMsg(self.id, self.url.clone()));
}
pub fn grant_paint_permission(&self) {
@@ -201,13 +204,6 @@ impl Pipeline {
self.render_chan.chan.try_send(PaintPermissionRevoked);
}
- pub fn reload(&self) {
- let url = self.url.borrow().clone();
- url.map(|url| {
- self.load(url);
- });
- }
-
pub fn exit(&self) {
debug!("pipeline {:?} exiting", self.id);
diff --git a/src/components/main/servo.rs b/src/components/main/servo.rs
index abdc740f0cf..cc000338ae0 100755..100644
--- a/src/components/main/servo.rs
+++ b/src/components/main/servo.rs
@@ -8,7 +8,6 @@
#![feature(globs, macro_rules, phase, thread_local)]
-#![feature(phase)]
#[phase(syntax, link)]
extern crate log;
@@ -30,6 +29,7 @@ extern crate script;
extern crate servo_macros = "macros";
extern crate servo_net = "net";
extern crate servo_msg = "msg";
+#[phase(syntax, link)]
extern crate servo_util = "util";
extern crate style;
extern crate sharegl;
diff --git a/src/components/net/http_loader.rs b/src/components/net/http_loader.rs
index dbb5d4ea674..df768a098be 100644
--- a/src/components/net/http_loader.rs
+++ b/src/components/net/http_loader.rs
@@ -9,7 +9,6 @@ use http::client::{RequestWriter, NetworkStream};
use http::method::Get;
use http::headers::HeaderEnum;
use std::io::Reader;
-use std::slice;
use servo_util::task::spawn_named;
use url::Url;
@@ -96,14 +95,13 @@ fn load(mut url: Url, start_chan: Sender<LoadResponse>) {
let progress_chan = start_sending(start_chan, metadata);
loop {
- let mut buf = slice::with_capacity(1024);
+ let mut buf = Vec::with_capacity(1024);
unsafe { buf.set_len(1024); }
- match response.read(buf) {
+ match response.read(buf.as_mut_slice()) {
Ok(len) => {
unsafe { buf.set_len(len); }
- let buf: ~[u8] = buf;
- progress_chan.send(Payload(buf.move_iter().collect()));
+ progress_chan.send(Payload(buf));
}
Err(_) => {
progress_chan.send(Done(Ok(())));
diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs
index b21bf35b325..5b8bd777468 100644
--- a/src/components/script/dom/element.rs
+++ b/src/components/script/dom/element.rs
@@ -206,7 +206,9 @@ impl<'a> ElementHelpers for JSRef<'a, Element> {
pub trait AttributeHandlers {
fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Temporary<Attr>>;
- fn set_attr(&mut self, name: DOMString, value: DOMString) -> ErrorResult;
+ fn set_attribute_from_parser(&mut self, local_name: DOMString,
+ value: DOMString, namespace: Namespace,
+ prefix: Option<DOMString>);
fn set_attribute(&mut self, namespace: Namespace, name: DOMString,
value: DOMString) -> ErrorResult;
fn do_set_attribute(&mut self, local_name: DOMString, value: DOMString,
@@ -238,8 +240,14 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
}
- fn set_attr(&mut self, name: DOMString, value: DOMString) -> ErrorResult {
- self.set_attribute(namespace::Null, name, value)
+ fn set_attribute_from_parser(&mut self, local_name: DOMString,
+ value: DOMString, namespace: Namespace,
+ prefix: Option<DOMString>) {
+ let name = match prefix {
+ None => local_name.clone(),
+ Some(ref prefix) => format!("{:s}:{:s}", *prefix, local_name),
+ };
+ self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false)
}
fn set_attribute(&mut self, namespace: Namespace, name: DOMString,
diff --git a/src/components/script/dom/htmliframeelement.rs b/src/components/script/dom/htmliframeelement.rs
index 1c44fa33e4d..f92fddabdaa 100644
--- a/src/components/script/dom/htmliframeelement.rs
+++ b/src/components/script/dom/htmliframeelement.rs
@@ -5,19 +5,22 @@
use dom::bindings::codegen::BindingDeclarations::HTMLIFrameElementBinding;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLIFrameElementDerived, HTMLElementCast};
use dom::bindings::error::ErrorResult;
-use dom::bindings::js::{JSRef, Temporary};
-use dom::bindings::trace::Untraceable;
+use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::document::Document;
use dom::element::{HTMLIFrameElementTypeId, Element};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
-use dom::node::{Node, ElementNodeTypeId};
+use dom::node::{Node, ElementNodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::Window;
+use servo_msg::constellation_msg::{PipelineId, SubpageId};
+use servo_msg::constellation_msg::{IFrameSandboxed, IFrameUnsandboxed};
+use servo_msg::constellation_msg::{ConstellationChan, LoadIframeUrlMsg};
+use servo_util::namespace::Null;
use servo_util::str::DOMString;
+use servo_util::url::try_parse_url;
-use servo_msg::constellation_msg::{PipelineId, SubpageId};
use std::ascii::StrAsciiExt;
use url::Url;
@@ -34,7 +37,6 @@ enum SandboxAllowance {
#[deriving(Encodable)]
pub struct HTMLIFrameElement {
pub htmlelement: HTMLElement,
- frame: Untraceable<Option<Url>>,
pub size: Option<IFrameSize>,
pub sandbox: Option<u8>
}
@@ -53,7 +55,7 @@ pub struct IFrameSize {
pub trait HTMLIFrameElementHelpers {
fn is_sandboxed(&self) -> bool;
- fn set_frame(&mut self, frame: Url);
+ fn get_url(&self) -> Option<Url>;
}
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
@@ -61,8 +63,13 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
self.sandbox.is_some()
}
- fn set_frame(&mut self, frame: Url) {
- *self.frame = Some(frame);
+ fn get_url(&self) -> Option<Url> {
+ let element: &JSRef<Element> = ElementCast::from_ref(self);
+ element.get_attribute(Null, "src").root().and_then(|src| {
+ let window = window_from_node(self).root();
+ try_parse_url(src.deref().value_ref(),
+ Some(window.deref().page().get_url())).ok()
+ })
}
}
@@ -70,7 +77,6 @@ impl HTMLIFrameElement {
pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLIFrameElement {
HTMLIFrameElement {
htmlelement: HTMLElement::new_inherited(HTMLIFrameElementTypeId, localName, document),
- frame: Untraceable::new(None),
size: None,
sandbox: None,
}
@@ -275,4 +281,35 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
self.deref_mut().sandbox = None;
}
}
+
+ fn bind_to_tree(&mut self) {
+ match self.super_type() {
+ Some(ref mut s) => s.bind_to_tree(),
+ _ => (),
+ }
+
+ match self.get_url() {
+ Some(url) => {
+ let sandboxed = if self.is_sandboxed() {
+ IFrameSandboxed
+ } else {
+ IFrameUnsandboxed
+ };
+
+ // Subpage Id
+ let window = window_from_node(self).root();
+ let page = window.deref().page();
+ let subpage_id = page.get_next_subpage_id();
+
+ self.deref_mut().size = Some(IFrameSize {
+ pipeline_id: page.id,
+ subpage_id: subpage_id,
+ });
+
+ let ConstellationChan(ref chan) = *page.constellation_chan.deref();
+ chan.send(LoadIframeUrlMsg(url, page.id, subpage_id, sandboxed));
+ }
+ _ => ()
+ }
+ }
}
diff --git a/src/components/script/dom/node.rs b/src/components/script/dom/node.rs
index 214dee08baf..e8be5f449aa 100644
--- a/src/components/script/dom/node.rs
+++ b/src/components/script/dom/node.rs
@@ -44,6 +44,8 @@ use std::cast;
use std::cell::{RefCell, Ref, RefMut};
use std::iter::{Map, Filter};
use std::mem;
+use style::ComputedValues;
+use sync::Arc;
use serialize::{Encoder, Encodable};
@@ -143,9 +145,16 @@ enum SuppressObserver {
Unsuppressed
}
+/// Layout data that is shared between the script and layout tasks.
+pub struct SharedLayoutData {
+ /// The results of CSS styling for this node.
+ pub style: Option<Arc<ComputedValues>>,
+}
+
/// Encapsulates the abstract layout data.
pub struct LayoutData {
chan: Option<LayoutChan>,
+ shared_data: SharedLayoutData,
data: *(),
}
diff --git a/src/components/script/dom/window.rs b/src/components/script/dom/window.rs
index ab51a5f457c..7e366492719 100644
--- a/src/components/script/dom/window.rs
+++ b/src/components/script/dom/window.rs
@@ -70,7 +70,7 @@ pub struct Window {
pub location: Option<JS<Location>>,
pub navigator: Option<JS<Navigator>>,
pub image_cache_task: ImageCacheTask,
- pub active_timers: ~HashMap<TimerId, TimerHandle>,
+ pub active_timers: HashMap<TimerId, TimerHandle>,
pub next_timer_handle: i32,
pub compositor: Untraceable<~ScriptListener>,
pub browser_context: Option<BrowserContext>,
@@ -380,7 +380,7 @@ impl Window {
location: None,
navigator: None,
image_cache_task: image_cache_task,
- active_timers: ~HashMap::new(),
+ active_timers: HashMap::new(),
next_timer_handle: 0,
browser_context: None,
performance: None,
diff --git a/src/components/script/html/hubbub_html_parser.rs b/src/components/script/html/hubbub_html_parser.rs
index 37f8c63f95b..46f047053f5 100644
--- a/src/components/script/html/hubbub_html_parser.rs
+++ b/src/components/script/html/hubbub_html_parser.rs
@@ -4,14 +4,12 @@
use dom::attr::AttrMethods;
use dom::bindings::codegen::InheritTypes::{NodeBase, NodeCast, TextCast, ElementCast};
-use dom::bindings::codegen::InheritTypes::HTMLIFrameElementCast;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root};
use dom::bindings::utils::Reflectable;
use dom::document::{Document, DocumentHelpers};
-use dom::element::{AttributeHandlers, HTMLLinkElementTypeId, HTMLIFrameElementTypeId};
+use dom::element::{AttributeHandlers, HTMLLinkElementTypeId};
use dom::htmlelement::HTMLElement;
use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6};
-use dom::htmliframeelement::{IFrameSize, HTMLIFrameElementHelpers};
use dom::htmlformelement::HTMLFormElement;
use dom::node::{ElementNodeTypeId, NodeHelpers, NodeMethods};
use dom::types::*;
@@ -19,8 +17,9 @@ use html::cssparse::{StylesheetProvenance, UrlProvenance, spawn_css_parser};
use script_task::Page;
use hubbub::hubbub;
-use servo_msg::constellation_msg::SubpageId;
+use hubbub::hubbub::{NullNs, XLinkNs, XmlNs, XmlNsNs};
use servo_net::resource_task::{Load, Payload, Done, ResourceTask, load_whole_resource};
+use servo_util::namespace;
use servo_util::namespace::Null;
use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
use servo_util::task::spawn_named;
@@ -67,7 +66,6 @@ enum JSMessage {
/// Messages generated by the HTML parser upon discovery of additional resources
pub enum HtmlDiscoveryMessage {
HtmlDiscoveredStyle(Stylesheet),
- HtmlDiscoveredIFrame((Url, SubpageId, bool)),
HtmlDiscoveredScript(JSResult)
}
@@ -252,7 +250,6 @@ pub fn parse_html(page: &Page,
resource_task: ResourceTask)
-> HtmlParserResult {
debug!("Hubbub: parsing {:?}", url);
- let next_subpage_id: SubpageId = page.next_subpage_id.deref().get();
// Spawn a CSS parser to receive links to CSS style sheets.
let (discovery_chan, discovery_port) = channel();
@@ -288,8 +285,6 @@ pub fn parse_html(page: &Page,
*page.mut_url() = Some((url2.clone(), true));
}
- let pipeline_id = page.id;
-
let mut parser = hubbub::Parser("UTF-8", false);
debug!("created parser");
@@ -299,8 +294,6 @@ pub fn parse_html(page: &Page,
let (css_chan2, js_chan2) = (css_chan.clone(), js_chan.clone());
- let next_subpage_id = RefCell::new(next_subpage_id);
-
let doc_cell = RefCell::new(document);
let tree_handler = hubbub::TreeHandler {
@@ -336,10 +329,17 @@ pub fn parse_html(page: &Page,
debug!("-- attach attrs");
for attr in tag.attributes.iter() {
- //FIXME: this should have proper error handling or explicitly drop
- // exceptions on the ground
- assert!(element.set_attr(attr.name.clone(),
- attr.value.clone()).is_ok());
+ let (namespace, prefix) = match attr.ns {
+ NullNs => (namespace::Null, None),
+ XLinkNs => (namespace::XLink, Some("xlink")),
+ XmlNs => (namespace::XML, Some("xml")),
+ XmlNsNs => (namespace::XMLNS, Some("xmlns")),
+ ns => fail!("Not expecting namespace {:?}", ns),
+ };
+ element.set_attribute_from_parser(attr.name.clone(),
+ attr.value.clone(),
+ namespace,
+ prefix.map(|p| p.to_owned()));
}
//FIXME: workaround for https://github.com/mozilla/rust/issues/13246;
@@ -352,10 +352,6 @@ pub fn parse_html(page: &Page,
let href= element.get_attribute(Null, "href").root();
href.map(|a| a.deref().Value())
};
- let src_opt = {
- let src_opt = element.get_attribute(Null, "src").root();
- src_opt.map(|a| a.deref().Value())
- };
// Spawn additional parsing, network loads, etc. from tag and attrs
let type_id = {
@@ -377,30 +373,6 @@ pub fn parse_html(page: &Page,
_ => {}
}
}
-
- ElementNodeTypeId(HTMLIFrameElementTypeId) => {
- let iframe_chan = discovery_chan.clone();
- let iframe_element: &mut JSRef<HTMLIFrameElement> =
- HTMLIFrameElementCast::to_mut_ref(&mut *element).unwrap();
- let sandboxed = iframe_element.is_sandboxed();
- for src in src_opt.iter() {
- let iframe_url = parse_url(*src, Some(url2.clone()));
- iframe_element.set_frame(iframe_url.clone());
-
- // Subpage Id
- let subpage_id = *next_subpage_id.borrow();
- let SubpageId(id_num) = subpage_id;
- *next_subpage_id.borrow_mut() = SubpageId(id_num + 1);
-
- iframe_element.deref_mut().size = Some(IFrameSize {
- pipeline_id: pipeline_id,
- subpage_id: subpage_id,
- });
- iframe_chan.send(HtmlDiscoveredIFrame((iframe_url,
- subpage_id,
- sandboxed)));
- }
- }
_ => {}
}
diff --git a/src/components/script/script.rs b/src/components/script/script.rs
index 4f90bf8ebd5..841bf7f8449 100644
--- a/src/components/script/script.rs
+++ b/src/components/script/script.rs
@@ -31,6 +31,7 @@ extern crate servo_macros = "macros";
extern crate servo_net = "net";
extern crate servo_util = "util";
extern crate style;
+extern crate sync;
extern crate servo_msg = "msg";
extern crate url;
diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs
index 3786091e7d7..9f71fdeba5d 100644
--- a/src/components/script/script_task.rs
+++ b/src/components/script/script_task.rs
@@ -22,7 +22,7 @@ use dom::node;
use dom::node::{Node, NodeHelpers};
use dom::window::{TimerId, Window};
use html::hubbub_html_parser::HtmlParserResult;
-use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredIFrame, HtmlDiscoveredScript};
+use html::hubbub_html_parser::{HtmlDiscoveredStyle, HtmlDiscoveredScript};
use html::hubbub_html_parser;
use layout_interface::{AddStylesheetMsg, DocumentDamage};
use layout_interface::{DocumentDamageLevel, HitTestQuery, HitTestResponse, LayoutQuery, MouseOverQuery, MouseOverResponse};
@@ -43,8 +43,7 @@ use js::rust::with_compartment;
use js;
use servo_msg::compositor_msg::{FinishedLoading, LayerId, Loading, PerformingLayout};
use servo_msg::compositor_msg::{ScriptListener};
-use servo_msg::constellation_msg::{ConstellationChan, IFrameSandboxed, IFrameUnsandboxed};
-use servo_msg::constellation_msg::{LoadIframeUrlMsg, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
+use servo_msg::constellation_msg::{ConstellationChan, LoadCompleteMsg, LoadUrlMsg, NavigationDirection};
use servo_msg::constellation_msg::{PipelineId, SubpageId, Failure, FailureMsg};
use servo_msg::constellation_msg;
use servo_net::image_cache_task::ImageCacheTask;
@@ -157,67 +156,78 @@ pub struct Page {
/// Associated resource task for use by DOM objects like XMLHttpRequest
pub resource_task: Untraceable<ResourceTask>,
-}
-pub struct PageTree {
- pub page: Rc<Page>,
- pub inner: Vec<PageTree>,
+ /// A handle for communicating messages to the constellation task.
+ pub constellation_chan: Untraceable<ConstellationChan>,
+
+ // Child Pages.
+ pub children: Traceable<RefCell<Vec<Rc<Page>>>>,
}
-pub struct PageTreeIterator<'a> {
- stack: Vec<&'a mut PageTree>,
+pub struct PageIterator {
+ stack: Vec<Rc<Page>>,
}
-impl PageTree {
- fn new(id: PipelineId, layout_chan: LayoutChan,
- window_size: Size2D<uint>, resource_task: ResourceTask) -> PageTree {
- PageTree {
- page: Rc::new(Page {
- id: id,
- frame: Traceable::new(RefCell::new(None)),
- layout_chan: Untraceable::new(layout_chan),
- layout_join_port: Untraceable::new(RefCell::new(None)),
- damage: Traceable::new(RefCell::new(None)),
- window_size: Untraceable::new(Cell::new(window_size)),
- js_info: Traceable::new(RefCell::new(None)),
- url: Untraceable::new(RefCell::new(None)),
- next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))),
- resize_event: Untraceable::new(Cell::new(None)),
- fragment_node: Traceable::new(RefCell::new(None)),
- last_reflow_id: Traceable::new(Cell::new(0)),
- resource_task: Untraceable::new(resource_task)
- }),
- inner: vec!(),
+trait IterablePage {
+ fn iter(&self) -> PageIterator;
+ fn find(&self, id: PipelineId) -> Option<Rc<Page>>;
+}
+impl IterablePage for Rc<Page> {
+ fn iter(&self) -> PageIterator {
+ PageIterator {
+ stack: vec!(self.clone()),
}
}
-
- fn id(&self) -> PipelineId {
- self.page().id
- }
-
- fn page<'a>(&'a self) -> &'a Page {
- &*self.page
- }
-
- pub fn find<'a> (&'a mut self, id: PipelineId) -> Option<&'a mut PageTree> {
- if self.page().id == id { return Some(self); }
- for page_tree in self.inner.mut_iter() {
- let found = page_tree.find(id);
+ fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
+ if self.id == id { return Some(self.clone()); }
+ for page in self.children.deref().borrow().iter() {
+ let found = page.find(id);
if found.is_some() { return found; }
}
None
}
- pub fn iter<'a>(&'a mut self) -> PageTreeIterator<'a> {
- PageTreeIterator {
- stack: vec!(self),
+}
+
+impl Page {
+ fn new(id: PipelineId, layout_chan: LayoutChan,
+ window_size: Size2D<uint>, resource_task: ResourceTask,
+ constellation_chan: ConstellationChan,
+ js_context: Rc<Cx>) -> Page {
+ let js_info = JSPageInfo {
+ dom_static: GlobalStaticData(),
+ js_context: Untraceable::new(js_context),
+ };
+ Page {
+ id: id,
+ frame: Traceable::new(RefCell::new(None)),
+ layout_chan: Untraceable::new(layout_chan),
+ layout_join_port: Untraceable::new(RefCell::new(None)),
+ damage: Traceable::new(RefCell::new(None)),
+ window_size: Untraceable::new(Cell::new(window_size)),
+ js_info: Traceable::new(RefCell::new(Some(js_info))),
+ url: Untraceable::new(RefCell::new(None)),
+ next_subpage_id: Untraceable::new(Cell::new(SubpageId(0))),
+ resize_event: Untraceable::new(Cell::new(None)),
+ fragment_node: Traceable::new(RefCell::new(None)),
+ last_reflow_id: Traceable::new(Cell::new(0)),
+ resource_task: Untraceable::new(resource_task),
+ constellation_chan: Untraceable::new(constellation_chan),
+ children: Traceable::new(RefCell::new(vec!())),
}
}
+ fn id(&self) -> PipelineId {
+ self.id
+ }
+
// must handle root case separately
- pub fn remove(&mut self, id: PipelineId) -> Option<PageTree> {
+ pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
let remove_idx = {
- self.inner.mut_iter()
+ self.children
+ .deref()
+ .borrow_mut()
+ .mut_iter()
.enumerate()
.find(|&(_idx, ref page_tree)| {
// FIXME: page_tree has a lifetime such that it's unusable for anything.
@@ -229,9 +239,9 @@ impl PageTree {
.map(|(idx, _)| idx)
};
match remove_idx {
- Some(idx) => return Some(self.inner.remove(idx).unwrap()),
+ Some(idx) => return Some(self.children.deref().borrow_mut().remove(idx).unwrap()),
None => {
- for page_tree in self.inner.mut_iter() {
+ for page_tree in self.children.deref().borrow_mut().mut_iter() {
match page_tree.remove(id) {
found @ Some(_) => return found,
None => (), // keep going...
@@ -243,14 +253,14 @@ impl PageTree {
}
}
-impl<'a> Iterator<Rc<Page>> for PageTreeIterator<'a> {
+impl Iterator<Rc<Page>> for PageIterator {
fn next(&mut self) -> Option<Rc<Page>> {
if !self.stack.is_empty() {
let next = self.stack.pop().unwrap();
- for child in next.inner.mut_iter() {
- self.stack.push(child);
+ for child in next.children.deref().borrow().iter() {
+ self.stack.push(child.clone());
}
- Some(next.page.clone())
+ Some(next.clone())
} else {
None
}
@@ -282,6 +292,13 @@ impl Page {
self.frame.deref().borrow_mut()
}
+ pub fn get_next_subpage_id(&self) -> SubpageId {
+ let subpage_id = self.next_subpage_id.deref().get();
+ let SubpageId(id_num) = subpage_id;
+ self.next_subpage_id.deref().set(SubpageId(id_num + 1));
+ subpage_id
+ }
+
/// Adds the given damage.
pub fn damage(&self, level: DocumentDamageLevel) {
let root = match *self.frame() {
@@ -432,13 +449,6 @@ impl Page {
}
}
- pub fn initialize_js_info(&self, js_context: Rc<Cx>) {
- *self.mut_js_info() = Some(JSPageInfo {
- dom_static: GlobalStaticData(),
- js_context: Untraceable::new(js_context),
- });
- }
-
pub fn hit_test(&self, point: &Point2D<f32>) -> Option<UntrustedNodeAddress> {
let frame = self.frame();
let document = frame.get_ref().document.root();
@@ -522,7 +532,7 @@ impl Drop for StackRootTLS {
/// FIXME: Rename to `Page`, following WebKit?
pub struct ScriptTask {
/// A handle to the information pertaining to page layout
- pub page_tree: RefCell<PageTree>,
+ pub page: RefCell<Rc<Page>>,
/// A handle to the image cache task.
pub image_cache_task: ImageCacheTask,
/// A handle to the resource task.
@@ -572,8 +582,8 @@ impl<'a> Drop for ScriptMemoryFailsafe<'a> {
fn drop(&mut self) {
match self.owner {
Some(owner) => {
- let mut page_tree = owner.page_tree.borrow_mut();
- for page in page_tree.iter() {
+ let mut page = owner.page.borrow_mut();
+ for page in page.iter() {
*page.mut_js_info() = None;
}
*owner.js_context.borrow_mut() = None;
@@ -596,9 +606,12 @@ impl ScriptTask {
window_size: Size2D<uint>)
-> Rc<ScriptTask> {
let (js_runtime, js_context) = ScriptTask::new_rt_and_cx();
+ let page = Page::new(id, layout_chan, window_size,
+ resource_task.clone(),
+ constellation_chan.clone(),
+ js_context.clone());
Rc::new(ScriptTask {
- page_tree: RefCell::new(PageTree::new(id, layout_chan,
- window_size, resource_task.clone())),
+ page: RefCell::new(Rc::new(page)),
image_cache_task: img_cache_task,
resource_task: resource_task,
@@ -703,8 +716,8 @@ impl ScriptTask {
let mut resizes = vec!();
{
- let mut page_tree = self.page_tree.borrow_mut();
- for page in page_tree.iter() {
+ let mut page = self.page.borrow_mut();
+ for page in page.iter() {
// Only process a resize if layout is idle.
let layout_join_port = page.layout_join_port.deref().borrow();
if layout_join_port.is_none() {
@@ -731,8 +744,8 @@ impl ScriptTask {
loop {
match event {
ResizeMsg(id, size) => {
- let mut page_tree = self.page_tree.borrow_mut();
- let page = page_tree.find(id).expect("resize sent to nonexistent pipeline").page();
+ let mut page = self.page.borrow_mut();
+ let page = page.find(id).expect("resize sent to nonexistent pipeline");
page.resize_event.deref().set(Some(size));
}
_ => {
@@ -774,23 +787,25 @@ impl ScriptTask {
layout_chan
} = new_layout_info;
- let mut page_tree = self.page_tree.borrow_mut();
- let parent_page_tree = page_tree.find(old_id).expect("ScriptTask: received a layout
+ let mut page = self.page.borrow_mut();
+ let parent_page = page.find(old_id).expect("ScriptTask: received a layout
whose parent has a PipelineId which does not correspond to a pipeline in the script
task's page tree. This is a bug.");
- let new_page_tree = {
- let window_size = parent_page_tree.page().window_size.deref().get();
- PageTree::new(new_id, layout_chan, window_size,
- parent_page_tree.page().resource_task.deref().clone())
+ let new_page = {
+ let window_size = parent_page.window_size.deref().get();
+ Page::new(new_id, layout_chan, window_size,
+ parent_page.resource_task.deref().clone(),
+ self.constellation_chan.clone(),
+ self.js_context.borrow().get_ref().clone())
};
- parent_page_tree.inner.push(new_page_tree);
+ parent_page.children.deref().borrow_mut().push(Rc::new(new_page));
}
/// Handles a timer that fired.
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
- let mut page_tree = self.page_tree.borrow_mut();
- let page = page_tree.find(id).expect("ScriptTask: received fire timer msg for a
- pipeline ID not associated with this script task. This is a bug.").page();
+ let mut page = self.page.borrow_mut();
+ let page = page.find(id).expect("ScriptTask: received fire timer msg for a
+ pipeline ID not associated with this script task. This is a bug.");
let frame = page.frame();
let mut window = frame.get_ref().window.root();
@@ -823,10 +838,10 @@ impl ScriptTask {
/// Handles a notification that reflow completed.
fn handle_reflow_complete_msg(&self, pipeline_id: PipelineId, reflow_id: uint) {
debug!("Script: Reflow {:?} complete for {:?}", reflow_id, pipeline_id);
- let mut page_tree = self.page_tree.borrow_mut();
- let page = page_tree.find(pipeline_id).expect(
+ let mut page = self.page.borrow_mut();
+ let page = page.find(pipeline_id).expect(
"ScriptTask: received a load message for a layout channel that is not associated \
- with this script task. This is a bug.").page();
+ with this script task. This is a bug.");
let last_reflow_id = page.last_reflow_id.deref().get();
if last_reflow_id == reflow_id {
let mut layout_join_port = page.layout_join_port.deref().borrow_mut();
@@ -844,9 +859,9 @@ impl ScriptTask {
/// Window was resized, but this script was not active, so don't reflow yet
fn handle_resize_inactive_msg(&self, id: PipelineId, new_size: Size2D<uint>) {
- let mut page_tree = self.page_tree.borrow_mut();
- let page = page_tree.find(id).expect("Received resize message for PipelineId not associated
- with a page in the page tree. This is a bug.").page();
+ let mut page = self.page.borrow_mut();
+ let page = page.find(id).expect("Received resize message for PipelineId not associated
+ with a page in the page tree. This is a bug.");
page.window_size.deref().set(new_size);
let mut page_url = page.mut_url();
let last_loaded_url = replace(&mut *page_url, None);
@@ -873,18 +888,18 @@ impl ScriptTask {
/// Returns true if the script task should shut down and false otherwise.
fn handle_exit_pipeline_msg(&self, id: PipelineId) -> bool {
// If root is being exited, shut down all pages
- let mut page_tree = self.page_tree.borrow_mut();
- if page_tree.page().id == id {
+ let mut page = self.page.borrow_mut();
+ if page.id == id {
debug!("shutting down layout for root page {:?}", id);
*self.js_context.borrow_mut() = None;
- shut_down_layout(&mut *page_tree, (*self.js_runtime).ptr);
+ shut_down_layout(&*page, (*self.js_runtime).ptr);
return true
}
// otherwise find just the matching page and exit all sub-pages
- match page_tree.remove(id) {
- Some(ref mut page_tree) => {
- shut_down_layout(&mut *page_tree, (*self.js_runtime).ptr);
+ match page.remove(id) {
+ Some(ref mut page) => {
+ shut_down_layout(&*page, (*self.js_runtime).ptr);
false
}
// TODO(tkuehn): pipeline closing is currently duplicated across
@@ -900,34 +915,32 @@ impl ScriptTask {
fn load(&self, pipeline_id: PipelineId, url: Url) {
debug!("ScriptTask: loading {:?} on page {:?}", url, pipeline_id);
- let mut page_tree = self.page_tree.borrow_mut();
- let page_tree = page_tree.find(pipeline_id).expect("ScriptTask: received a load
+ let mut page = self.page.borrow_mut();
+ let page = page.find(pipeline_id).expect("ScriptTask: received a load
message for a layout channel that is not associated with this script task. This
is a bug.");
- let page = page_tree.page();
let last_loaded_url = replace(&mut *page.mut_url(), None);
- for loaded in last_loaded_url.iter() {
- let (ref loaded, needs_reflow) = *loaded;
- if *loaded == url {
+ match last_loaded_url {
+ Some((ref loaded, needs_reflow)) if *loaded == url => {
*page.mut_url() = Some((loaded.clone(), false));
if needs_reflow {
page.damage(ContentChangedDocumentDamage);
page.reflow(ReflowForDisplay, self.chan.clone(), self.compositor);
}
return;
- }
+ },
+ _ => (),
}
let cx = self.js_context.borrow();
let cx = cx.get_ref();
// Create the window and document objects.
let mut window = Window::new(cx.deref().ptr,
- page_tree.page.clone(),
+ page.clone(),
self.chan.clone(),
self.compositor.dup(),
self.image_cache_task.clone()).root();
- page.initialize_js_info(cx.clone());
let mut document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root();
window.deref_mut().init_browser_context(&*document);
@@ -940,7 +953,7 @@ impl ScriptTask {
// Parse HTML.
//
// Note: We can parse the next document in parallel with any previous documents.
- let html_parsing_result = hubbub_html_parser::parse_html(page,
+ let html_parsing_result = hubbub_html_parser::parse_html(&*page,
&mut *document,
url.clone(),
self.resource_task.clone());
@@ -974,20 +987,6 @@ impl ScriptTask {
let LayoutChan(ref chan) = *page.layout_chan;
chan.send(AddStylesheetMsg(sheet));
}
- Some(HtmlDiscoveredIFrame((iframe_url, subpage_id, sandboxed))) => {
- let SubpageId(num) = subpage_id;
- page.next_subpage_id.deref().set(SubpageId(num + 1));
- let sandboxed = if sandboxed {
- IFrameSandboxed
- } else {
- IFrameUnsandboxed
- };
- let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(LoadIframeUrlMsg(iframe_url,
- pipeline_id,
- subpage_id,
- sandboxed));
- }
None => break
}
}
@@ -1054,10 +1053,10 @@ impl ScriptTask {
///
/// TODO: Actually perform DOM event dispatch.
fn handle_event(&self, pipeline_id: PipelineId, event: Event_) {
- fn get_page<'a>(page_tree: &'a mut PageTree, pipeline_id: PipelineId) -> &'a Page {
- page_tree.find(pipeline_id).expect("ScriptTask: received an event \
+ fn get_page(page: &Rc<Page>, pipeline_id: PipelineId) -> Rc<Page> {
+ page.find(pipeline_id).expect("ScriptTask: received an event \
message for a layout channel that is not associated with this script task.\
- This is a bug.").page()
+ This is a bug.")
}
match event {
@@ -1065,8 +1064,7 @@ impl ScriptTask {
debug!("script got resize event: {:u}, {:u}", new_width, new_height);
let window = {
- let mut page_tree = self.page_tree.borrow_mut();
- let page = get_page(&mut *page_tree, pipeline_id);
+ let page = get_page(&*self.page.borrow(), pipeline_id);
page.window_size.deref().set(Size2D(new_width, new_height));
let frame = page.frame();
@@ -1102,9 +1100,7 @@ impl ScriptTask {
// FIXME(pcwalton): This reflows the entire document and is not incremental-y.
ReflowEvent => {
debug!("script got reflow event");
-
- let mut page_tree = self.page_tree.borrow_mut();
- let page = get_page(&mut *page_tree, pipeline_id);
+ let page = get_page(&*self.page.borrow(), pipeline_id);
let frame = page.frame();
if frame.is_some() {
page.damage(MatchSelectorsDocumentDamage);
@@ -1114,8 +1110,7 @@ impl ScriptTask {
ClickEvent(_button, point) => {
debug!("ClickEvent: clicked at {:?}", point);
- let mut page_tree = self.page_tree.borrow_mut();
- let page = get_page(&mut *page_tree, pipeline_id);
+ let page = get_page(&*self.page.borrow(), pipeline_id);
match page.hit_test(&point) {
Some(node_address) => {
debug!("node address is {:?}", node_address);
@@ -1129,7 +1124,7 @@ impl ScriptTask {
Some(node) => {
debug!("clicked on {:s}", node.debug_str());
let element: &JSRef<Element> = ElementCast::to_ref(&node).unwrap();
- self.load_url_from_element(page, element);
+ self.load_url_from_element(&*page, element);
}
None => {}
}
@@ -1141,8 +1136,7 @@ impl ScriptTask {
MouseDownEvent(..) => {}
MouseUpEvent(..) => {}
MouseMoveEvent(point) => {
- let mut page_tree = self.page_tree.borrow_mut();
- let page = get_page(&mut *page_tree, pipeline_id);
+ let page = get_page(&*self.page.borrow(), pipeline_id);
match page.get_nodes_under_mouse(&point) {
Some(node_address) => {
@@ -1232,7 +1226,7 @@ impl ScriptTask {
}
/// Shuts down layout for the given page tree.
-fn shut_down_layout(page_tree: &mut PageTree, rt: *JSRuntime) {
+fn shut_down_layout(page_tree: &Rc<Page>, rt: *JSRuntime) {
for page in page_tree.iter() {
page.join_layout();
diff --git a/src/components/util/range.rs b/src/components/util/range.rs
index 0acf6343dab..05421d9af87 100644
--- a/src/components/util/range.rs
+++ b/src/components/util/range.rs
@@ -6,12 +6,85 @@ use std::cmp::{max, min};
use std::iter;
use std::fmt;
use std::num;
-use std::num::Bounded;
+use std::num::{Bounded, Zero};
+
+/// An index type to be used by a `Range`
+pub trait RangeIndex<T>: Eq + Ord
+ + Clone
+ + Copy
+ + Zero
+ + TotalEq
+ + TotalOrd
+ + Add<Self, Self>
+ + Sub<Self, Self>
+ + Neg<Self>
+ + fmt::Show {
+ fn new(x: T) -> Self;
+ fn get(self) -> T;
+}
+
+impl RangeIndex<int> for int {
+ #[inline]
+ fn new(x: int) -> int { x }
+
+ #[inline]
+ fn get(self) -> int { self }
+}
+
+/// Implements a range index type with operator overloads
+#[macro_export]
+macro_rules! range_index {
+ ($(#[$attr:meta])* struct $Self:ident($T:ty)) => (
+ #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show, Zero)]
+ $(#[$attr])*
+ pub struct $Self(pub $T);
+
+ impl $Self {
+ #[inline]
+ pub fn to_uint(self) -> uint {
+ self.get() as uint
+ }
+ }
+
+ impl RangeIndex<$T> for $Self {
+ #[inline]
+ fn new(x: $T) -> $Self {
+ $Self(x)
+ }
+
+ #[inline]
+ fn get(self) -> $T {
+ match self { $Self(x) => x }
+ }
+ }
+
+ impl Add<$Self, $Self> for $Self {
+ #[inline]
+ fn add(&self, other: &$Self) -> $Self {
+ $Self(self.get() + other.get())
+ }
+ }
+
+ impl Sub<$Self, $Self> for $Self {
+ #[inline]
+ fn sub(&self, other: &$Self) -> $Self {
+ $Self(self.get() - other.get())
+ }
+ }
+
+ impl Neg<$Self> for $Self {
+ #[inline]
+ fn neg(&self) -> $Self {
+ $Self(-self.get())
+ }
+ }
+ )
+}
#[deriving(Show)]
-pub enum RangeRelation<T> {
- OverlapsBegin(/* overlap */ T),
- OverlapsEnd(/* overlap */ T),
+pub enum RangeRelation<I> {
+ OverlapsBegin(/* overlap */ I),
+ OverlapsEnd(/* overlap */ I),
ContainedBy,
Contains,
Coincides,
@@ -19,59 +92,88 @@ pub enum RangeRelation<T> {
EntirelyAfter
}
+/// A range of indices
#[deriving(Clone)]
-pub struct Range<T> {
- off: T,
- len: T,
+pub struct Range<I> {
+ off: I,
+ len: I,
}
-impl<T: Int + TotalOrd + Signed> fmt::Show for Range<T> {
+impl<T: Int, I: fmt::Show + RangeIndex<T>> fmt::Show for Range<I> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f.buf, "[{} .. {})", self.begin(), self.end())
}
}
-impl<T: Int + TotalOrd + Signed> Range<T> {
+/// An iterator over each index in a range
+pub struct EachIndex<T, I> {
+ it: iter::Range<T>,
+}
+
+pub fn each_index<T: Int, I: RangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I> {
+ EachIndex {
+ it: iter::range(start.get(), stop.get())
+ }
+}
+
+impl<T: Int, I: RangeIndex<T>> Iterator<I> for EachIndex<T, I> {
#[inline]
- pub fn new(off: T, len: T) -> Range<T> {
- Range {
- off: off,
- len: len,
- }
+ fn next(&mut self) -> Option<I> {
+ self.it.next().map(|i| RangeIndex::new(i))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (uint, Option<uint>) {
+ self.it.size_hint()
+ }
+}
+
+impl<T: Int, I: RangeIndex<T>> Range<I> {
+ #[inline]
+ pub fn new(off: I, len: I) -> Range<I> {
+ Range { off: off, len: len }
}
#[inline]
- pub fn empty() -> Range<T> {
+ pub fn empty() -> Range<I> {
Range::new(num::zero(), num::zero())
}
#[inline]
- pub fn begin(&self) -> T { self.off }
+ pub fn begin(&self) -> I { self.off }
#[inline]
- pub fn length(&self) -> T { self.len }
+ pub fn length(&self) -> I { self.len }
#[inline]
- pub fn end(&self) -> T { self.off + self.len }
+ pub fn end(&self) -> I { self.off + self.len }
#[inline]
- pub fn eachi(&self) -> iter::Range<T> {
- range(self.off, self.off + self.len)
+ pub fn each_index(&self) -> EachIndex<T, I> {
+ each_index(self.off, self.off + self.len)
}
#[inline]
- pub fn contains(&self, i: T) -> bool {
+ pub fn contains(&self, i: I) -> bool {
i >= self.begin() && i < self.end()
}
#[inline]
pub fn is_valid_for_string(&self, s: &str) -> bool {
let s_len = s.len();
- match num::cast(s_len) {
+ match num::cast::<uint, T>(s_len) {
Some(len) => {
- self.begin() < len && self.end() <= len && self.length() <= len
+ let len = RangeIndex::new(len);
+ self.begin() < len
+ && self.end() <= len
+ && self.length() <= len
},
None => {
- debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the max \
- value for T (max={})", s_len, { let val: T = Bounded::max_value(); val });
+ debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
+ max value for the range index (max={})", s_len,
+ {
+ let max: T = Bounded::max_value();
+ let val: I = RangeIndex::new(max);
+ val
+ });
false
},
}
@@ -83,34 +185,34 @@ impl<T: Int + TotalOrd + Signed> Range<T> {
}
#[inline]
- pub fn shift_by(&mut self, i: T) {
+ pub fn shift_by(&mut self, i: I) {
self.off = self.off + i;
}
#[inline]
- pub fn extend_by(&mut self, i: T) {
+ pub fn extend_by(&mut self, i: I) {
self.len = self.len + i;
}
#[inline]
- pub fn extend_to(&mut self, i: T) {
+ pub fn extend_to(&mut self, i: I) {
self.len = i - self.off;
}
#[inline]
- pub fn adjust_by(&mut self, off_i: T, len_i: T) {
+ pub fn adjust_by(&mut self, off_i: I, len_i: I) {
self.off = self.off + off_i;
self.len = self.len + len_i;
}
#[inline]
- pub fn reset(&mut self, off_i: T, len_i: T) {
+ pub fn reset(&mut self, off_i: I, len_i: I) {
self.off = off_i;
self.len = len_i;
}
#[inline]
- pub fn intersect(&self, other: &Range<T>) -> Range<T> {
+ pub fn intersect(&self, other: &Range<I>) -> Range<I> {
let begin = max(self.begin(), other.begin());
let end = min(self.end(), other.end());
@@ -125,7 +227,7 @@ impl<T: Int + TotalOrd + Signed> Range<T> {
/// from the point of view of `self`. So, 'EntirelyBefore' means
/// that the `self` range is entirely before `other` range.
#[inline]
- pub fn relation_to_range(&self, other: &Range<T>) -> RangeRelation<T> {
+ pub fn relation_to_range(&self, other: &Range<I>) -> RangeRelation<I> {
if other.begin() > self.end() {
return EntirelyBefore;
}
@@ -154,19 +256,20 @@ impl<T: Int + TotalOrd + Signed> Range<T> {
}
#[inline]
- pub fn repair_after_coalesced_range(&mut self, other: &Range<T>) {
+ pub fn repair_after_coalesced_range(&mut self, other: &Range<I>) {
let relation = self.relation_to_range(other);
debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
*other, relation);
+ let _1: I = RangeIndex::new(num::one::<T>());
match relation {
EntirelyBefore => {},
EntirelyAfter => { self.shift_by(-other.length()); },
- Coincides | ContainedBy => { self.reset(other.begin(), num::one()); },
+ Coincides | ContainedBy => { self.reset(other.begin(), _1); },
Contains => { self.extend_by(-other.length()); },
- OverlapsBegin(overlap) => { self.extend_by(num::one::<T>() - overlap); },
+ OverlapsBegin(overlap) => { self.extend_by(_1 - overlap); },
OverlapsEnd(overlap) => {
- let len = self.length() - overlap + num::one();
+ let len = self.length() - overlap + _1;
self.reset(other.begin(), len);
}
};
diff --git a/src/components/util/url.rs b/src/components/util/url.rs
index 47c4043b330..da2ca64c0e0 100644
--- a/src/components/util/url.rs
+++ b/src/components/util/url.rs
@@ -18,7 +18,7 @@ Create a URL object from a string. Does various helpful browsery things like
*/
// TODO: about:failure->
pub fn try_parse_url(str_url: &str, base_url: Option<std_url::Url>) -> Result<std_url::Url, ~str> {
- let str_url = str_url.trim_chars(& &[' ', '\t', '\n', '\r', '\x0C']).to_owned();
+ let str_url = str_url.trim_chars(& &[' ', '\t', '\n', '\r', '\x0C']);
let schm = std_url::get_scheme(str_url);
let str_url = match schm {
Err(_) => {
@@ -69,7 +69,7 @@ pub fn try_parse_url(str_url: &str, base_url: Option<std_url::Url>) -> Result<st
"file://".to_owned() + path.display().to_str()
}
// TODO: handle the rest of the about: pages
- _ => str_url
+ _ => str_url.to_owned()
}
},
"data" => {
@@ -78,7 +78,7 @@ pub fn try_parse_url(str_url: &str, base_url: Option<std_url::Url>) -> Result<st
// %-encoded or base64'd.
str_url.chars().filter(|&c| !c.is_whitespace()).collect()
},
- _ => str_url
+ _ => str_url.to_owned()
}
}
};