aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/text.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/text.rs')
-rw-r--r--components/layout/text.rs45
1 files changed, 33 insertions, 12 deletions
diff --git a/components/layout/text.rs b/components/layout/text.rs
index 0930389f37f..535c255bc76 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -32,6 +32,7 @@ use style::properties::style_structs;
use style::values::generics::text::LineHeight;
use unicode_bidi as bidi;
use unicode_script::{Script, get_script};
+use xi_unicode::LineBreakLeafIter;
/// Returns the concatenated text of a list of unscanned text fragments.
fn text(fragments: &LinkedList<Fragment>) -> String {
@@ -91,6 +92,15 @@ impl TextRunScanner {
let mut last_whitespace = false;
let mut paragraph_bytes_processed = 0;
+ // The first time we process a text run we will set this
+ // linebreaker. There is no way for the linebreaker to start
+ // with an empty state; you must give it its first input immediately.
+ //
+ // This linebreaker is shared across text runs, so we can know if
+ // there is a break at the beginning of a text run or clump, e.g.
+ // in the case of FooBar<span>Baz</span>
+ let mut linebreaker = None;
+
while !fragments.is_empty() {
// Create a clump.
split_first_fragment_at_newline_if_necessary(&mut fragments);
@@ -109,7 +119,8 @@ impl TextRunScanner {
&mut new_fragments,
&mut paragraph_bytes_processed,
bidi_levels,
- last_whitespace);
+ last_whitespace,
+ &mut linebreaker);
}
debug!("TextRunScanner: complete.");
@@ -129,7 +140,8 @@ impl TextRunScanner {
out_fragments: &mut Vec<Fragment>,
paragraph_bytes_processed: &mut usize,
bidi_levels: Option<&[bidi::Level]>,
- mut last_whitespace: bool)
+ mut last_whitespace: bool,
+ linebreaker: &mut Option<LineBreakLeafIter>)
-> bool {
debug!("TextRunScanner: flushing {} fragments in range", self.clump.len());
@@ -309,22 +321,26 @@ impl TextRunScanner {
flags: flags,
};
- // FIXME(https://github.com/rust-lang/rust/issues/23338)
- run_info_list.into_iter().map(|run_info| {
+ let mut result = Vec::with_capacity(run_info_list.len());
+ for run_info in run_info_list {
let mut options = options;
options.script = run_info.script;
if run_info.bidi_level.is_rtl() {
options.flags.insert(ShapingFlags::RTL_FLAG);
}
let mut font = fontgroup.fonts.get(run_info.font_index).unwrap().borrow_mut();
- ScannedTextRun {
- run: Arc::new(TextRun::new(&mut *font,
- run_info.text,
- &options,
- run_info.bidi_level)),
+
+ let (run, break_at_zero) = TextRun::new(&mut *font,
+ run_info.text,
+ &options,
+ run_info.bidi_level,
+ linebreaker);
+ result.push((ScannedTextRun {
+ run: Arc::new(run),
insertion_point: run_info.insertion_point,
- }
- }).collect::<Vec<_>>()
+ }, break_at_zero))
+ }
+ result
};
// Make new fragments with the runs and adjusted text indices.
@@ -351,12 +367,17 @@ impl TextRunScanner {
}
};
let mapping = mappings.next().unwrap();
- let scanned_run = runs[mapping.text_run_index].clone();
+ let (scanned_run, break_at_zero) = runs[mapping.text_run_index].clone();
let mut byte_range = Range::new(ByteIndex(mapping.byte_range.begin() as isize),
ByteIndex(mapping.byte_range.length() as isize));
let mut flags = ScannedTextFlags::empty();
+ if !break_at_zero && mapping.byte_range.begin() == 0 {
+ // If this is the first segment of the text run,
+ // and the text run doesn't break at zero, suppress line breaks
+ flags.insert(ScannedTextFlags::SUPPRESS_LINE_BREAK_BEFORE)
+ }
let text_size = old_fragment.border_box.size;
let requires_line_break_afterward_if_wrapping_on_newlines =