diff options
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r-- | components/layout/construct.rs | 331 |
1 files changed, 228 insertions, 103 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 807bac242cc..bbbd9287e13 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -51,6 +51,7 @@ use style::computed_values::float::T as Float; use style::computed_values::list_style_position::T as ListStylePosition; use style::computed_values::position::T as Position; use style::context::SharedStyleContext; +use style::dom::TElement; use style::logical_geometry::Direction; use style::properties::ComputedValues; use style::properties::longhands::list_style_image; @@ -170,11 +171,12 @@ pub struct InlineBlockSplit { 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 { + 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(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT); @@ -183,7 +185,9 @@ impl InlineBlockSplit { predecessors: mem::replace( fragment_accumulator, InlineFragmentsAccumulator::from_inline_node( - node, style_context)).to_intermediate_inline_fragments(style_context), + node, + style_context, + )).to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context), flow: flow, }; @@ -280,8 +284,13 @@ impl InlineFragmentsAccumulator { self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants); } - fn to_intermediate_inline_fragments(self, context: &SharedStyleContext) - -> IntermediateInlineFragments { + fn to_intermediate_inline_fragments<N>( + self, + context: &SharedStyleContext, + ) -> IntermediateInlineFragments + where + N: ThreadSafeLayoutNode, + { let InlineFragmentsAccumulator { mut fragments, enclosing_node, @@ -308,9 +317,21 @@ impl InlineFragmentsAccumulator { if let Some((start, end)) = bidi_control_chars { fragments.fragments.push_front( - control_chars_to_fragment(&enclosing_node, context, start, restyle_damage)); + control_chars_to_fragment::<N::ConcreteElement>( + &enclosing_node, + context, + start, + restyle_damage, + ) + ); fragments.fragments.push_back( - control_chars_to_fragment(&enclosing_node, context, end, restyle_damage)); + control_chars_to_fragment::<N::ConcreteElement>( + &enclosing_node, + context, + end, + restyle_damage, + ) + ); } } fragments @@ -402,13 +423,18 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> /// `#[inline(always)]` because this is performance critical and LLVM will not inline it /// otherwise. #[inline(always)] - fn flush_inline_fragments_to_flow(&mut self, - fragment_accumulator: InlineFragmentsAccumulator, - flow: &mut FlowRef, - absolute_descendants: &mut AbsoluteDescendants, - legalizer: &mut Legalizer, - node: &ConcreteThreadSafeLayoutNode) { - let mut fragments = fragment_accumulator.to_intermediate_inline_fragments(self.style_context()); + fn flush_inline_fragments_to_flow( + &mut self, + fragment_accumulator: InlineFragmentsAccumulator, + flow: &mut FlowRef, + absolute_descendants: &mut AbsoluteDescendants, + legalizer: &mut Legalizer, + node: &ConcreteThreadSafeLayoutNode, + ) { + let mut fragments = + fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( + self.style_context(), + ); if fragments.is_empty() { return }; @@ -479,7 +505,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> } inline_flow_ref.finish(); - legalizer.add_child(self.style_context(), flow, inline_flow_ref) + legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + self.style_context(), + flow, + inline_flow_ref, + ) } fn build_block_flow_using_construction_result_of_child( @@ -512,7 +542,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> legalizer, node); } - legalizer.add_child(self.style_context(), flow, kid_flow) + legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + self.style_context(), + flow, + kid_flow, + ) } abs_descendants.push_descendants(kid_abs_descendants); } @@ -546,7 +580,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> node); // Push the flow generated by the {ib} split onto our list of flows. - legalizer.add_child(self.style_context(), flow, kid_flow) + legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + self.style_context(), + flow, + kid_flow, + ) } // Add the fragments to the list we're maintaining. @@ -666,11 +704,17 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let context = self.style_context(); let mut style = node.style(context); - style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoText, &style); + style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoText, + &style, + ); if node_is_input_or_text_area { - style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoInputText, &style) + style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoInputText, + &style, + ) } self.create_fragments_for_node_text_content(&mut fragments, node, &style) @@ -878,7 +922,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let construction_item = ConstructionItem::InlineFragments( InlineFragmentsConstructionResult { splits: opt_inline_block_splits, - fragments: fragment_accumulator.to_intermediate_inline_fragments(self.style_context()), + fragments: fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>( + self.style_context(), + ), }); ConstructionResult::ConstructionItem(construction_item) } else { @@ -902,9 +948,13 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace( node.opaque(), node.get_pseudo_element_type(), - context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoText, &style), - node.restyle_damage())) + context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoText, + &style, + ), + node.restyle_damage(), + )) } // If this is generated content, then we need to initialize the accumulator with the @@ -913,8 +963,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let mut fragments = IntermediateInlineFragments::new(); match (node.get_pseudo_element_type(), node.type_id()) { (_, Some(LayoutNodeType::Text)) => { - let text_style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoText, &style); + let text_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoText, + &style, + ); self.create_fragments_for_node_text_content(&mut fragments, node, &text_style) } (PseudoElementType::Normal, _) => { @@ -949,8 +1002,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let context = self.style_context(); let style = node.style(context); - let style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoInlineBlockWrapper, &style); + let style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoInlineBlockWrapper, + &style, + ); let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new( block_flow)); let fragment = Fragment::from_opaque_node_and_style(node.opaque(), @@ -967,7 +1023,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { splits: LinkedList::new(), - fragments: fragment_accumulator.to_intermediate_inline_fragments(context), + fragments: fragment_accumulator + .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(context), }); ConstructionResult::ConstructionItem(construction_item) } @@ -987,8 +1044,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> InlineAbsoluteHypotheticalFragmentInfo::new(block_flow)); let style_context = self.style_context(); let style = node.style(style_context); - let style = style_context.stylist.style_for_anonymous( - &style_context.guards, &PseudoElement::ServoInlineAbsolute, &style); + let style = style_context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &style_context.guards, + &PseudoElement::ServoInlineAbsolute, + &style, + ); let fragment = Fragment::from_opaque_node_and_style(node.opaque(), PseudoElementType::Normal, style, @@ -1003,7 +1063,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> let construction_item = ConstructionItem::InlineFragments(InlineFragmentsConstructionResult { splits: LinkedList::new(), - fragments: fragment_accumulator.to_intermediate_inline_fragments(style_context), + fragments: fragment_accumulator + .to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context), }); ConstructionResult::ConstructionItem(construction_item) } @@ -1097,8 +1158,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> { let context = self.style_context(); table_style = node.style(context); - wrapper_style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoTableWrapper, &table_style); + wrapper_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + &context.guards, + &PseudoElement::ServoTableWrapper, + &table_style, + ); } let wrapper_fragment = Fragment::from_opaque_node_and_style(node.opaque(), @@ -1128,7 +1192,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> CaptionSide::Top); if let ConstructionResult::Flow(table_flow, table_abs_descendants) = construction_result { - legalizer.add_child(self.style_context(), &mut wrapper_flow, table_flow); + legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>( + self.style_context(), + &mut wrapper_flow, + table_flow, + ); abs_descendants.push_descendants(table_abs_descendants); } @@ -1821,16 +1889,24 @@ fn bidi_control_chars(style: &ServoArc<ComputedValues>) -> Option<(&'static str, } } -fn control_chars_to_fragment(node: &InlineFragmentNodeInfo, - context: &SharedStyleContext, - text: &str, - restyle_damage: RestyleDamage) - -> Fragment { +fn control_chars_to_fragment<E>( + node: &InlineFragmentNodeInfo, + context: &SharedStyleContext, + text: &str, + restyle_damage: RestyleDamage, +) -> Fragment +where + E: TElement, +{ let info = SpecificFragmentInfo::UnscannedText( Box::new(UnscannedTextFragmentInfo::new(String::from(text), None)) ); - let text_style = context.stylist.style_for_anonymous( - &context.guards, &PseudoElement::ServoText, &node.style); + let text_style = context.stylist.style_for_anonymous::<E>( + &context.guards, + &PseudoElement::ServoText, + &node.style, + ); + Fragment::from_opaque_node_and_style(node.address, node.pseudo, text_style, @@ -1887,16 +1963,24 @@ impl Legalizer { /// Makes the `child` flow a new child of `parent`. Anonymous flows are automatically inserted /// to keep the tree legal. - fn add_child(&mut self, context: &SharedStyleContext, parent: &mut FlowRef, mut child: FlowRef) { + fn add_child<E>( + &mut self, + context: &SharedStyleContext, + parent: &mut FlowRef, + mut child: FlowRef, + ) + where + E: TElement, + { while !self.stack.is_empty() { - if self.try_to_add_child(context, parent, &mut child) { + if self.try_to_add_child::<E>(context, parent, &mut child) { return } self.flush_top_of_stack(parent) } - while !self.try_to_add_child(context, parent, &mut child) { - self.push_next_anonymous_flow(context, parent) + while !self.try_to_add_child::<E>(context, parent, &mut child) { + self.push_next_anonymous_flow::<E>(context, parent) } } @@ -1913,8 +1997,15 @@ impl Legalizer { /// This method attempts to create anonymous blocks in between `parent` and `child` if and only /// if those blocks will only ever have `child` as their sole child. At present, this is only /// true for anonymous block children of flex flows. - fn try_to_add_child(&mut self, context: &SharedStyleContext, parent: &mut FlowRef, child: &mut FlowRef) - -> bool { + fn try_to_add_child<E>( + &mut self, + context: &SharedStyleContext, + parent: &mut FlowRef, + child: &mut FlowRef, + ) -> bool + where + E: TElement, + { let parent = self.stack.last_mut().unwrap_or(parent); let (parent_class, child_class) = (parent.class(), child.class()); match (parent_class, child_class) { @@ -1944,12 +2035,14 @@ impl Legalizer { (FlowClass::Flex, FlowClass::Inline) => { FlowRef::deref_mut(child).mut_base().flags.insert(FlowFlags::MARGINS_CANNOT_COLLAPSE); - let mut block_wrapper = - Legalizer::create_anonymous_flow(context, - parent, - &[PseudoElement::ServoAnonymousBlock], - SpecificFragmentInfo::Generic, - BlockFlow::from_fragment); + let mut block_wrapper = Legalizer::create_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousBlock], + SpecificFragmentInfo::Generic, + BlockFlow::from_fragment, + ); + { let flag = if parent.as_flex().main_mode() == Direction::Inline { FragmentFlags::IS_INLINE_FLEX_ITEM @@ -1997,54 +2090,76 @@ impl Legalizer { /// Adds the anonymous flow that would be necessary to make an illegal child of `parent` legal /// to the stack. - fn push_next_anonymous_flow(&mut self, context: &SharedStyleContext, parent: &FlowRef) { + fn push_next_anonymous_flow<E>( + &mut self, + context: &SharedStyleContext, + parent: &FlowRef, + ) + where + E: TElement, + { let parent_class = self.stack.last().unwrap_or(parent).class(); match parent_class { FlowClass::TableRow => { - self.push_new_anonymous_flow(context, - parent, - &[PseudoElement::ServoAnonymousTableCell], - SpecificFragmentInfo::TableCell, - TableCellFlow::from_fragment) + self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTableCell], + SpecificFragmentInfo::TableCell, + TableCellFlow::from_fragment, + ) } FlowClass::Table | FlowClass::TableRowGroup => { - self.push_new_anonymous_flow(context, - parent, - &[PseudoElement::ServoAnonymousTableRow], - SpecificFragmentInfo::TableRow, - TableRowFlow::from_fragment) + self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTableRow], + SpecificFragmentInfo::TableRow, + TableRowFlow::from_fragment, + ) } FlowClass::TableWrapper => { - self.push_new_anonymous_flow(context, - parent, - &[PseudoElement::ServoAnonymousTable], - SpecificFragmentInfo::Table, - TableFlow::from_fragment) + self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoAnonymousTable], + SpecificFragmentInfo::Table, + TableFlow::from_fragment, + ) } _ => { - self.push_new_anonymous_flow(context, - parent, - &[PseudoElement::ServoTableWrapper, - PseudoElement::ServoAnonymousTableWrapper], - SpecificFragmentInfo::TableWrapper, - TableWrapperFlow::from_fragment) + self.push_new_anonymous_flow::<E, _>( + context, + parent, + &[PseudoElement::ServoTableWrapper, + PseudoElement::ServoAnonymousTableWrapper], + SpecificFragmentInfo::TableWrapper, + TableWrapperFlow::from_fragment, + ) } } } /// Creates an anonymous flow and pushes it onto the stack. - fn push_new_anonymous_flow<F>(&mut self, - context: &SharedStyleContext, - reference: &FlowRef, - pseudos: &[PseudoElement], - specific_fragment_info: SpecificFragmentInfo, - constructor: extern "Rust" fn(Fragment) -> F) - where F: Flow { - let new_flow = Legalizer::create_anonymous_flow(context, - reference, - pseudos, - specific_fragment_info, - constructor); + fn push_new_anonymous_flow<E, F>( + &mut self, + context: &SharedStyleContext, + reference: &FlowRef, + pseudos: &[PseudoElement], + specific_fragment_info: SpecificFragmentInfo, + constructor: extern "Rust" fn(Fragment) -> F, + ) + where + E: TElement, + F: Flow, + { + let new_flow = Self::create_anonymous_flow::<E, _>( + context, + reference, + pseudos, + specific_fragment_info, + constructor, + ); self.stack.push(new_flow) } @@ -2053,21 +2168,31 @@ impl Legalizer { /// /// This method invokes the supplied constructor function on the given specific fragment info /// in order to actually generate the flow. - fn create_anonymous_flow<F>(context: &SharedStyleContext, - reference: &FlowRef, - pseudos: &[PseudoElement], - specific_fragment_info: SpecificFragmentInfo, - constructor: extern "Rust" fn(Fragment) -> F) - -> FlowRef - where F: Flow { + fn create_anonymous_flow<E, F>( + context: &SharedStyleContext, + reference: &FlowRef, + pseudos: &[PseudoElement], + specific_fragment_info: SpecificFragmentInfo, + constructor: extern "Rust" fn(Fragment) -> F, + ) -> FlowRef + where + E: TElement, + F: Flow, + { let reference_block = reference.as_block(); let mut new_style = reference_block.fragment.style.clone(); for pseudo in pseudos { - new_style = context.stylist.style_for_anonymous(&context.guards, pseudo, &new_style) + new_style = context.stylist.style_for_anonymous::<E>( + &context.guards, + pseudo, + &new_style, + ); } - let fragment = reference_block.fragment - .create_similar_anonymous_fragment(new_style, - specific_fragment_info); + let fragment = + reference_block.fragment.create_similar_anonymous_fragment( + new_style, + specific_fragment_info, + ); FlowRef::new(Arc::new(constructor(fragment))) } } |