diff options
author | Bobby Holley <bobbyholley@gmail.com> | 2015-11-20 09:51:05 -0800 |
---|---|---|
committer | Bobby Holley <bobbyholley@gmail.com> | 2015-11-28 18:01:02 -0800 |
commit | cf33f00018c7dc44a09086d6bb68b253153635ae (patch) | |
tree | efa655a0967756601963042f0b321e18ed37ed02 /components/layout/construct.rs | |
parent | 77a80919967446639141321ba83b3b0b6d1d1665 (diff) | |
download | servo-cf33f00018c7dc44a09086d6bb68b253153635ae.tar.gz servo-cf33f00018c7dc44a09086d6bb68b253153635ae.zip |
Generalize the rest of layout to operate on generic Layout*.
There wasn't a good way to split this up, unfortunately.
With this change, the only remaining usage of the Servo-specific structures is
in layout_task, where the root node is received from the script task. \o/
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r-- | components/layout/construct.rs | 87 |
1 files changed, 49 insertions, 38 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 53b2416ee8d..49cc3567d57 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -38,6 +38,7 @@ use script::dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId}; use script::dom::htmlobjectelement::is_image_data; use std::borrow::ToOwned; use std::collections::LinkedList; +use std::marker::PhantomData; use std::mem; use std::sync::Arc; use std::sync::atomic::Ordering; @@ -57,7 +58,7 @@ use traversal::PostorderNodeMutTraversal; use url::Url; use util::linked_list; use util::opts; -use wrapper::{PseudoElementType, ServoThreadSafeLayoutNode, TextContent, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; +use wrapper::{PseudoElementType, TextContent, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; /// The results of flow construction for a DOM node. #[derive(Clone)] @@ -208,7 +209,8 @@ impl InlineFragmentsAccumulator { } } - fn from_inline_node(node: &ServoThreadSafeLayoutNode) -> InlineFragmentsAccumulator { + fn from_inline_node<'ln, N>(node: &N) -> InlineFragmentsAccumulator + where N: ThreadSafeLayoutNode<'ln> { InlineFragmentsAccumulator { fragments: IntermediateInlineFragments::new(), enclosing_node: Some(InlineFragmentNodeInfo { @@ -265,29 +267,35 @@ impl InlineFragmentsAccumulator { } /// An object that knows how to create flows. -pub struct FlowConstructor<'a> { +pub struct FlowConstructor<'a, 'ln, N: ThreadSafeLayoutNode<'ln>> { /// The layout context. pub layout_context: &'a LayoutContext<'a>, + /// Satisfy the compiler about the unused parameters, which we use to improve the ergonomics of + /// the ensuing impl {} by removing the need to parameterize all the methods individually. + phantom1: PhantomData<&'ln ()>, + phantom2: PhantomData<N>, } -impl<'a> FlowConstructor<'a> { +impl<'a, 'ln, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln>> + FlowConstructor<'a, 'ln, ConcreteThreadSafeLayoutNode> { /// Creates a new flow constructor. - pub fn new<'b>(layout_context: &'b LayoutContext<'b>) - -> FlowConstructor<'b> { + pub fn new(layout_context: &'a LayoutContext<'a>) -> Self { FlowConstructor { layout_context: layout_context, + phantom1: PhantomData, + phantom2: PhantomData, } } #[inline] fn set_flow_construction_result(&self, - node: &ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, result: ConstructionResult) { node.set_flow_construction_result(result); } /// Builds the fragment for the given block or subclass thereof. - fn build_fragment_for_block(&mut self, node: &ServoThreadSafeLayoutNode) -> Fragment { + fn build_fragment_for_block(&mut self, node: &ConcreteThreadSafeLayoutNode) -> Fragment { let specific_fragment_info = match node.type_id() { Some(NodeTypeId::Element(ElementTypeId::HTMLElement( HTMLElementTypeId::HTMLIFrameElement))) => { @@ -343,7 +351,7 @@ impl<'a> FlowConstructor<'a> { fn generate_anonymous_table_flows_if_necessary(&mut self, flow: &mut FlowRef, child: &mut FlowRef, - child_node: &ServoThreadSafeLayoutNode) { + child_node: &ConcreteThreadSafeLayoutNode) { if !flow.is_block_flow() { return } @@ -401,7 +409,7 @@ impl<'a> FlowConstructor<'a> { flow: &mut FlowRef, flow_list: &mut Vec<FlowRef>, absolute_descendants: &mut AbsoluteDescendants, - node: &ServoThreadSafeLayoutNode) { + node: &ConcreteThreadSafeLayoutNode) { let mut fragments = fragment_accumulator.to_intermediate_inline_fragments(); if fragments.is_empty() { return @@ -486,8 +494,8 @@ impl<'a> FlowConstructor<'a> { &mut self, flow: &mut FlowRef, consecutive_siblings: &mut Vec<FlowRef>, - node: &ServoThreadSafeLayoutNode, - kid: ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, + kid: ConcreteThreadSafeLayoutNode, inline_fragment_accumulator: &mut InlineFragmentsAccumulator, abs_descendants: &mut AbsoluteDescendants) { match kid.swap_out_construction_result() { @@ -595,7 +603,7 @@ impl<'a> FlowConstructor<'a> { fn build_flow_for_block_starting_with_fragments( &mut self, mut flow: FlowRef, - node: &ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, initial_fragments: IntermediateInlineFragments) -> ConstructionResult { // Gather up fragments for the inline flows we might need to create. @@ -662,7 +670,7 @@ impl<'a> FlowConstructor<'a> { /// /// FIXME(pcwalton): It is not clear to me that there isn't a cleaner way to handle /// `<textarea>`. - fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ServoThreadSafeLayoutNode) + fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let mut initial_fragments = IntermediateInlineFragments::new(); let node_is_input_or_text_area = @@ -695,7 +703,7 @@ impl<'a> FlowConstructor<'a> { /// Pushes fragments appropriate for the content of the given node onto the given list. fn create_fragments_for_node_text_content(&self, fragments: &mut IntermediateInlineFragments, - node: &ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, style: &Arc<ComputedValues>) { // Fast path: If there is no text content, return immediately. let text_content = node.text_content(); @@ -744,7 +752,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: block`. This yields a `BlockFlow` with possibly /// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed /// to happen. - fn build_flow_for_block(&mut self, node: &ServoThreadSafeLayoutNode, float_kind: Option<FloatKind>) + fn build_flow_for_block(&mut self, node: &ConcreteThreadSafeLayoutNode, float_kind: Option<FloatKind>) -> ConstructionResult { let fragment = self.build_fragment_for_block(node); let flow: FlowRef = if node.style().is_multicol() { @@ -758,7 +766,7 @@ impl<'a> FlowConstructor<'a> { /// Bubbles up {ib} splits. fn accumulate_inline_block_splits(&mut self, splits: LinkedList<InlineBlockSplit>, - node: &ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, fragment_accumulator: &mut InlineFragmentsAccumulator, opt_inline_block_splits: &mut LinkedList<InlineBlockSplit>) { for split in splits { @@ -783,7 +791,7 @@ impl<'a> FlowConstructor<'a> { /// Returns the `InlineFragmentsConstructionResult`, if any. There will be no /// `InlineFragmentsConstructionResult` if this node consisted entirely of ignorable /// whitespace. - fn build_fragments_for_nonreplaced_inline_content(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_fragments_for_nonreplaced_inline_content(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let mut opt_inline_block_splits: LinkedList<InlineBlockSplit> = LinkedList::new(); let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node); @@ -897,7 +905,7 @@ impl<'a> FlowConstructor<'a> { /// Creates an `InlineFragmentsConstructionResult` for replaced content. Replaced content /// doesn't render its children, so this just nukes a child's fragments and creates a /// `Fragment`. - fn build_fragments_for_replaced_inline_content(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_fragments_for_replaced_inline_content(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { for kid in node.children() { self.set_flow_construction_result(&kid, ConstructionResult::None) @@ -941,7 +949,7 @@ impl<'a> FlowConstructor<'a> { ConstructionResult::ConstructionItem(construction_item) } - fn build_fragment_for_inline_block(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_fragment_for_inline_block(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let block_flow_result = self.build_flow_for_block(node, None); let (block_flow, abs_descendants) = match block_flow_result { @@ -973,7 +981,7 @@ impl<'a> FlowConstructor<'a> { /// This is an annoying case, because the computed `display` value is `block`, but the /// hypothetical box is inline. - fn build_fragment_for_absolutely_positioned_inline(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_fragment_for_absolutely_positioned_inline(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let block_flow_result = self.build_flow_for_block(node, None); let (block_flow, abs_descendants) = match block_flow_result { @@ -1005,7 +1013,7 @@ impl<'a> FlowConstructor<'a> { /// Builds one or more fragments for a node with `display: inline`. This yields an /// `InlineFragmentsConstructionResult`. - fn build_fragments_for_inline(&mut self, node: &ServoThreadSafeLayoutNode) -> ConstructionResult { + fn build_fragments_for_inline(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { // Is this node replaced content? if !node.is_replaced_content() { // Go to a path that concatenates our kids' fragments. @@ -1021,7 +1029,7 @@ impl<'a> FlowConstructor<'a> { /// `caption-side` property is equal to the given `side`. fn place_table_caption_under_table_wrapper_on_side(&mut self, table_wrapper_flow: &mut FlowRef, - node: &ServoThreadSafeLayoutNode, + node: &ConcreteThreadSafeLayoutNode, side: caption_side::T) { // Only flows that are table captions are matched here. for kid in node.children() { @@ -1046,7 +1054,7 @@ impl<'a> FlowConstructor<'a> { fn generate_anonymous_missing_child(&mut self, child_flows: Vec<FlowRef>, flow: &mut FlowRef, - node: &ServoThreadSafeLayoutNode) { + node: &ConcreteThreadSafeLayoutNode) { let mut anonymous_flow = flow.generate_missing_child_flow(node); let mut consecutive_siblings = vec!(); for kid_flow in child_flows { @@ -1072,7 +1080,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with /// possibly other `TableCaptionFlow`s or `TableFlow`s underneath it. - fn build_flow_for_table_wrapper(&mut self, node: &ServoThreadSafeLayoutNode, float_value: float::T) + fn build_flow_for_table_wrapper(&mut self, node: &ConcreteThreadSafeLayoutNode, float_value: float::T) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableWrapper); let mut wrapper_flow: FlowRef = Arc::new( @@ -1134,7 +1142,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table-caption`. This yields a `TableCaptionFlow` /// with possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_table_caption(&mut self, node: &ServoThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_caption(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let fragment = self.build_fragment_for_block(node); let flow = Arc::new(TableCaptionFlow::from_fragment(fragment)); self.build_flow_for_block_like(flow, node) @@ -1142,7 +1150,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow` /// with possibly other `TableRowFlow`s underneath it. - fn build_flow_for_table_rowgroup(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_flow_for_table_rowgroup(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow); let flow = Arc::new(TableRowGroupFlow::from_fragment(fragment)); @@ -1151,7 +1159,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with /// possibly other `TableCellFlow`s underneath it. - fn build_flow_for_table_row(&mut self, node: &ServoThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_row(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow); let flow = Arc::new(TableRowFlow::from_fragment(fragment)); self.build_flow_for_block_like(flow, node) @@ -1159,7 +1167,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with /// possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_table_cell(&mut self, node: &ServoThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_cell(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let fragment = Fragment::new(node, SpecificFragmentInfo::TableCell); // Determine if the table cell should be hidden. Per CSS 2.1 § 17.6.1.1, this will be true @@ -1180,7 +1188,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with /// possibly other `BlockFlow`s or `InlineFlow`s underneath it. - fn build_flow_for_list_item(&mut self, node: &ServoThreadSafeLayoutNode, flotation: float::T) + fn build_flow_for_list_item(&mut self, node: &ConcreteThreadSafeLayoutNode, flotation: float::T) -> ConstructionResult { let flotation = FloatKind::from_property(flotation); let marker_fragments = match node.style().get_list().list_style_image.0 { @@ -1239,7 +1247,7 @@ impl<'a> FlowConstructor<'a> { } /// Creates a fragment for a node with `display: table-column`. - fn build_fragments_for_table_column(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_fragments_for_table_column(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { // CSS 2.1 § 17.2.1. Treat all child fragments of a `table-column` as `display: none`. for kid in node.children() { @@ -1254,7 +1262,7 @@ impl<'a> FlowConstructor<'a> { /// Builds a flow for a node with `display: table-column-group`. /// This yields a `TableColGroupFlow`. - fn build_flow_for_table_colgroup(&mut self, node: &ServoThreadSafeLayoutNode) + fn build_flow_for_table_colgroup(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { let fragment = Fragment::new(node, @@ -1283,7 +1291,7 @@ impl<'a> FlowConstructor<'a> { } /// Builds a flow for a node with 'display: flex'. - fn build_flow_for_flex(&mut self, node: &ServoThreadSafeLayoutNode, float_kind: Option<FloatKind>) + fn build_flow_for_flex(&mut self, node: &ConcreteThreadSafeLayoutNode, float_kind: Option<FloatKind>) -> ConstructionResult { let fragment = self.build_fragment_for_block(node); let flow = Arc::new(FlexFlow::from_fragment(fragment, float_kind)); @@ -1295,7 +1303,7 @@ impl<'a> FlowConstructor<'a> { /// /// TODO(pcwalton): Add some more fast paths, like toggling `display: none`, adding block kids /// to block parents with no {ib} splits, adding out-of-flow kids, etc. - pub fn repair_if_possible(&mut self, node: &ServoThreadSafeLayoutNode) -> bool { + pub fn repair_if_possible(&mut self, node: &ConcreteThreadSafeLayoutNode) -> bool { // We can skip reconstructing the flow if we don't have to reconstruct and none of our kids // did either. // @@ -1403,14 +1411,16 @@ impl<'a> FlowConstructor<'a> { } } -impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { +impl<'a, 'ln, ConcreteThreadSafeLayoutNode> PostorderNodeMutTraversal<'ln, ConcreteThreadSafeLayoutNode> + for FlowConstructor<'a, 'ln, ConcreteThreadSafeLayoutNode> + where ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln> { // Construct Flow based on 'display', 'position', and 'float' values. // // CSS 2.1 Section 9.7 // // TODO: This should actually consult the table in that section to get the // final computed value for 'display'. - fn process(&mut self, node: &ServoThreadSafeLayoutNode) -> bool { + fn process(&mut self, node: &ConcreteThreadSafeLayoutNode) -> bool { // Get the `display` property for this node, and determine whether this node is floated. let (display, float, positioning) = match node.type_id() { None => { @@ -1580,7 +1590,8 @@ trait NodeUtils { fn swap_out_construction_result(self) -> ConstructionResult; } -impl<'ln> NodeUtils for ServoThreadSafeLayoutNode<'ln> { +impl<'ln, ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode + where ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode<'ln> { fn is_replaced_content(&self) -> bool { match self.type_id() { None | @@ -1639,7 +1650,7 @@ trait ObjectElement<'a> { fn object_data(&self) -> Option<Url>; } -impl<'ln> ObjectElement<'ln> for ServoThreadSafeLayoutNode<'ln> { +impl<'ln, N> ObjectElement<'ln> for N where N: ThreadSafeLayoutNode<'ln> { fn get_type_and_data(&self) -> (Option<&'ln str>, Option<&'ln str>) { let elem = self.as_element(); (elem.get_attr(&ns!(), &atom!("type")), elem.get_attr(&ns!(), &atom!("data"))) |