diff --git a/components/layout/block.rs b/components/layout/block.rs index 70a3da462da..9580f1cd6a5 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -1494,42 +1494,15 @@ impl BlockFlow { surrounding_inline_size, } } -} -impl Flow for BlockFlow { - fn class(&self) -> FlowClass { - FlowClass::Block - } - - fn as_mut_block<'a>(&'a mut self) -> &'a mut BlockFlow { - self - } - - fn as_block<'a>(&'a self) -> &'a BlockFlow { - self - } - - /// Pass 1 of reflow: computes minimum and preferred inline-sizes. - /// - /// Recursively (bottom-up) determine the flow's minimum and preferred inline-sizes. When - /// called on this flow, all child flows have had their minimum and preferred inline-sizes set. - /// This function must decide minimum/preferred inline-sizes based on its children's - /// inline-sizes and the dimensions of any fragments it is responsible for flowing. - fn bubble_inline_sizes(&mut self) { + /// Computes intrinsic widths for a block. + pub fn bubble_inline_sizes_for_block(&mut self, consult_children: bool) { let _scope = layout_debug_scope!("block::bubble_inline_sizes {:x}", self.base.debug_id()); let mut flags = self.base.flags; flags.remove(HAS_LEFT_FLOATED_DESCENDANTS); flags.remove(HAS_RIGHT_FLOATED_DESCENDANTS); - // If this block has a fixed width, just use that for the minimum - // and preferred width, rather than bubbling up children inline - // width. - let fixed_width = match self.fragment.style().get_box().width { - LengthOrPercentageOrAuto::Length(_) => true, - _ => false, - }; - // Find the maximum inline-size from children. let mut computation = self.fragment.compute_intrinsic_inline_sizes(); let (mut left_float_width, mut right_float_width) = (Au(0), Au(0)); @@ -1539,7 +1512,7 @@ impl Flow for BlockFlow { flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED); let child_base = flow::mut_base(kid); let float_kind = child_base.flags.float_kind(); - if !is_absolutely_positioned && !fixed_width { + if !is_absolutely_positioned && consult_children { computation.content_intrinsic_sizes.minimum_inline_size = max(computation.content_intrinsic_sizes.minimum_inline_size, child_base.intrinsic_inline_sizes.minimum_inline_size); @@ -1591,6 +1564,36 @@ impl Flow for BlockFlow { } self.base.flags = flags } +} + +impl Flow for BlockFlow { + fn class(&self) -> FlowClass { + FlowClass::Block + } + + fn as_mut_block<'a>(&'a mut self) -> &'a mut BlockFlow { + self + } + + fn as_block<'a>(&'a self) -> &'a BlockFlow { + self + } + + /// Pass 1 of reflow: computes minimum and preferred inline-sizes. + /// + /// Recursively (bottom-up) determine the flow's minimum and preferred inline-sizes. When + /// called on this flow, all child flows have had their minimum and preferred inline-sizes set. + /// This function must decide minimum/preferred inline-sizes based on its children's + /// inline-sizes and the dimensions of any fragments it is responsible for flowing. + fn bubble_inline_sizes(&mut self) { + // If this block has a fixed width, just use that for the minimum and preferred width, + // rather than bubbling up children inline width. + let consult_children = match self.fragment.style().get_box().width { + LengthOrPercentageOrAuto::Length(_) => false, + _ => true, + }; + self.bubble_inline_sizes_for_block(consult_children) + } /// Recursively (top-down) determines the actual inline-size of child contexts and fragments. /// When called on this context, the context has had its inline-size set by the parent context. diff --git a/components/layout/table.rs b/components/layout/table.rs index 4b1a0ceda20..5d42b0772d4 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -576,11 +576,17 @@ impl ISizeAndMarginsComputer for InternalTable { block: &mut BlockFlow, layout_context: &LayoutContext, parent_flow_inline_size: Au) { - let input = self.compute_inline_size_constraint_inputs(block, - parent_flow_inline_size, - layout_context); - let solution = self.solve_inline_size_constraints(block, &input); + let mut input = self.compute_inline_size_constraint_inputs(block, + parent_flow_inline_size, + layout_context); + // Tables are always at least as wide as their minimum inline size. + let minimum_inline_size = + block.base.intrinsic_inline_sizes.minimum_inline_size - + block.fragment.border_padding.inline_start_end(); + input.available_inline_size = cmp::max(input.available_inline_size, minimum_inline_size); + + let solution = self.solve_inline_size_constraints(block, &input); self.set_inline_size_constraint_solutions(block, solution); } diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 92ce3d98ceb..56c66d2a967 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -106,7 +106,7 @@ impl Flow for TableCellFlow { let _scope = layout_debug_scope!("table_cell::bubble_inline_sizes {:x}", self.block_flow.base.debug_id()); - self.block_flow.bubble_inline_sizes(); + self.block_flow.bubble_inline_sizes_for_block(true); let specified_inline_size = MaybeAuto::from_style(self.block_flow .fragment .style() diff --git a/tests/wpt/css-tests/css21_dev/html4/table-visual-layout-026a.htm b/tests/wpt/css-tests/css21_dev/html4/table-visual-layout-026a.htm index a94f7e541dc..11b55d294fd 100644 --- a/tests/wpt/css-tests/css21_dev/html4/table-visual-layout-026a.htm +++ b/tests/wpt/css-tests/css21_dev/html4/table-visual-layout-026a.htm @@ -68,4 +68,4 @@