Refactor RenderBox::split_to_width to use TextRanges.

This commit is contained in:
Brian J. Burg 2012-10-18 13:36:44 -07:00
parent 7bfafa5bb8
commit c9ec35fa2d

View file

@ -22,7 +22,7 @@ use layout::debug::BoxedDebugMethods;
use layout::flow::FlowContext; use layout::flow::FlowContext;
use layout::text::TextBoxData; use layout::text::TextBoxData;
use servo_text::text_run; use servo_text::text_run;
use servo_text::text_run::{TextRange, TextRun}; use servo_text::text_run::{MutableTextRange, TextRange, TextRun};
use std::net::url::Url; use std::net::url::Url;
use task::spawn; use task::spawn;
use util::color::Color; use util::color::Color;
@ -185,30 +185,29 @@ impl RenderBox : RenderBoxMethods {
@UnscannedTextBox(*) => fail ~"WAT: shouldn't be an unscanned text box here.", @UnscannedTextBox(*) => fail ~"WAT: shouldn't be an unscanned text box here.",
@TextBox(_,data) => { @TextBox(_,data) => {
let mut i : uint = 0; let mut pieces_processed_count : uint = 0;
let mut remaining_width : au = max_width; let mut remaining_width : au = max_width;
let mut left_offset : uint = data.range.begin(); let left_range = MutableTextRange(data.range.begin(), 0);
let mut left_length : uint = 0; let mut right_range : Option<TextRange> = None;
let mut right_offset : Option<uint> = None; debug!("split_to_width: splitting text box (strlen=%u, range=%?, avail_width=%?)",
let mut right_length : Option<uint> = None; data.run.text.len(), data.range, max_width);
debug!("split_to_width: splitting text box (strlen=%u, off=%u, len=%u, avail_width=%?)",
data.run.text.len(), data.range.begin(), data.range.length(), max_width);
do data.run.iter_indivisible_pieces_for_range(data.range) |piece_range| { do data.run.iter_indivisible_pieces_for_range(data.range) |piece_range| {
debug!("split_to_width: considering range (off=%u, len=%u, remain_width=%?)", debug!("split_to_width: considering piece (range=%?, remain_width=%?)",
piece_range.begin(), piece_range.length(), remaining_width); piece_range, remaining_width);
let metrics = data.run.metrics_for_range(piece_range); let metrics = data.run.metrics_for_range(piece_range);
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(piece_range) { if starts_line && pieces_processed_count == 0
&& data.run.range_is_trimmable_whitespace(piece_range) {
debug!("split_to_width: case=skipping leading trimmable whitespace"); debug!("split_to_width: case=skipping leading trimmable whitespace");
left_offset += piece_range.length(); left_range.shift_by(piece_range.length() as int);
} else { } else {
debug!("split_to_width: case=enlarging span"); debug!("split_to_width: case=enlarging span");
remaining_width -= advance; remaining_width -= advance;
left_length += piece_range.length(); left_range.extend_by(piece_range.length() as int);
} }
} else { /* advance > remaining_width */ } else { /* advance > remaining_width */
should_continue = false; should_continue = false;
@ -217,39 +216,35 @@ impl RenderBox : RenderBoxMethods {
// 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 piece_range.end() < data.range.end() { if piece_range.end() < data.range.end() {
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(piece_range.end()); right_range = Some(TextRange(piece_range.end(),
right_length = Some(data.range.end() - piece_range.end()); data.range.end() - piece_range.end()));
} else { } else {
debug!("split_to_width: case=skipping trimmable trailing whitespace"); debug!("split_to_width: case=skipping trimmable trailing whitespace");
} }
} else if piece_range.begin() < data.range.end() { } else if piece_range.begin() < data.range.end() {
// still things left, create right chunk // still things left, create right chunk
right_offset = Some(piece_range.begin()); right_range = Some(TextRange(piece_range.begin(),
right_length = Some(data.range.end() - piece_range.begin()); data.range.end() - piece_range.begin()));
debug!("split_to_width: case=splitting remainder with right span: (off=%u, len=%u)", debug!("split_to_width: case=splitting remainder with right range=%?",
piece_range.begin(), data.range.end() - piece_range.begin()); right_range);
} }
} }
i += 1; pieces_processed_count += 1;
should_continue should_continue
} }
let left_box = if left_length > 0 { let left_box = if left_range.length() > 0 {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, Some(layout::text::adapt_textbox_with_range(self.d(), data.run, left_range.as_immutable()))
TextRange(left_offset, left_length)))
} else { None }; } else { None };
let right_box = option::map_default(&right_range, None, |range: &TextRange| {
Some(layout::text::adapt_textbox_with_range(self.d(), data.run, *range))
});
match (right_offset, right_length) { return if pieces_processed_count == 1 || left_box.is_none() {
(Some(right_off), Some(right_len)) => { SplitDidNotFit(left_box, right_box)
let right_box = layout::text::adapt_textbox_with_range(self.d(), data.run, } else {
TextRange(right_off, right_len)); SplitDidFit(left_box, right_box)
return if i == 1 || left_box.is_none() {
SplitDidNotFit(left_box, Some(right_box))
} else {
SplitDidFit(left_box, Some(right_box))
}
},
(_, _) => { return SplitDidFit(left_box, None); },
} }
}, },
} }