diff options
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() } } }; |