diff options
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r-- | components/layout/construct.rs | 97 |
1 files changed, 80 insertions, 17 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 0f832bacfb8..c88de5e8b3e 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -27,6 +27,7 @@ use flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use flow::{Descendants, AbsDescendants}; use flow; use flow_ref::FlowRef; +use fragment::{InlineBlockFragment, InlineBlockFragmentInfo}; use fragment::{Fragment, GenericFragment, IframeFragment, IframeFragmentInfo}; use fragment::{ImageFragment, ImageFragmentInfo, SpecificFragmentInfo, TableFragment}; use fragment::{TableCellFragment, TableColumnFragment, TableColumnFragmentInfo}; @@ -266,19 +267,38 @@ impl<'a, 'b> FlowConstructor<'a, 'b> { } } - let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments); - let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style()); - inline_flow.minimum_block_size_above_baseline = ascent; - inline_flow.minimum_depth_below_baseline = descent; - let mut inline_flow = inline_flow as Box<Flow>; - TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow); - let mut inline_flow = FlowRef::new(inline_flow); - inline_flow.finish(self.layout_context); - - if flow.get().need_anonymous_flow(inline_flow.get()) { - flow_list.push(inline_flow) + // Build a list of all the inline-block fragments before fragments is moved. + let mut inline_block_flows = vec!(); + for f in fragments.fragments.iter() { + match f.specific { + InlineBlockFragment(ref info) => { + inline_block_flows.push(info.flow_ref.clone()); + }, + _ => {} + } + } + + let mut inline_flow_ref = FlowRef::new(box InlineFlow::from_fragments((*node).clone(), fragments)); + + // Add all the inline-block fragments as children of the inline flow. + for inline_block_flow in inline_block_flows.iter() { + inline_flow_ref.add_new_child(inline_block_flow.clone()); + } + + { + let inline_flow = inline_flow_ref.get_mut().as_inline(); + let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style()); + inline_flow.minimum_block_size_above_baseline = ascent; + inline_flow.minimum_depth_below_baseline = descent; + TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow); + } + + inline_flow_ref.finish(self.layout_context); + + if flow.get().need_anonymous_flow(inline_flow_ref.get()) { + flow_list.push(inline_flow_ref) } else { - flow.add_new_child(inline_flow) + flow.add_new_child(inline_flow_ref) } } @@ -582,6 +602,27 @@ impl<'a, 'b> FlowConstructor<'a, 'b> { ConstructionItemConstructionResult(construction_item) } + fn build_fragment_for_inline_block(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { + let block_flow_result = self.build_flow_for_block(node); + let block_flow = match block_flow_result { + FlowConstructionResult(block_flow, _) => block_flow, + _ => unreachable!() + }; + + let fragment_info = InlineBlockFragment(InlineBlockFragmentInfo::new(block_flow)); + let mut fragment = Fragment::new_from_specific_info(node, fragment_info); + + let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node); + fragment_accumulator.fragments.push(&mut fragment, node.style().clone()); + + let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult { + splits: Vec::new(), + fragments: fragment_accumulator.finish(), + abs_descendants: Descendants::new(), + }); + ConstructionItemConstructionResult(construction_item) + } + /// Builds one or more fragments for a node with `display: inline`. This yields an /// `InlineFragmentsConstructionResult`. fn build_fragments_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult { @@ -643,7 +684,8 @@ impl<'a, 'b> FlowConstructor<'a, 'b> { /// 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: &ThreadSafeLayoutNode) -> ConstructionResult { + fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, + float_value: float::T) -> ConstructionResult { let fragment = Fragment::new_from_specific_info(node, TableWrapperFragment); let wrapper_flow = box TableWrapperFlow::from_node_and_fragment(node, fragment); let mut wrapper_flow = FlowRef::new(wrapper_flow as Box<Flow>); @@ -693,7 +735,20 @@ impl<'a, 'b> FlowConstructor<'a, 'b> { abs_descendants.push(wrapper_flow.clone()); } } - FlowConstructionResult(wrapper_flow, abs_descendants) + + match float_value { + float::none => { + FlowConstructionResult(wrapper_flow, abs_descendants) + } + _ => { + let float_kind = FloatKind::from_property(float_value); + let float_flow = box BlockFlow::float_from_node(self, node, float_kind) as Box<Flow>; + let mut float_flow = FlowRef::new(float_flow); + float_flow.add_new_child(wrapper_flow); + float_flow.finish(self.layout_context); + FlowConstructionResult(float_flow, abs_descendants) + } + } } /// Builds a flow for a node with `display: table-caption`. This yields a `TableCaptionFlow` @@ -817,8 +872,8 @@ impl<'a, 'b> PostorderNodeMutTraversal for FlowConstructor<'a, 'b> { } // Table items contribute table flow construction results. - (display::table, _, _) => { - let construction_result = self.build_flow_for_table_wrapper(node); + (display::table, float_value, _) => { + let construction_result = self.build_flow_for_table_wrapper(node, float_value); node.set_flow_construction_result(construction_result) } @@ -833,11 +888,19 @@ impl<'a, 'b> PostorderNodeMutTraversal for FlowConstructor<'a, 'b> { } // Inline items contribute inline fragment construction results. - (display::inline, float::none, _) => { + // + // FIXME(pcwalton, #3307): This is not sufficient to handle floated generated content. + (display::inline, _, _) => { let construction_result = self.build_fragments_for_inline(node); node.set_flow_construction_result(construction_result) } + // Inline-block items contribute inline fragment construction results. + (display::inline_block, float::none, _) => { + let construction_result = self.build_fragment_for_inline_block(node); + node.set_flow_construction_result(construction_result) + } + // Table items contribute table flow construction results. (display::table_caption, _, _) => { let construction_result = self.build_flow_for_table_caption(node); |