diff options
author | Brian J. Burg <burg@cs.washington.edu> | 2012-11-21 17:46:33 -0800 |
---|---|---|
committer | Brian J. Burg <burg@cs.washington.edu> | 2012-11-21 17:46:33 -0800 |
commit | 29e46273f98023d00876db5e05db1f4c035e4dd1 (patch) | |
tree | d05325311fe14b8944c9def0641f072c8dcaf989 /src | |
parent | ddb4e5e17dbc93defd85f5a653cbf443650a1610 (diff) | |
download | servo-29e46273f98023d00876db5e05db1f4c035e4dd1.tar.gz servo-29e46273f98023d00876db5e05db1f4c035e4dd1.zip |
Finish conversion to using only character ranges. We don't crash on multi-byte characters any more.
Diffstat (limited to 'src')
-rw-r--r-- | src/servo-gfx/text/glyph.rs | 8 | ||||
-rw-r--r-- | src/servo-gfx/text/text_run.rs | 36 | ||||
-rw-r--r-- | src/servo/layout/inline.rs | 11 | ||||
-rw-r--r-- | src/servo/layout/text.rs | 6 |
4 files changed, 31 insertions, 30 deletions
diff --git a/src/servo-gfx/text/glyph.rs b/src/servo-gfx/text/glyph.rs index 97ad9323fa3..f698d520f92 100644 --- a/src/servo-gfx/text/glyph.rs +++ b/src/servo-gfx/text/glyph.rs @@ -631,12 +631,8 @@ impl GlyphStore { } pure fn char_is_newline(i: uint) -> bool { - if i >= self.entry_buffer.len() { - error!("char_is_newline: beyond entry buffer!"); - false - } else { - self.entry_buffer[i].char_is_newline() - } + assert i < self.entry_buffer.len(); + self.entry_buffer[i].char_is_newline() } pure fn is_ligature_start(i: uint) -> bool { diff --git a/src/servo-gfx/text/text_run.rs b/src/servo-gfx/text/text_run.rs index 4c41c0bc39c..60acae0d6b5 100644 --- a/src/servo-gfx/text/text_run.rs +++ b/src/servo-gfx/text/text_run.rs @@ -59,15 +59,16 @@ impl TextRun { 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 byte_i = 0u; + let mut char_j = 0u; let mut prev_is_whitespace = false; - while i < text.len() { - let {ch, next} = str::char_range_at(text, i); + while byte_i < text.len() { + let {ch, next} = str::char_range_at(text, byte_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); }, + ' ' => { glyphs.set_char_is_space(char_j); }, + '\t' => { glyphs.set_char_is_tab(char_j); }, + '\n' => { glyphs.set_char_is_newline(char_j); }, _ => {} } @@ -76,21 +77,22 @@ impl TextRun { match ch { ' ' | '\t' | '\n' => {}, _ => { - glyphs.set_can_break_before(i, BreakTypeNormal); + glyphs.set_can_break_before(char_j, BreakTypeNormal); prev_is_whitespace = false; } } } else { match ch { ' ' | '\t' | '\n' => { - glyphs.set_can_break_before(i, BreakTypeNormal); + glyphs.set_can_break_before(char_j, BreakTypeNormal); prev_is_whitespace = true; }, _ => { } } } - i = next; + byte_i = next; + char_j += 1; } } @@ -102,18 +104,14 @@ impl TextRun { } } + pure fn char_len() -> uint { self.glyphs.entry_buffer.len() } pure fn glyphs(&self) -> &self/GlyphStore { &self.glyphs } pure fn range_is_trimmable_whitespace(&self, range: &const Range) -> bool { - let mut i = range.begin(); - while i < range.end() { - // jump i to each new char - let {ch, next} = str::char_range_at(self.text, i); - match ch { - ' ' | '\t' | '\r' => {}, - _ => { return false; } - } - i = next; + for range.eachi |i| { + if !self.glyphs.char_is_space(i) && + !self.glyphs.char_is_tab(i) && + !self.glyphs.char_is_newline(i) { return false; } } return true; } @@ -124,7 +122,9 @@ impl TextRun { fn min_width_for_range(&self, range: &const Range) -> Au { let mut max_piece_width = Au(0); + debug!("iterating outer range %?", range); for self.iter_indivisible_pieces_for_range(range) |piece_range| { + debug!("iterated on %?", piece_range); let metrics = self.font.measure_text(self, piece_range); max_piece_width = Au::max(max_piece_width, metrics.advance_width); } diff --git a/src/servo/layout/inline.rs b/src/servo/layout/inline.rs index 4f11841894a..f1885e8b6ac 100644 --- a/src/servo/layout/inline.rs +++ b/src/servo/layout/inline.rs @@ -246,7 +246,7 @@ priv impl TextRunScanner { debug!("TextRunScanner: pushing single text box in range: %?", self.clump); let new_box = layout::text::adapt_textbox_with_range(old_box.d(), run, - &const Range::new(0, run.text.len())); + &const Range::new(0, run.char_len())); out_boxes.push(new_box); }, (false, true) => { @@ -263,14 +263,15 @@ priv impl TextRunScanner { transform_text(in_boxes[idx].raw_text(), compression) }); - // next, concatenate all of the transformed strings together, saving the new text indices - - // TODO(Issue #118): use a rope, simply give ownership of nonzero strs to rope + // next, concatenate all of the transformed strings together, saving the new char indices let mut run_str : ~str = ~""; let new_ranges : DVec<Range> = DVec(); + let mut char_total = 0u; for uint::range(0, transformed_strs.len()) |i| { - new_ranges.push(Range::new(run_str.len(), transformed_strs[i].len())); + let added_chars = str::char_len(transformed_strs[i]); + new_ranges.push(Range::new(char_total, added_chars)); str::push_str(&mut run_str, transformed_strs[i]); + char_total += added_chars; } // create the run, then make new boxes with the run and adjusted text indices diff --git a/src/servo/layout/text.rs b/src/servo/layout/text.rs index 42ae528b34f..1e0029a9bfe 100644 --- a/src/servo/layout/text.rs +++ b/src/servo/layout/text.rs @@ -19,8 +19,12 @@ pub fn TextBoxData(run: @TextRun, range: &const Range) -> TextBoxData { pub fn adapt_textbox_with_range(box_data: &RenderBoxData, run: @TextRun, range: &const Range) -> @RenderBox { + assert range.begin() < run.char_len(); + assert range.end() <= run.char_len(); + assert range.length() > 0; + debug!("Creating textbox with span: (strlen=%u, off=%u, len=%u) of textrun: %s", - run.text.len(), range.begin(), range.length(), run.text); + run.char_len(), range.begin(), range.length(), run.text); let new_box_data = copy *box_data; let new_text_data = TextBoxData(run, range); let metrics = run.metrics_for_range(range); |