aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/text.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-04-17 03:31:12 +0530
committerbors-servo <lbergstrom+bors@mozilla.com>2016-04-17 03:31:12 +0530
commit15e76eb6e2c00ba26b65df73f1954ccada7509cf (patch)
tree98e0f73d67a8a4a1882c6c485e419668f3b0074c /components/layout/text.rs
parentcc290c6e8a3a8576e57e48dd21fa74aa0e1cf3a9 (diff)
parent1695d14a9e248edb3f51856d25a35a96861e251e (diff)
downloadservo-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.rs55
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;
}