diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2016-04-17 03:31:12 +0530 |
---|---|---|
committer | bors-servo <lbergstrom+bors@mozilla.com> | 2016-04-17 03:31:12 +0530 |
commit | 15e76eb6e2c00ba26b65df73f1954ccada7509cf (patch) | |
tree | 98e0f73d67a8a4a1882c6c485e419668f3b0074c /components/layout/text.rs | |
parent | cc290c6e8a3a8576e57e48dd21fa74aa0e1cf3a9 (diff) | |
parent | 1695d14a9e248edb3f51856d25a35a96861e251e (diff) | |
download | servo-15e76eb6e2c00ba26b65df73f1954ccada7509cf.tar.gz servo-15e76eb6e2c00ba26b65df73f1954ccada7509cf.zip |
Auto merge of #10643 - mbrubeck:empty-span-border, r=pcwalton
Fix handling of borders and padding for empty/stripped inline flows
This forces fragment generation for empty inline flows, if they have borders or padding. Fixes #10533 and #2001. Also includes fixes for other bugs that were uncovered by this change; see the individual commit messages for detailed explanations. r? @pcwalton
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10643)
<!-- Reviewable:end -->
Diffstat (limited to 'components/layout/text.rs')
-rw-r--r-- | components/layout/text.rs | 55 |
1 files changed, 41 insertions, 14 deletions
diff --git a/components/layout/text.rs b/components/layout/text.rs index 41dbb8682f0..22fbeb9ad1a 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -15,7 +15,7 @@ use gfx::font_context::FontContext; use gfx::text::glyph::CharIndex; use gfx::text::text_run::TextRun; use gfx::text::util::{self, CompressionMode}; -use inline::InlineFragments; +use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFragments, LAST_FRAGMENT_OF_ELEMENT}; use range::{Range, RangeIndex}; use std::borrow::ToOwned; use std::collections::LinkedList; @@ -173,6 +173,7 @@ impl TextRunScanner { let mut insertion_point = None; for (fragment_index, in_fragment) in self.clump.iter().enumerate() { + debug!(" flushing {:?}", in_fragment); let mut mapping = RunMapping::new(&run_info_list[..], &run_info, fragment_index); let text; let selection; @@ -239,7 +240,6 @@ impl TextRunScanner { mapping.flush(&mut mappings, &mut run_info, &**text, - insertion_point, compression, text_transform, &mut last_whitespace, @@ -269,7 +269,6 @@ impl TextRunScanner { mapping.flush(&mut mappings, &mut run_info, &**text, - insertion_point, compression, text_transform, &mut last_whitespace, @@ -321,19 +320,26 @@ impl TextRunScanner { // Make new fragments with the runs and adjusted text indices. debug!("TextRunScanner: pushing {} fragment(s)", self.clump.len()); let mut mappings = mappings.into_iter().peekable(); + let mut prev_fragments_to_meld = Vec::new(); + for (logical_offset, old_fragment) in mem::replace(&mut self.clump, LinkedList::new()).into_iter().enumerate() { - loop { + let mut is_first_mapping_of_this_old_fragment = true; + loop { match mappings.peek() { Some(mapping) if mapping.old_fragment_index == logical_offset => {} Some(_) | None => { - if let Some(ref mut last_fragment) = out_fragments.last_mut() { - last_fragment.meld_with_next_inline_fragment(&old_fragment); + if is_first_mapping_of_this_old_fragment { + // There were no mappings for this unscanned fragment. Transfer its + // flags to the previous/next sibling elements instead. + if let Some(ref mut last_fragment) = out_fragments.last_mut() { + last_fragment.meld_with_next_inline_fragment(&old_fragment); + } + prev_fragments_to_meld.push(old_fragment); } break; } }; - let mut mapping = mappings.next().unwrap(); let scanned_run = runs[mapping.text_run_index].clone(); @@ -372,10 +378,31 @@ impl TextRunScanner { let bounding_box_size = bounding_box_for_run_metrics(&new_metrics, writing_mode); new_text_fragment_info.content_size = bounding_box_size; - let new_fragment = old_fragment.transform( + let mut new_fragment = old_fragment.transform( bounding_box_size, SpecificFragmentInfo::ScannedText(new_text_fragment_info)); + let is_last_mapping_of_this_old_fragment = match mappings.peek() { + Some(mapping) if mapping.old_fragment_index == logical_offset => false, + _ => true + }; + + if let Some(ref mut context) = new_fragment.inline_context { + for node in &mut context.nodes { + if !is_last_mapping_of_this_old_fragment { + node.flags.remove(LAST_FRAGMENT_OF_ELEMENT); + } + if !is_first_mapping_of_this_old_fragment { + node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT); + } + } + } + + for prev_fragment in prev_fragments_to_meld.drain(..) { + new_fragment.meld_with_prev_inline_fragment(&prev_fragment); + } + + is_first_mapping_of_this_old_fragment = false; out_fragments.push(new_fragment) } } @@ -578,15 +605,12 @@ impl RunMapping { mappings: &mut Vec<RunMapping>, run_info: &mut RunInfo, text: &str, - insertion_point: Option<CharIndex>, compression: CompressionMode, text_transform: text_transform::T, last_whitespace: &mut bool, start_position: &mut usize, end_position: usize) { - if *start_position == end_position && insertion_point.is_none() { - return; - } + let was_empty = *start_position == end_position; let old_byte_length = run_info.text.len(); *last_whitespace = util::transform_text(&text[(*start_position)..end_position], compression, @@ -605,8 +629,11 @@ impl RunMapping { run_info.character_length = run_info.character_length + character_count; *start_position = end_position; - // Don't flush mappings that contain no characters and no insertion_point. - if character_count == 0 && !self.contains_insertion_point(insertion_point) { + // Don't save mappings that contain only discarded characters. + // (But keep ones that contained no characters to begin with, since they might have been + // generated by an empty flow to draw its borders/padding/insertion point.) + let is_empty = character_count == 0; + if is_empty && !was_empty { return; } |