mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
More TextRange refactoring.
This commit is contained in:
parent
f9040afada
commit
efca6fedfc
2 changed files with 31 additions and 32 deletions
|
@ -193,41 +193,41 @@ impl RenderBox : RenderBoxMethods {
|
||||||
let mut right_length : Option<uint> = None;
|
let mut right_length : Option<uint> = None;
|
||||||
debug!("split_to_width: splitting text box (strlen=%u, off=%u, len=%u, avail_width=%?)",
|
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);
|
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=%?)",
|
debug!("split_to_width: considering range (off=%u, len=%u, remain_width=%?)",
|
||||||
off, len, remaining_width);
|
subrange.begin(), subrange.length(), remaining_width);
|
||||||
let metrics = data.run.metrics_for_range(TextRange(off, len));
|
let metrics = data.run.metrics_for_range(subrange);
|
||||||
let advance = metrics.advance_width;
|
let advance = metrics.advance_width;
|
||||||
let should_continue : bool;
|
let should_continue : bool;
|
||||||
|
|
||||||
if advance <= remaining_width {
|
if advance <= remaining_width {
|
||||||
should_continue = true;
|
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");
|
debug!("split_to_width: case=skipping leading trimmable whitespace");
|
||||||
left_offset += len;
|
left_offset += subrange.length();
|
||||||
} else {
|
} else {
|
||||||
debug!("split_to_width: case=enlarging span");
|
debug!("split_to_width: case=enlarging span");
|
||||||
remaining_width -= advance;
|
remaining_width -= advance;
|
||||||
left_length += len;
|
left_length += subrange.length();
|
||||||
}
|
}
|
||||||
} else { /* advance > remaining_width */
|
} else { /* advance > remaining_width */
|
||||||
should_continue = false;
|
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 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");
|
debug!("split_to_width: case=skipping trimmable trailing whitespace, then split remainder");
|
||||||
right_offset = Some(off + len);
|
right_offset = Some(subrange.end());
|
||||||
right_length = Some((data.offset + data.length) - (off + len));
|
right_length = Some((data.offset + data.length) - subrange.end());
|
||||||
} else {
|
} else {
|
||||||
debug!("split_to_width: case=skipping trimmable trailing whitespace");
|
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
|
// still things left, create right chunk
|
||||||
right_offset = Some(off);
|
right_offset = Some(subrange.begin());
|
||||||
right_length = Some((data.offset + data.length) - off);
|
right_length = Some((data.offset + data.length) - subrange.begin());
|
||||||
debug!("split_to_width: case=splitting remainder with right span: (off=%u, len=%u)",
|
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;
|
i += 1;
|
||||||
|
@ -293,12 +293,12 @@ impl RenderBox : RenderBoxMethods {
|
||||||
// factor in min/pref widths of any text runs that it owns.
|
// factor in min/pref widths of any text runs that it owns.
|
||||||
TextBox(_,d) => {
|
TextBox(_,d) => {
|
||||||
let mut max_line_width: au = au(0);
|
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 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);
|
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()
|
line_width += glyph.advance()
|
||||||
};
|
};
|
||||||
max_line_width = au::max(max_line_width, line_width);
|
max_line_width = au::max(max_line_width, line_width);
|
||||||
|
|
|
@ -139,14 +139,14 @@ pub fn deserialize(cache: @FontCache, run: &SendableTextRun) -> @TextRun {
|
||||||
|
|
||||||
trait TextRunMethods {
|
trait TextRunMethods {
|
||||||
pure fn glyphs(&self) -> &self/GlyphStore;
|
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.
|
// TODO: needs to take box style as argument, or move to TextBox.
|
||||||
// see Gecko's IsTrimmableSpace methods for details.
|
// see Gecko's IsTrimmableSpace methods for details.
|
||||||
pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool;
|
pure fn range_is_trimmable_whitespace(&self, range: TextRange) -> bool;
|
||||||
|
|
||||||
fn metrics_for_range(&self, range: TextRange) -> RunMetrics;
|
fn metrics_for_range(&self, range: TextRange) -> RunMetrics;
|
||||||
fn min_width_for_range(&self, range: TextRange) -> au;
|
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 {
|
impl TextRun : TextRunMethods {
|
||||||
|
@ -174,14 +174,14 @@ impl TextRun : TextRunMethods {
|
||||||
assert range.is_valid_for_string(self.text);
|
assert range.is_valid_for_string(self.text);
|
||||||
|
|
||||||
let mut max_piece_width = au(0);
|
let mut max_piece_width = au(0);
|
||||||
for self.iter_indivisible_pieces_for_range(range) |piece_offset, piece_len| {
|
for self.iter_indivisible_pieces_for_range(range) |piece_range| {
|
||||||
let metrics = self.font.measure_text(self, piece_offset, piece_len);
|
let metrics = self.font.measure_text(self, piece_range.begin(), piece_range.length());
|
||||||
max_piece_width = au::max(max_piece_width, metrics.advance_width);
|
max_piece_width = au::max(max_piece_width, metrics.advance_width);
|
||||||
}
|
}
|
||||||
return max_piece_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);
|
assert range.is_valid_for_string(self.text);
|
||||||
|
|
||||||
let clump = MutableTextRange(range.begin(), 0);
|
let clump = MutableTextRange(range.begin(), 0);
|
||||||
|
@ -197,7 +197,7 @@ impl TextRun : TextRunMethods {
|
||||||
in_clump = false;
|
in_clump = false;
|
||||||
// don't include the linebreak 'glyph'
|
// don't include the linebreak 'glyph'
|
||||||
// (we assume there's one GlyphEntry for a newline, and no actual glyphs)
|
// (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
|
// flush any remaining chars as a line
|
||||||
if in_clump {
|
if in_clump {
|
||||||
clump.extend_to(range.end());
|
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);
|
assert range.is_valid_for_string(self.text);
|
||||||
|
|
||||||
let clump = MutableTextRange(range.begin(), 0);
|
let clump = MutableTextRange(range.begin(), 0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// find next non-whitespace byte index, then clump all whitespace before it.
|
// find next non-whitespace byte index, then clump all whitespace before it.
|
||||||
if clump.end() == range.end() { break }
|
if clump.end() == range.end() { break }
|
||||||
match str::find_from(self.text, clump.begin(), |c| !char::is_whitespace(c)) {
|
match str::find_from(self.text, clump.begin(), |c| !char::is_whitespace(c)) {
|
||||||
Some(nonws_char_offset) => {
|
Some(nonws_char_offset) => {
|
||||||
clump.extend_to(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);
|
clump.reset(clump.end(), 0);
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// nothing left, flush last piece containing only whitespace
|
// nothing left, flush last piece containing only whitespace
|
||||||
if clump.end() < range.end() {
|
if clump.end() < range.end() {
|
||||||
clump.extend_to(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)) {
|
match str::find_from(self.text, clump.begin(), |c| char::is_whitespace(c)) {
|
||||||
Some(ws_char_offset) => {
|
Some(ws_char_offset) => {
|
||||||
clump.extend_to(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);
|
clump.reset(clump.end(), 0);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// nothing left, flush last piece containing only non-whitespaces
|
// nothing left, flush last piece containing only non-whitespaces
|
||||||
if clump.end() < range.end() {
|
if clump.end() < range.end() {
|
||||||
clump.extend_to(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 font = flib.get_test_font();
|
||||||
let run = TextRun(font, copy text);
|
let run = TextRun(font, copy text);
|
||||||
let mut slices : ~[~str] = ~[];
|
let mut slices : ~[~str] = ~[];
|
||||||
for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |offset, length| {
|
for run.iter_indivisible_pieces_for_range(TextRange(0, text.len())) |subrange| {
|
||||||
slices.push(str::slice(text, offset, length));
|
slices.push(str::slice(text, subrange.begin(), subrange.length()));
|
||||||
}
|
}
|
||||||
assert slices == res;
|
assert slices == res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue