From b2f8228b10867ca0ccd0ce2ee77e919bf6b6804c Mon Sep 17 00:00:00 2001 From: "Brian J. Burg" Date: Wed, 21 Nov 2012 15:51:01 -0800 Subject: [PATCH] Convert linebox scanner and other bits to use character indices instead of string byte offsets. Fix some bugs in set_char_break_before, and remove dead inline tests. --- src/servo-gfx/font.rs | 2 +- src/servo-gfx/text/glyph.rs | 31 ++++-------- src/servo-gfx/text/text_run.rs | 92 ++++------------------------------ src/servo/layout/box.rs | 2 +- 4 files changed, 22 insertions(+), 105 deletions(-) diff --git a/src/servo-gfx/font.rs b/src/servo-gfx/font.rs index d04f065b8a9a..14a1190c1307 100644 --- a/src/servo-gfx/font.rs +++ b/src/servo-gfx/font.rs @@ -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()); diff --git a/src/servo-gfx/text/glyph.rs b/src/servo-gfx/text/glyph.rs index 91011d78774c..97ad9323fa36 100644 --- a/src/servo-gfx/text/glyph.rs +++ b/src/servo-gfx/text/glyph.rs @@ -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) @@ -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 { - 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 @@ -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; @@ -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; } } @@ -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); } } diff --git a/src/servo-gfx/text/text_run.rs b/src/servo-gfx/text/text_run.rs index 550802f084b0..4c41c0bc39c6 100644 --- a/src/servo-gfx/text/text_run.rs +++ b/src/servo-gfx/text/text_run.rs @@ -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); @@ -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; @@ -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 } } } @@ -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(~"", ~[]); } - -*/ diff --git a/src/servo/layout/box.rs b/src/servo/layout/box.rs index b21b983b0a1d..6bb127bd1b3a 100644 --- a/src/servo/layout/box.rs +++ b/src/servo/layout/box.rs @@ -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);