Skip to content
Permalink
Browse files

Finish conversion to using only character ranges. We don't crash on m…

…ulti-byte characters any more.
  • Loading branch information
Brian J. Burg
Brian J. Burg committed Nov 22, 2012
1 parent ddb4e5e commit 29e46273f98023d00876db5e05db1f4c035e4dd1
Showing with 31 additions and 30 deletions.
  1. +2 −6 src/servo-gfx/text/glyph.rs
  2. +18 −18 src/servo-gfx/text/text_run.rs
  3. +6 −5 src/servo/layout/inline.rs
  4. +5 −1 src/servo/layout/text.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 {
@@ -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);
}
@@ -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
@@ -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);

0 comments on commit 29e4627

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