Skip to content

Commit

Permalink
Compute and store line break information in the glyph storage when cr…
Browse files Browse the repository at this point in the history
…eating text runs.
  • Loading branch information
Brian J. Burg committed Nov 21, 2012
1 parent 2ad1c15 commit 751901d
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/servo-gfx/font.rs
Expand Up @@ -375,6 +375,8 @@ pub trait FontMethods {
range: &Range,
baseline_origin: Point2D<Au>,
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;
Expand Down Expand Up @@ -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),
Expand Down
9 changes: 6 additions & 3 deletions src/servo-gfx/text/glyph.rs
Expand Up @@ -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;
Expand All @@ -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; }
}
}
Expand Down
44 changes: 43 additions & 1 deletion 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;

Expand Down Expand Up @@ -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 {
Expand All @@ -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,
Expand Down

0 comments on commit 751901d

Please sign in to comment.