New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't mark the first/last fragment of an {ib} split as FIRST/LAST_FRAGMENT_OF_ELEMENT. #14035
Changes from all commits
File filter...
Jump to…
| @@ -29,7 +29,7 @@ use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; | ||
| use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo}; | ||
| use fragment::WhitespaceStrippingResult; | ||
| use gfx::display_list::OpaqueNode; | ||
| use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags}; | ||
| use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow}; | ||
| use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT}; | ||
| use linked_list::prepend_from; | ||
| use list_item::{ListItemFlow, ListStyleTypeContent}; | ||
| @@ -159,6 +159,32 @@ pub struct InlineBlockSplit { | ||
| pub flow: FlowRef, | ||
| } | ||
|
|
||
| impl InlineBlockSplit { | ||
| /// Flushes the given accumulator to the new split and makes a new accumulator to hold any | ||
| /// subsequent fragments. | ||
| fn new<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>(fragment_accumulator: &mut InlineFragmentsAccumulator, | ||
| node: &ConcreteThreadSafeLayoutNode, | ||
| style_context: &SharedStyleContext, | ||
| flow: FlowRef) | ||
| -> InlineBlockSplit { | ||
| fragment_accumulator.enclosing_node.as_mut().expect( | ||
| "enclosing_node is None; Are {ib} splits being generated outside of an inline node?" | ||
| ).flags.remove(LAST_FRAGMENT_OF_ELEMENT); | ||
|
|
||
| let split = InlineBlockSplit { | ||
| predecessors: mem::replace( | ||
| fragment_accumulator, | ||
| InlineFragmentsAccumulator::from_inline_node( | ||
| node, style_context)).to_intermediate_inline_fragments(), | ||
| flow: flow, | ||
| }; | ||
|
|
||
| fragment_accumulator.enclosing_node.as_mut().unwrap().flags.remove(FIRST_FRAGMENT_OF_ELEMENT); | ||
|
|
||
| split | ||
| } | ||
| } | ||
|
|
||
| /// Holds inline fragments and absolute descendants. | ||
| #[derive(Clone)] | ||
| pub struct IntermediateInlineFragments { | ||
| @@ -192,8 +218,14 @@ struct InlineFragmentsAccumulator { | ||
| /// The list of fragments. | ||
| fragments: IntermediateInlineFragments, | ||
|
|
||
| /// Whether we've created a range to enclose all the fragments. This will be Some() if the | ||
| /// outer node is an inline and None otherwise. | ||
| /// Information about the inline box directly enclosing the fragments being gathered, if any. | ||
| /// | ||
| /// `inline::InlineFragmentNodeInfo` also stores flags indicating whether a fragment is the | ||
| /// first and/or last of the corresponding inline box. This `InlineFragmentsAccumulator` may | ||
| /// represent only one side of an {ib} split, so we store these flags as if it represented only | ||
| /// one fragment. `to_intermediate_inline_fragments` later splits this hypothetical fragment | ||
| /// into pieces, leaving the `FIRST_FRAGMENT_OF_ELEMENT` and `LAST_FRAGMENT_OF_ELEMENT` flags, | ||
| /// if present, on the first and last fragments of the output. | ||
| enclosing_node: Option<InlineFragmentNodeInfo>, | ||
|
|
||
| /// Restyle damage to use for fragments created in this node. | ||
| @@ -222,7 +254,7 @@ impl InlineFragmentsAccumulator { | ||
| pseudo: node.get_pseudo_element_type().strip(), | ||
| style: node.style(style_context), | ||
| selected_style: node.selected_style(), | ||
| flags: InlineFragmentNodeFlags::empty(), | ||
| flags: FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT, | ||
Permutatrix
Author
Contributor
|
||
| }), | ||
| bidi_control_chars: None, | ||
| restyle_damage: node.restyle_damage(), | ||
| @@ -245,21 +277,23 @@ impl InlineFragmentsAccumulator { | ||
| bidi_control_chars, | ||
| restyle_damage, | ||
| } = self; | ||
| if let Some(enclosing_node) = enclosing_node { | ||
| if let Some(mut enclosing_node) = enclosing_node { | ||
| let fragment_count = fragments.fragments.len(); | ||
| for (index, fragment) in fragments.fragments.iter_mut().enumerate() { | ||
| let mut enclosing_node = enclosing_node.clone(); | ||
| if index == 0 { | ||
| enclosing_node.flags.insert(FIRST_FRAGMENT_OF_ELEMENT) | ||
| if index != 0 { | ||
| enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT) | ||
| } | ||
| if index == fragment_count - 1 { | ||
| enclosing_node.flags.insert(LAST_FRAGMENT_OF_ELEMENT) | ||
| if index != fragment_count - 1 { | ||
| enclosing_node.flags.remove(LAST_FRAGMENT_OF_ELEMENT) | ||
| } | ||
| fragment.add_inline_context_style(enclosing_node); | ||
| } | ||
|
|
||
| // Control characters are later discarded in transform_text, so they don't affect the | ||
| // is_first/is_last styles above. | ||
| enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT); | ||
|
|
||
| if let Some((start, end)) = bidi_control_chars { | ||
| fragments.fragments.push_front( | ||
| control_chars_to_fragment(&enclosing_node, start, restyle_damage)); | ||
| @@ -715,14 +749,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> | ||
| } = split; | ||
| fragment_accumulator.push_all(predecessors); | ||
|
|
||
| let split = InlineBlockSplit { | ||
| predecessors: mem::replace( | ||
| fragment_accumulator, | ||
| InlineFragmentsAccumulator::from_inline_node( | ||
| node, self.style_context())).to_intermediate_inline_fragments(), | ||
| flow: kid_flow, | ||
| }; | ||
| opt_inline_block_splits.push_back(split) | ||
| opt_inline_block_splits.push_back( | ||
| InlineBlockSplit::new(fragment_accumulator, node, self.style_context(), kid_flow)); | ||
| } | ||
| } | ||
|
|
||
| @@ -749,17 +777,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> | ||
| ConstructionResult::None => {} | ||
| ConstructionResult::Flow(flow, kid_abs_descendants) => { | ||
| if !flow::base(&*flow).flags.contains(IS_ABSOLUTELY_POSITIONED) { | ||
| // {ib} split. Flush the accumulator to our new split and make a new | ||
| // accumulator to hold any subsequent fragments we come across. | ||
| let split = InlineBlockSplit { | ||
| predecessors: | ||
| mem::replace( | ||
| &mut fragment_accumulator, | ||
| InlineFragmentsAccumulator::from_inline_node( | ||
| node, self.style_context())).to_intermediate_inline_fragments(), | ||
| flow: flow, | ||
| }; | ||
| opt_inline_block_splits.push_back(split); | ||
| opt_inline_block_splits.push_back(InlineBlockSplit::new( | ||
| &mut fragment_accumulator, node, self.style_context(), flow)); | ||
| abs_descendants.push_descendants(kid_abs_descendants); | ||
| } else { | ||
| // Push the absolutely-positioned kid as an inline containing block. | ||
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This looks good to me, but I wonder if there's a way to organize this so this doesn't start with this flags. It feels weird to use these flags here since we always remove them in
to_intermediate_inline_fragments.Maybe keeping in the accumulator something like
saw_ib_splitflag or similar, and don't insert the flags in that case?