aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/construct.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r--components/layout/construct.rs97
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);