Skip to content
Permalink
Browse files

Compute and store line break information in the glyph storage when cr…

…eating text runs.
  • Loading branch information
Brian J. Burg
Brian J. Burg committed Nov 21, 2012
1 parent 2ad1c15 commit 751901d39ea8223dec479992b4e41cc7bf4e01e9
Showing with 52 additions and 7 deletions.
  1. +3 −3 src/servo-gfx/font.rs
  2. +6 −3 src/servo-gfx/text/glyph.rs
  3. +43 −1 src/servo-gfx/text/text_run.rs
@@ -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;
@@ -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),
@@ -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; }
}
}
@@ -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,

0 comments on commit 751901d

Please sign in to comment.
You can’t perform that action at this time.