Skip to content

Commit

Permalink
Convert linebox scanner and other bits to use character indices inste…
Browse files Browse the repository at this point in the history
…ad of string byte offsets. Fix some bugs in set_char_break_before, and remove dead inline tests.
  • Loading branch information
Brian J. Burg committed Nov 21, 2012
1 parent 751901d commit b2f8228
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 105 deletions.
2 changes: 1 addition & 1 deletion src/servo-gfx/font.rs
Expand Up @@ -416,7 +416,7 @@ pub impl Font : FontMethods {
let azglyphs = DVec();
azglyphs.reserve(range.length());

for run.glyphs.iter_glyphs_for_byte_range(range) |_i, glyph| {
for run.glyphs.iter_glyphs_for_char_range(range) |_i, glyph| {
let glyph_advance = glyph.advance();
let glyph_offset = glyph.offset().get_default(Au::zero_point());

Expand Down
31 changes: 9 additions & 22 deletions src/servo-gfx/text/glyph.rs
Expand Up @@ -214,10 +214,12 @@ impl GlyphEntry {
}

// setter methods
#[inline(always)]
pure fn set_char_is_space() -> GlyphEntry {
GlyphEntry(self.value | FLAG_CHAR_IS_SPACE)
}

#[inline(always)]
pure fn set_char_is_tab() -> GlyphEntry {
assert !self.is_simple();
GlyphEntry(self.value | FLAG_CHAR_IS_TAB)
Expand All @@ -229,16 +231,10 @@ impl GlyphEntry {
GlyphEntry(self.value | FLAG_CHAR_IS_NEWLINE)
}

// returns a glyph entry only if the setting had changed.
pure fn set_can_break_before(e: BreakType) -> Option<GlyphEntry> {
let flag = break_enum_to_flag(e);
let mask = (flag as u32) << FLAG_CAN_BREAK_SHIFT;
let toggle = mask ^ (self.value & FLAG_CAN_BREAK_MASK);

match (toggle as bool) {
true => Some(GlyphEntry(self.value ^ toggle)),
false => None
}
#[inline(always)]
pure fn set_can_break_before(e: BreakType) -> GlyphEntry {
let flag = (break_enum_to_flag(e) as u32) << FLAG_CAN_BREAK_SHIFT;
GlyphEntry(self.value | flag)
}

// helper methods
Expand Down Expand Up @@ -599,12 +595,10 @@ impl GlyphStore {
}
}
}

return true;
return true;
}

pure fn iter_glyphs_for_byte_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
warn!("Using deprecated iter_glyphs_for_byte_range API!");
pure fn iter_glyphs_for_char_range(range: &const Range, cb: fn&(uint, GlyphInfo/&) -> bool) {
if range.begin() >= self.entry_buffer.len() {
error!("iter_glyphs_for_range: range.begin beyond length!");
return;
Expand All @@ -614,10 +608,6 @@ impl GlyphStore {
return;
}

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 Expand Up @@ -686,9 +676,6 @@ impl GlyphStore {
fn set_can_break_before(&mut self, i: uint, t: BreakType) {
assert i < self.entry_buffer.len();
let entry = self.entry_buffer[i];
match entry.set_can_break_before(t) {
Some(e) => self.entry_buffer[i] = e,
None => {}
};
self.entry_buffer[i] = entry.set_can_break_before(t);
}
}
92 changes: 11 additions & 81 deletions src/servo-gfx/text/text_run.rs
Expand Up @@ -123,8 +123,6 @@ impl TextRun {
}

fn min_width_for_range(&self, range: &const Range) -> Au {
assert range.is_valid_for_string(self.text);

let mut max_piece_width = Au(0);
for self.iter_indivisible_pieces_for_range(range) |piece_range| {
let metrics = self.font.measure_text(self, piece_range);
Expand All @@ -134,8 +132,6 @@ impl TextRun {
}

fn iter_natural_lines_for_range(&self, range: &const Range, f: fn(&const Range) -> bool) {
assert range.is_valid_for_string(self.text);

let mut clump = Range::new(range.begin(), 0);
let mut in_clump = false;

Expand All @@ -147,8 +143,7 @@ impl TextRun {
(true, false) => { /* chomp whitespace */ }
(true, true) => {
in_clump = false;
// don't include the linebreak 'glyph'
// (we assume there's one GlyphEntry for a newline, and no actual glyphs)
// don't include the linebreak character itself in the clump.
if !f(&const clump) { break }
}
}
Expand All @@ -162,86 +157,21 @@ impl TextRun {
}

fn iter_indivisible_pieces_for_range(&self, range: &const Range, f: fn(&const Range) -> bool) {
assert range.is_valid_for_string(self.text);

let mut clump = Range::new(range.begin(), 0);

loop {
// find next non-whitespace byte index, then clump all whitespace before it.
match str::find_between(self.text, clump.begin(), range.end(), |c| !char::is_whitespace(c)) {
Some(nonws_char_offset) => {
clump.extend_to(nonws_char_offset);
if !f(&const clump) { break }
clump.reset(clump.end(), 0);
},
None => {
// nothing left, flush last piece containing only whitespace
if clump.end() < range.end() {
clump.extend_to(range.end());
f(&const clump);
break;
}
}
};
// extend clump to non-break-before characters.
while clump.end() < range.end()
&& self.glyphs.can_break_before(clump.end()) != BreakTypeNormal {

// find next whitespace byte index, then clump all non-whitespace before it.
match str::find_between(self.text, clump.begin(), range.end(), |c| char::is_whitespace(c)) {
Some(ws_char_offset) => {
clump.extend_to(ws_char_offset);
if !f(&const clump) { break }
clump.reset(clump.end(), 0);
}
None => {
// nothing left, flush last piece containing only non-whitespaces
if clump.end() < range.end() {
clump.extend_to(range.end());
f(&const clump);
break;
}
}
clump.extend_by(1);
}
}
}
}

// this test can't run until LayoutContext is removed as an argument
// to min_width_for_range.
/*
#[test]
fn test_calc_min_break_width() {
fn test_min_width_for_run(text: ~str, width: Au) {
let flib = FontCache();
let font = flib.get_test_font();
let run = TextRun(font, text);
run.min_width_for_range(0, text.len())
}

test_min_width_for_run(~"firecracker", au::from_px(84));
test_min_width_for_run(~"firecracker yumyum", au::from_px(84));
test_min_width_for_run(~"yumyum firecracker", au::from_px(84));
test_min_width_for_run(~"yumyum firecracker yumyum", au::from_px(84));
}
*/

/*#[test]
#[ignore]
fn test_iter_indivisible_pieces() {
fn test_pieces(text: ~str, res: ~[~str]) {
let flib = FontCache();
let font = flib.get_test_font();
let run = TextRun::new(font, copy text);
let mut slices : ~[~str] = ~[];
for run.iter_indivisible_pieces_for_range(Range(0, text.len())) |subrange| {
slices.push(str::slice(text, subrange.begin(), subrange.length()));
// now clump.end() is break-before or range.end()
if !f(&const clump) || clump.end() == range.end() { break; }

// now clump includes one break-before character, or starts from range.end()
clump.reset(clump.end(), 1);
}
assert slices == res;
}
test_pieces(~"firecracker yumyum woopwoop", ~[~"firecracker", ~" ", ~"yumyum", ~" ", ~"woopwoop"]);
test_pieces(~"firecracker yumyum ", ~[~"firecracker", ~" ", ~"yumyum", ~" "]);
test_pieces(~" firecracker yumyum", ~[~" ", ~"firecracker", ~" ", ~"yumyum"]);
test_pieces(~" ", ~[~" "]);
test_pieces(~"", ~[]);
}
*/
2 changes: 1 addition & 1 deletion src/servo/layout/box.rs
Expand Up @@ -295,7 +295,7 @@ impl RenderBox : RenderBoxMethods {
let mut max_line_width: Au = Au(0);
for d.run.iter_natural_lines_for_range(&const d.range) |line_range| {
let mut line_width: Au = Au(0);
for d.run.glyphs.iter_glyphs_for_byte_range(line_range) |_char_i, glyph| {
for d.run.glyphs.iter_glyphs_for_char_range(line_range) |_char_i, glyph| {
line_width += glyph.advance()
}
max_line_width = Au::max(max_line_width, line_width);
Expand Down

0 comments on commit b2f8228

Please sign in to comment.