diff options
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r-- | components/layout/construct.rs | 101 |
1 files changed, 69 insertions, 32 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 0b489459352..086b323e878 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -25,14 +25,16 @@ use flow::{MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; +use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM}; 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}; +use model::Direction; use multicol::{MulticolColumnFlow, MulticolFlow}; use parallel; use script_layout_interface::{LayoutElementType, LayoutNodeType, is_image_data}; @@ -159,6 +161,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 +220,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 +256,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, }), bidi_control_chars: None, restyle_damage: node.restyle_damage(), @@ -245,21 +279,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 +751,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 +779,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. @@ -1928,9 +1949,16 @@ impl Legalizer { &[PseudoElement::ServoAnonymousBlock], SpecificFragmentInfo::Generic, BlockFlow::from_fragment); - flow::mut_base(FlowRef::deref_mut(&mut - block_wrapper)).flags - .insert(MARGINS_CANNOT_COLLAPSE); + { + let flag = if parent.as_flex().main_mode() == Direction::Inline { + IS_INLINE_FLEX_ITEM + } else { + IS_BLOCK_FLEX_ITEM + }; + let mut block = FlowRef::deref_mut(&mut block_wrapper).as_mut_block(); + block.base.flags.insert(MARGINS_CANNOT_COLLAPSE); + block.fragment.flags.insert(flag); + } block_wrapper.add_new_child((*child).clone()); block_wrapper.finish(); parent.add_new_child(block_wrapper); @@ -1938,7 +1966,16 @@ impl Legalizer { } (FlowClass::Flex, _) => { - flow::mut_base(FlowRef::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE); + { + let flag = if parent.as_flex().main_mode() == Direction::Inline { + IS_INLINE_FLEX_ITEM + } else { + IS_BLOCK_FLEX_ITEM + }; + let mut block = FlowRef::deref_mut(child).as_mut_block(); + block.base.flags.insert(MARGINS_CANNOT_COLLAPSE); + block.fragment.flags.insert(flag); + } parent.add_new_child((*child).clone()); true } |