From fbef2724bf12c2204f0256cebaa5a4d0e8ef45f2 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Fri, 15 Apr 2016 15:44:44 -0700 Subject: [PATCH] Fix up inline context flags during text fragment scanning This fixes two problems that could cause scanned text fragments to end up with incorrect LAST_FRAGMENT_OF_ELEMENT or FIRST_FRAGMENT_OF_ELEMENT flags: 1. If a single unscanned fragment was split into multiple scanned fragments, then all of them would inherit its flags. We need to clear these flags, except for the first and last scanned fragment. 2. When an unscanned fragment generated zero scanned fragments, we correctly called `meld_with_next_inline_fragment` to transfer LAST_FRAGMENT flags to the preceding fragment, but we didn't do anything to transfer FIRST_FRAGMENT flags to the following fragment. We can fix this by calling `meld_with_prev_inline_fragment` on the following fragment. --- components/layout/text.rs | 40 +++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/components/layout/text.rs b/components/layout/text.rs index 41dbb8682f0..da89ae495b8 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; @@ -321,19 +321,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 +379,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) } }