aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBrian J. Burg <burg@cs.washington.edu>2012-11-21 17:46:33 -0800
committerBrian J. Burg <burg@cs.washington.edu>2012-11-21 17:46:33 -0800
commit29e46273f98023d00876db5e05db1f4c035e4dd1 (patch)
treed05325311fe14b8944c9def0641f072c8dcaf989 /src
parentddb4e5e17dbc93defd85f5a653cbf443650a1610 (diff)
downloadservo-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.rs8
-rw-r--r--src/servo-gfx/text/text_run.rs36
-rw-r--r--src/servo/layout/inline.rs11
-rw-r--r--src/servo/layout/text.rs6
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);