mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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.
This commit is contained in:
parent
b607b3a932
commit
fbef2724bf
1 changed files with 34 additions and 6 deletions
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue