diff --git a/src/servo-gfx/font.rs b/src/servo-gfx/font.rs index 1b0b6970782..d04f065b8a9 100644 --- a/src/servo-gfx/font.rs +++ b/src/servo-gfx/font.rs @@ -375,6 +375,8 @@ pub trait FontMethods { range: &Range, baseline_origin: Point2D, color: Color); + // This calculates run metrics for the specified character range + // within the provided textrun. fn measure_text(&TextRun, &const Range) -> RunMetrics; fn shape_text(@self, &str, &mut GlyphStore); fn get_descriptor() -> FontDescriptor; @@ -448,12 +450,10 @@ pub impl Font : FontMethods { } fn measure_text(run: &TextRun, range: &const Range) -> RunMetrics { - assert range.is_valid_for_string(run.text); - // 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); - for run.glyphs.iter_glyphs_for_byte_range(range) |_i, glyph| { + for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| { advance += glyph.advance(); } let mut bounds = Rect(Point2D(Au(0), -self.metrics.ascent), diff --git a/src/servo-gfx/text/glyph.rs b/src/servo-gfx/text/glyph.rs index 5cd17125294..91011d78774 100644 --- a/src/servo-gfx/text/glyph.rs +++ b/src/servo-gfx/text/glyph.rs @@ -604,6 +604,7 @@ impl GlyphStore { } pure fn iter_glyphs_for_byte_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) { + warn!("Using deprecated iter_glyphs_for_byte_range API!"); if range.begin() >= self.entry_buffer.len() { error!("iter_glyphs_for_range: range.begin beyond length!"); return; @@ -613,9 +614,11 @@ impl GlyphStore { return; } - // TODO: actually compute char indexes from byte indexes. - let char_range = copy *range; - for char_range.eachi |i| { + self.iter_glyphs_for_char_range(range, cb) + } + + pure fn iter_glyphs_for_char_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) { + for range.eachi |i| { if !self.iter_glyphs_for_char_index(i, cb) { break; } } } diff --git a/src/servo-gfx/text/text_run.rs b/src/servo-gfx/text/text_run.rs index deaa5377f44..550802f084b 100644 --- a/src/servo-gfx/text/text_run.rs +++ b/src/servo-gfx/text/text_run.rs @@ -1,6 +1,9 @@ use font_context::FontContext; use geometry::Au; -use glyph::GlyphStore; +use glyph::{ + BreakTypeNormal, + GlyphStore, +}; use servo_gfx_font::{Font, FontDescriptor, RunMetrics}; use servo_gfx_util::range::Range; @@ -42,6 +45,7 @@ impl SendableTextRun { impl TextRun { static fn new(font: @Font, text: ~str) -> TextRun { let mut glyph_store = GlyphStore::new(str::char_len(text)); + TextRun::compute_potential_breaks(text, &mut glyph_store); font.shape_text(text, &mut glyph_store); let run = TextRun { @@ -52,6 +56,44 @@ impl TextRun { return move run; } + static fn compute_potential_breaks(text: &str, glyphs: &mut GlyphStore) { + // TODO(Issue #230): do a better job. See Gecko's LineBreaker. + + let mut i = 0u; + let mut prev_is_whitespace = false; + while i < text.len() { + let {ch, next} = str::char_range_at(text, i); + // set char properties. + match ch { + ' ' => { glyphs.set_char_is_space(i); }, + '\t' => { glyphs.set_char_is_tab(i); }, + '\n' => { glyphs.set_char_is_newline(i); }, + _ => {} + } + + // set line break opportunities at whitespace/non-whitespace boundaries. + if prev_is_whitespace { + match ch { + ' ' | '\t' | '\n' => {}, + _ => { + glyphs.set_can_break_before(i, BreakTypeNormal); + prev_is_whitespace = false; + } + } + } else { + match ch { + ' ' | '\t' | '\n' => { + glyphs.set_can_break_before(i, BreakTypeNormal); + prev_is_whitespace = true; + }, + _ => { } + } + } + + i = next; + } + } + pub fn serialize(&self) -> SendableTextRun { SendableTextRun { text: copy self.text,