diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-01-22 21:49:18 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-01-23 00:57:54 +0100 |
commit | 5ac12b5df4406dbde1ceeb6be36be5c3162401a2 (patch) | |
tree | 173742ffb60360fc56f39a5b05b53890e84853ee /components/layout/construct.rs | |
parent | 6f543d3de1658e3cacf7fc2caed7b9bda69e1d23 (diff) | |
download | servo-5ac12b5df4406dbde1ceeb6be36be5c3162401a2.tar.gz servo-5ac12b5df4406dbde1ceeb6be36be5c3162401a2.zip |
style: Make the TElement type arrive to the `cascade` function.
Not super-proud of this one, but it's the easiest way I could think of.
The changeset looks bigger than what it is, because while at it I've rewrapped a
fair amount of functions around to use proper block indentation.
Alternatives are parameterizing Stylist by <E>, which is not fun, or moving the
concrete element from layout_thread to layout, but that implies layout depending
on script, which isn't fun either.
Other alternative is implementing an empty enum and making anon boxes work on
it. It has the advantage of removing the annoying type parameter, but the
disadvantage of instantiating `cascade` twice, which isn't great, and having to
maintain all the boilerplate of a `TElement` implementation that just does
nothing.
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))) } } |