diff --git a/src/servo/gfx/display_list.rs b/src/servo/gfx/display_list.rs index e09b337032e..c324eb83dcb 100644 --- a/src/servo/gfx/display_list.rs +++ b/src/servo/gfx/display_list.rs @@ -4,11 +4,12 @@ use geom::rect::Rect; use image::base::Image; use render_context::RenderContext; use servo_text::text_run; +use text::text_run::SendableTextRun; +use util::range::Range; use std::arc::ARC; use clone_arc = std::arc::clone; use dvec::DVec; -use text::text_run::{TextRange, SendableTextRun}; pub use layout::display_list_builder::DisplayListBuilder; @@ -24,7 +25,7 @@ pub enum DisplayItemData { // TODO: need to provide spacing data for text run. // (i.e, to support rendering of CSS 'word-spacing' and 'letter-spacing') // TODO: don't copy text runs, ever. - TextData(~SendableTextRun, TextRange), + TextData(~SendableTextRun, Range), ImageData(ARC<~image::base::Image>), BorderData(au, u8, u8, u8) } @@ -76,7 +77,7 @@ pub fn Border(bounds: Rect, width: au, r: u8, g: u8, b: u8) -> DisplayItem { } } -pub fn Text(bounds: Rect, run: ~SendableTextRun, range: TextRange) -> DisplayItem { +pub fn Text(bounds: Rect, run: ~SendableTextRun, range: Range) -> DisplayItem { DisplayItem { draw: |self, ctx| draw_Text(self, ctx), bounds: bounds, diff --git a/src/servo/gfx/render_context.rs b/src/servo/gfx/render_context.rs index 430dd608d92..f125044ee78 100644 --- a/src/servo/gfx/render_context.rs +++ b/src/servo/gfx/render_context.rs @@ -2,10 +2,11 @@ use mod au = geometry; use compositor::LayerBuffer; use text::font::Font; -use text::text_run::{TextRun, TextRange}; +use text::text_run::TextRun; use text::font_cache::FontCache; use image::base::Image; use au = au::au; +use util::range::Range; use core::libc::types::common::c99::uint16_t; use core::ptr::to_unsafe_ptr; @@ -67,7 +68,7 @@ impl RenderContext { draw_options); } - pub fn draw_text(&self, bounds: Rect, run: &TextRun, range: TextRange) { + pub fn draw_text(&self, bounds: Rect, run: &TextRun, range: Range) { use ptr::{null}; use vec::raw::to_ptr; use libc::types::common::c99::{uint16_t, uint32_t}; diff --git a/src/servo/layout/box.rs b/src/servo/layout/box.rs index f312ea8ec3d..985e592536a 100644 --- a/src/servo/layout/box.rs +++ b/src/servo/layout/box.rs @@ -22,10 +22,11 @@ use layout::debug::BoxedDebugMethods; use layout::flow::FlowContext; use layout::text::TextBoxData; use servo_text::text_run; -use servo_text::text_run::{MutableTextRange, TextRange, TextRun}; +use servo_text::text_run::TextRun; use std::net::url::Url; use task::spawn; use util::color::Color; +use util::range::*; use util::tree; /** @@ -187,8 +188,8 @@ impl RenderBox : RenderBoxMethods { let mut pieces_processed_count : uint = 0; let mut remaining_width : au = max_width; - let left_range = MutableTextRange(data.range.begin(), 0); - let mut right_range : Option = None; + let left_range = MutableRange(data.range.begin(), 0); + let mut right_range : Option = None; debug!("split_to_width: splitting text box (strlen=%u, range=%?, avail_width=%?)", data.run.text.len(), data.range, max_width); do data.run.iter_indivisible_pieces_for_range(data.range) |piece_range| { @@ -216,14 +217,14 @@ impl RenderBox : RenderBoxMethods { // if there are still things after the trimmable whitespace, create right chunk if piece_range.end() < data.range.end() { debug!("split_to_width: case=skipping trimmable trailing whitespace, then split remainder"); - right_range = Some(TextRange(piece_range.end(), + right_range = Some(Range(piece_range.end(), data.range.end() - piece_range.end())); } else { debug!("split_to_width: case=skipping trimmable trailing whitespace"); } } else if piece_range.begin() < data.range.end() { // still things left, create right chunk - right_range = Some(TextRange(piece_range.begin(), + right_range = Some(Range(piece_range.begin(), data.range.end() - piece_range.begin())); debug!("split_to_width: case=splitting remainder with right range=%?", right_range); @@ -237,7 +238,7 @@ impl RenderBox : RenderBoxMethods { Some(layout::text::adapt_textbox_with_range(self.d(), data.run, left_range.as_immutable())) } else { None }; - let right_box = option::map_default(&right_range, None, |range: &TextRange| { + let right_box = option::map_default(&right_range, None, |range: &Range| { Some(layout::text::adapt_textbox_with_range(self.d(), data.run, *range)) }); diff --git a/src/servo/layout/inline.rs b/src/servo/layout/inline.rs index 2c86e15527c..3b06f033820 100644 --- a/src/servo/layout/inline.rs +++ b/src/servo/layout/inline.rs @@ -16,6 +16,7 @@ use num::Num; use servo_text::text_run::TextRun; use servo_text::util::*; use std::arc; +use util::range::Range; use util::tree; /* @@ -169,7 +170,7 @@ impl TextRunScanner { debug!("TextRunScanner: pushing single text box when start=%u,end=%u", self.clump_start, self.clump_end); let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump_start].d(), run, - TextRange(0, run.text.len())); + Range(0, run.text.len())); out_boxes.push(new_box); }, (false, true) => { @@ -223,7 +224,7 @@ impl TextRunScanner { debug!("TextRunScanner: pushing box(es) when start=%u,end=%u", self.clump_start, self.clump_end); let new_box = layout::text::adapt_textbox_with_range(in_boxes[self.clump_start].d(), run, - TextRange(0, run.text.len())); + Range(0, run.text.len())); out_boxes.push(new_box); } } /* /match */ diff --git a/src/servo/layout/text.rs b/src/servo/layout/text.rs index 49f8682f4ec..2277de9c89a 100644 --- a/src/servo/layout/text.rs +++ b/src/servo/layout/text.rs @@ -1,14 +1,15 @@ /** Text layout. */ -use servo_text::text_run::{TextRange, TextRun}; +use servo_text::text_run::TextRun; use layout::box::{TextBox, RenderBox, RenderBoxData, UnscannedTextBox}; +use util::range::Range; pub struct TextBoxData { run: @TextRun, - range: TextRange, + range: Range, } -pub fn TextBoxData(run: @TextRun, range: TextRange) -> TextBoxData { +pub fn TextBoxData(run: @TextRun, range: Range) -> TextBoxData { TextBoxData { run: run, range: range, @@ -16,7 +17,7 @@ pub fn TextBoxData(run: @TextRun, range: TextRange) -> TextBoxData { } pub fn adapt_textbox_with_range(box_data: &RenderBoxData, run: @TextRun, - range: TextRange) -> @RenderBox { + range: Range) -> @RenderBox { debug!("Creating textbox with span: (strlen=%u, off=%u, len=%u) of textrun: %s", run.text.len(), range.begin(), range.length(), run.text); let new_box_data = copy *box_data; diff --git a/src/servo/servo.rc b/src/servo/servo.rc index 87504256dbf..d9b6f2c5950 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -129,6 +129,7 @@ pub mod util { pub mod time; pub mod url; pub mod vec; + pub mod range; } pub mod opts; diff --git a/src/servo/text/font.rs b/src/servo/text/font.rs index d0fe1f246eb..7cd147f00dc 100644 --- a/src/servo/text/font.rs +++ b/src/servo/text/font.rs @@ -9,8 +9,9 @@ use glyph::GlyphIndex; use libc::{ c_int, c_double, c_ulong }; use native_font::NativeFont; use ptr::{null, addr_of}; -use text::text_run::{TextRun, TextRange}; +use text::text_run::TextRun; use vec_to_ptr = vec::raw::to_ptr; +use servo_util::range::Range; // Used to abstract over the shaper's choice of fixed int representation. type FractionalPixel = float; @@ -41,7 +42,7 @@ struct RunMetrics { // Public API pub trait FontMethods { - fn measure_text(&TextRun, TextRange) -> RunMetrics; + fn measure_text(&TextRun, Range) -> RunMetrics; fn buf(&self) -> @~[u8]; // these are used to get glyphs and advances in the case that the @@ -51,7 +52,7 @@ pub trait FontMethods { } pub impl Font : FontMethods { - fn measure_text(run: &TextRun, range: TextRange) -> RunMetrics { + fn measure_text(run: &TextRun, range: Range) -> RunMetrics { assert range.is_valid_for_string(run.text); // TODO: alter advance direction for RTL diff --git a/src/servo/text/glyph.rs b/src/servo/text/glyph.rs index 96782078284..99c1317d171 100644 --- a/src/servo/text/glyph.rs +++ b/src/servo/text/glyph.rs @@ -6,7 +6,7 @@ use core::u16; use geom::point::Point2D; use num::from_int; use std::sort; -use servo_text::text_run::TextRange; +use servo_util::range::Range; use servo_util::vec::*; @@ -545,7 +545,7 @@ impl GlyphStore { } } - fn iter_glyphs_for_range(&self, range: TextRange, cb: fn&(uint, GlyphInfo/&) -> T) { + fn iter_glyphs_for_range(&self, range: Range, cb: fn&(uint, GlyphInfo/&) -> T) { assert range.begin() < self.entry_buffer.len(); assert range.end() <= self.entry_buffer.len(); diff --git a/src/servo/text/text_run.rs b/src/servo/text/text_run.rs index 300cb6bdd7a..c99bd2ab2a8 100644 --- a/src/servo/text/text_run.rs +++ b/src/servo/text/text_run.rs @@ -12,6 +12,7 @@ use libc::{c_void}; use servo_util::color; use shaper::shape_textrun; use std::arc; +use servo_util::range::{Range, MutableRange}; pub struct TextRun { text: ~str, @@ -19,98 +20,6 @@ pub struct TextRun { priv glyphs: GlyphStore, } -pub struct TextRange { - priv off: u16, - priv len: u16 -} - -pure fn TextRange(off: uint, len :uint) -> TextRange { - assert off <= u16::max_value as uint; - assert len <= u16::max_value as uint; - - TextRange { - off: off as u16, - len: len as u16 - } -} - -impl TextRange { - pub pure fn begin() -> uint { self.off as uint } - pub pure fn length() -> uint { self.len as uint } - pub pure fn end() -> uint { (self.off as uint) + (self.len as uint) } - - pub pure fn eachi(cb: fn&(uint) -> bool) { - do uint::range(self.off as uint, - (self.off as uint) + (self.len as uint)) |i| { - cb(i) - } - } - - pub pure fn is_valid_for_string(s: &str) -> bool { - self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len() - } - - pub pure fn shift_by(i: int) -> TextRange { - TextRange(((self.off as int) + i) as uint, self.len as uint) - } - - pub pure fn extend_by(i: int) -> TextRange { - TextRange(self.off as uint, ((self.len as int) + i) as uint) - } - - pub pure fn adjust_by(off_i: int, len_i: int) -> TextRange { - TextRange(((self.off as int) + off_i) as uint, ((self.len as int) + len_i) as uint) - } -} - -pub struct MutableTextRange { - priv mut off: uint, - priv mut len: uint -} - -pure fn MutableTextRange(off: uint, len :uint) -> MutableTextRange { - MutableTextRange { off: off, len: len } -} - -impl MutableTextRange { - pub pure fn begin() -> uint { self.off } - pub pure fn length() -> uint { self.len } - pub pure fn end() -> uint { self.off + self.len } - pub pure fn eachi(cb: fn&(uint) -> bool) { - do uint::range(self.off, self.off + self.len) |i| { cb(i) } - } - - pub pure fn as_immutable() -> TextRange { - TextRange(self.begin(), self.length()) - } - - pub pure fn is_valid_for_string(s: &str) -> bool { - self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len() - } - - pub fn shift_by(i: int) { - self.off = ((self.off as int) + i) as uint; - } - - pub fn extend_by(i: int) { - self.len = ((self.len as int) + i) as uint; - } - - pub fn extend_to(i: uint) { - self.len = i - self.off; - } - - pub fn adjust_by(off_i: int, len_i: int) { - self.off = ((self.off as int) + off_i) as uint; - self.len = ((self.len as int) + len_i) as uint; - } - - pub fn reset(off_i: uint, len_i: uint) { - self.off = off_i; - self.len = len_i; - } -} - // This is a hack until TextRuns are normally sendable, or // we instead use ARC everywhere. pub struct SendableTextRun { @@ -139,20 +48,20 @@ pub fn deserialize(cache: @FontCache, run: &SendableTextRun) -> @TextRun { trait TextRunMethods { pure fn glyphs(&self) -> &self/GlyphStore; - fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool); + fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn&(Range) -> bool); // TODO: needs to take box style as argument, or move to TextBox. // see Gecko's IsTrimmableSpace methods for details. - pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool; + pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool; - fn metrics_for_range(&self, range: TextRange) -> RunMetrics; - fn min_width_for_range(&self, range: TextRange) -> au; - fn iter_natural_lines_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool); + fn metrics_for_range(&self, range: Range) -> RunMetrics; + fn min_width_for_range(&self, range: Range) -> au; + fn iter_natural_lines_for_range(&self, range: Range, f: fn&(Range) -> bool); } impl TextRun : TextRunMethods { pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs } - pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool { + pure fn range_is_trimmable_whitespace(&self, range: Range) -> bool { let mut i = range.begin(); while i < range.end() { // jump i to each new char @@ -166,11 +75,11 @@ impl TextRun : TextRunMethods { return true; } - fn metrics_for_range(&self, range: TextRange) -> RunMetrics { + fn metrics_for_range(&self, range: Range) -> RunMetrics { self.font.measure_text(self, range) } - fn min_width_for_range(&self, range: TextRange) -> au { + fn min_width_for_range(&self, range: Range) -> au { assert range.is_valid_for_string(self.text); let mut max_piece_width = au(0); @@ -181,10 +90,10 @@ impl TextRun : TextRunMethods { return max_piece_width; } - fn iter_natural_lines_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) { + fn iter_natural_lines_for_range(&self, range: Range, f: fn(Range) -> bool) { assert range.is_valid_for_string(self.text); - let clump = MutableTextRange(range.begin(), 0); + let clump = MutableRange(range.begin(), 0); let mut in_clump = false; // clump non-linebreaks of nonzero length @@ -209,10 +118,10 @@ impl TextRun : TextRunMethods { } } - fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) { + fn iter_indivisible_pieces_for_range(&self, range: Range, f: fn(Range) -> bool) { assert range.is_valid_for_string(self.text); - let clump = MutableTextRange(range.begin(), 0); + let clump = MutableRange(range.begin(), 0); loop { // find next non-whitespace byte index, then clump all whitespace before it. if clump.end() == range.end() { break } @@ -291,7 +200,7 @@ fn test_iter_indivisible_pieces() { let font = flib.get_test_font(); let run = TextRun(font, copy text); let mut slices : ~[~str] = ~[]; - for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |subrange| { + for run.iter_indivisible_pieces_for_range(Range(0, text.len())) |subrange| { slices.push(str::slice(text, subrange.begin(), subrange.length())); } assert slices == res; diff --git a/src/servo/util/range.rs b/src/servo/util/range.rs new file mode 100644 index 00000000000..ced76294aba --- /dev/null +++ b/src/servo/util/range.rs @@ -0,0 +1,91 @@ +pub struct Range { + priv off: u16, + priv len: u16 +} + +pub pure fn Range(off: uint, len: uint) -> Range { + assert off <= u16::max_value as uint; + assert len <= u16::max_value as uint; + + Range { + off: off as u16, + len: len as u16 + } +} + +pub impl Range { + pub pure fn begin() -> uint { self.off as uint } + pub pure fn length() -> uint { self.len as uint } + pub pure fn end() -> uint { (self.off as uint) + (self.len as uint) } + + pub pure fn eachi(cb: fn&(uint) -> bool) { + do uint::range(self.off as uint, + (self.off as uint) + (self.len as uint)) |i| { + cb(i) + } + } + + pub pure fn is_valid_for_string(s: &str) -> bool { + self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len() + } + + pub pure fn shift_by(i: int) -> Range { + Range(((self.off as int) + i) as uint, self.len as uint) + } + + pub pure fn extend_by(i: int) -> Range { + Range(self.off as uint, ((self.len as int) + i) as uint) + } + + pub pure fn adjust_by(off_i: int, len_i: int) -> Range { + Range(((self.off as int) + off_i) as uint, ((self.len as int) + len_i) as uint) + } +} + +pub struct MutableRange { + priv mut off: uint, + priv mut len: uint +} + +pure fn MutableRange(off: uint, len :uint) -> MutableRange { + MutableRange { off: off, len: len } +} + +impl MutableRange { + pub pure fn begin() -> uint { self.off } + pub pure fn length() -> uint { self.len } + pub pure fn end() -> uint { self.off + self.len } + pub pure fn eachi(cb: fn&(uint) -> bool) { + do uint::range(self.off, self.off + self.len) |i| { cb(i) } + } + + pub pure fn as_immutable() -> Range { + Range(self.begin(), self.length()) + } + + pub pure fn is_valid_for_string(s: &str) -> bool { + self.begin() < s.len() && self.end() <= s.len() && self.length() <= s.len() + } + + pub fn shift_by(i: int) { + self.off = ((self.off as int) + i) as uint; + } + + pub fn extend_by(i: int) { + self.len = ((self.len as int) + i) as uint; + } + + pub fn extend_to(i: uint) { + self.len = i - self.off; + } + + pub fn adjust_by(off_i: int, len_i: int) { + self.off = ((self.off as int) + off_i) as uint; + self.len = ((self.len as int) + len_i) as uint; + } + + pub fn reset(off_i: uint, len_i: uint) { + self.off = off_i; + self.len = len_i; + } +}