More TextRange refactoring.

This commit is contained in:
Brian J. Burg 2012-10-18 11:31:58 -07:00
parent f9040afada
commit efca6fedfc
2 changed files with 31 additions and 32 deletions

View file

@ -193,41 +193,41 @@ impl RenderBox : RenderBoxMethods {
let mut right_length : Option<uint> = None;
debug!("split_to_width: splitting text box (strlen=%u, off=%u, len=%u, avail_width=%?)",
data.run.text.len(), data.offset, data.length, max_width);
do data.run.iter_indivisible_pieces_for_range(TextRange(data.offset, data.length)) |off, len| {
do data.run.iter_indivisible_pieces_for_range(TextRange(data.offset, data.length)) |subrange| {
debug!("split_to_width: considering range (off=%u, len=%u, remain_width=%?)",
off, len, remaining_width);
let metrics = data.run.metrics_for_range(TextRange(off, len));
subrange.begin(), subrange.length(), remaining_width);
let metrics = data.run.metrics_for_range(subrange);
let advance = metrics.advance_width;
let should_continue : bool;
if advance <= remaining_width {
should_continue = true;
if starts_line && i == 0 && data.run.range_is_trimmable_whitespace(TextRange(off, len)) {
if starts_line && i == 0 && data.run.range_is_trimmable_whitespace(subrange) {
debug!("split_to_width: case=skipping leading trimmable whitespace");
left_offset += len;
left_offset += subrange.length();
} else {
debug!("split_to_width: case=enlarging span");
remaining_width -= advance;
left_length += len;
left_length += subrange.length();
}
} else { /* advance > remaining_width */
should_continue = false;
if data.run.range_is_trimmable_whitespace(TextRange(off, len)) {
if data.run.range_is_trimmable_whitespace(subrange) {
// if there are still things after the trimmable whitespace, create right chunk
if off + len < data.offset + data.length {
if subrange.end() < data.offset + data.length {
debug!("split_to_width: case=skipping trimmable trailing whitespace, then split remainder");
right_offset = Some(off + len);
right_length = Some((data.offset + data.length) - (off + len));
right_offset = Some(subrange.end());
right_length = Some((data.offset + data.length) - subrange.end());
} else {
debug!("split_to_width: case=skipping trimmable trailing whitespace");
}
} else if off < data.length + data.offset {
} else if subrange.begin() < data.length + data.offset {
// still things left, create right chunk
right_offset = Some(off);
right_length = Some((data.offset + data.length) - off);
right_offset = Some(subrange.begin());
right_length = Some((data.offset + data.length) - subrange.begin());
debug!("split_to_width: case=splitting remainder with right span: (off=%u, len=%u)",
off, (data.offset + data.length) - off);
subrange.begin(), (data.offset + data.length) - subrange.begin());
}
}
i += 1;
@ -293,12 +293,12 @@ impl RenderBox : RenderBoxMethods {
// factor in min/pref widths of any text runs that it owns.
TextBox(_,d) => {
let mut max_line_width: au = au(0);
for d.run.iter_natural_lines_for_range(TextRange(d.offset, d.length)) |line_offset, line_len| {
for d.run.iter_natural_lines_for_range(TextRange(d.offset, d.length)) |line_range| {
// if the line is a single newline, then len will be zero
if line_len == 0 { loop }
if line_range.length() == 0 { loop }
let mut line_width: au = au(0);
do d.run.glyphs.iter_glyphs_for_range(line_offset, line_len) |_char_i, glyph| {
do d.run.glyphs.iter_glyphs_for_range(line_range.begin(), line_range.length()) |_char_i, glyph| {
line_width += glyph.advance()
};
max_line_width = au::max(max_line_width, line_width);

View file

@ -139,14 +139,14 @@ pub fn deserialize(cache: @FontCache, run: &SendableTextRun) -> @TextRun {
trait TextRunMethods {
pure fn glyphs(&self) -> &self/GlyphStore;
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn(uint, uint) -> bool);
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool);
// TODO: needs to take box style as argument, or move to TextBox.
// see Gecko's IsTrimmableSpace methods for details.
pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool;
fn metrics_for_range(&self, range: TextRange) -> RunMetrics;
fn min_width_for_range(&self, range: TextRange) -> au;
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn(uint, uint) -> bool);
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn&(TextRange) -> bool);
}
impl TextRun : TextRunMethods {
@ -174,14 +174,14 @@ impl TextRun : TextRunMethods {
assert range.is_valid_for_string(self.text);
let mut max_piece_width = au(0);
for self.iter_indivisible_pieces_for_range(range) |piece_offset, piece_len| {
let metrics = self.font.measure_text(self, piece_offset, piece_len);
for self.iter_indivisible_pieces_for_range(range) |piece_range| {
let metrics = self.font.measure_text(self, piece_range.begin(), piece_range.length());
max_piece_width = au::max(max_piece_width, metrics.advance_width);
}
return max_piece_width;
}
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn(uint, uint) -> bool) {
fn iter_natural_lines_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) {
assert range.is_valid_for_string(self.text);
let clump = MutableTextRange(range.begin(), 0);
@ -197,7 +197,7 @@ impl TextRun : TextRunMethods {
in_clump = false;
// don't include the linebreak 'glyph'
// (we assume there's one GlyphEntry for a newline, and no actual glyphs)
if !f(clump.begin(), clump.length()) { break }
if !f(clump.as_immutable()) { break }
}
}
}
@ -205,29 +205,28 @@ impl TextRun : TextRunMethods {
// flush any remaining chars as a line
if in_clump {
clump.extend_to(range.end());
f(clump.begin(), clump.length());
f(clump.as_immutable());
}
}
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn(uint, uint) -> bool) {
fn iter_indivisible_pieces_for_range(&self, range: TextRange, f: fn(TextRange) -> bool) {
assert range.is_valid_for_string(self.text);
let clump = MutableTextRange(range.begin(), 0);
loop {
// find next non-whitespace byte index, then clump all whitespace before it.
if clump.end() == range.end() { break }
match str::find_from(self.text, clump.begin(), |c| !char::is_whitespace(c)) {
Some(nonws_char_offset) => {
clump.extend_to(nonws_char_offset);
if !f(clump.begin(), clump.length()) { break }
if !f(clump.as_immutable()) { 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(clump.begin(), clump.length());
f(clump.as_immutable());
}
}
};
@ -237,14 +236,14 @@ impl TextRun : TextRunMethods {
match str::find_from(self.text, clump.begin(), |c| char::is_whitespace(c)) {
Some(ws_char_offset) => {
clump.extend_to(ws_char_offset);
if !f(clump.begin(), clump.length()) { break }
if !f(clump.as_immutable()) { 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(clump.begin(), clump.length());
f(clump.as_immutable());
}
}
}
@ -292,8 +291,8 @@ fn test_iter_indivisible_pieces() {
let font = flib.get_test_font();
let run = TextRun(font, copy text);
let mut slices : ~[~str] = ~[];
for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |offset, length| {
slices.push(str::slice(text, offset, length));
for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |subrange| {
slices.push(str::slice(text, subrange.begin(), subrange.length()));
}
assert slices == res;
}