Commit ccfb6b8a authored by David Grogan's avatar David Grogan Committed by Commit Bot

[FlexNG] Honor stretched items' specified min/max sizes

A stretched item's pre-flex layout was getting a fixed cross size equal
to the container's cross size, ignoring the item's min/max cross size.

Bug: 845235
Change-Id: I8ff2c160f6ede952297ac4f114e954d8dcc5538e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2113809
Commit-Queue: David Grogan <dgrogan@chromium.org>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#752613}
parent c565effe
......@@ -326,7 +326,8 @@ double NGFlexLayoutAlgorithm::GetMainOverCrossAspectRatio(
NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
const NGBlockNode& flex_item,
const NGPhysicalBoxStrut& physical_margins) const {
const NGPhysicalBoxStrut& physical_margins,
const MinMaxSizes& cross_axis_min_max) const {
const ComputedStyle& child_style = flex_item.Style();
NGConstraintSpaceBuilder space_builder(ConstraintSpace(),
child_style.GetWritingMode(),
......@@ -341,19 +342,16 @@ NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForIntrinsicBlockSize(
if (ShouldItemShrinkToFit(flex_item)) {
space_builder.SetIsShrinkToFit(true);
} else if (WillChildCrossSizeBeContainerCrossSize(flex_item)) {
// TODO(dgrogan): Do you need to further adjust available size by item's min
// and max cross sizes before SetIsFixed{Inline,Block}Size(true) ?
if (is_column_) {
space_builder.SetIsFixedInlineSize(true);
child_available_size.inline_size =
(child_available_size.inline_size - margins.InlineSum())
.ClampNegativeToZero();
cross_axis_min_max.ClampSizeToMinAndMax(
child_available_size.inline_size - margins.InlineSum());
} else {
space_builder.SetIsFixedBlockSize(true);
DCHECK_NE(content_box_size_.block_size, kIndefiniteSize);
child_available_size.block_size =
(child_available_size.block_size - margins.BlockSum())
.ClampNegativeToZero();
child_available_size.block_size = cross_axis_min_max.ClampSizeToMinAndMax(
child_available_size.block_size - margins.BlockSum());
}
}
......@@ -422,33 +420,19 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
is_horizontal_flow_ ? physical_border_padding.VerticalSum()
: physical_border_padding.HorizontalSum();
base::Optional<LayoutUnit> intrinsic_block_size;
auto IntrinsicBlockSizeFunc = [&]() -> LayoutUnit {
if (!intrinsic_block_size) {
NGConstraintSpace child_space =
BuildSpaceForIntrinsicBlockSize(child, physical_child_margins);
intrinsic_block_size =
child.Layout(child_space, /* break_token */ nullptr)
->IntrinsicBlockSize();
}
return *intrinsic_block_size;
};
base::Optional<MinMaxSizes> min_max_size;
auto MinMaxSizesFunc = [&]() -> MinMaxSizes {
if (!min_max_size) {
NGConstraintSpace child_space =
BuildSpaceForIntrinsicBlockSize(child, physical_child_margins);
if (child.Style().OverflowBlockDirection() == EOverflow::kAuto) {
// Ensure this child has been laid out so its auto scrollbars are
// included in its intrinsic sizes.
IntrinsicBlockSizeFunc();
child.Layout(flex_basis_space);
}
// We want the child's min/max size in its writing mode, not ours.
// We'll only ever use it if the child's inline axis is our main axis.
min_max_size = child.ComputeMinMaxSizes(
child_style.GetWritingMode(),
MinMaxSizesInput(content_box_size_.block_size), &child_space);
MinMaxSizesInput(content_box_size_.block_size), &flex_basis_space);
}
return *min_max_size;
};
......@@ -491,6 +475,19 @@ void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() {
LengthResolvePhase::kLayout);
}
base::Optional<LayoutUnit> intrinsic_block_size;
auto IntrinsicBlockSizeFunc = [&]() -> LayoutUnit {
if (!intrinsic_block_size) {
NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(
child, physical_child_margins,
min_max_sizes_in_cross_axis_direction);
scoped_refptr<const NGLayoutResult> layout_result =
child.Layout(child_space, /* break_token */ nullptr);
intrinsic_block_size = layout_result->IntrinsicBlockSize();
}
return *intrinsic_block_size;
};
// The logic that calculates flex_base_border_box assumes that the used
// value of the flex-basis property is either definite or 'content'.
LayoutUnit flex_base_border_box;
......@@ -813,6 +810,8 @@ scoped_refptr<const NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
space_builder.SetIsFixedInlineSize(true);
}
if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node)) {
// TODO(dgrogan): These need margins subtracted and min/max sizes
// applied, like in BuildSpaceForIntrinsicBlockSize.
if (is_column_)
space_builder.SetIsFixedInlineSize(true);
else
......
......@@ -53,7 +53,8 @@ class CORE_EXPORT NGFlexLayoutAlgorithm
NGConstraintSpace BuildSpaceForFlexBasis(const NGBlockNode& flex_item) const;
NGConstraintSpace BuildSpaceForIntrinsicBlockSize(
const NGBlockNode& flex_item,
const NGPhysicalBoxStrut& physical_margins) const;
const NGPhysicalBoxStrut& physical_margins,
const MinMaxSizes& cross_axis) const;
void ConstructAndAppendFlexItems();
void ApplyStretchAlignmentToChild(FlexItem& flex_item);
void GiveLinesAndItemsFinalPositionAndSize();
......
<!DOCTYPE html>
<title>item's min/max cross sizes</title>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#definite-sizes" title="Bullet 1">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="" />
<meta name="assert" content="specified max cross size on stretched items is honored pre-flexing" />
<style>
.inline-block {
display: inline-block;
width: 40px;
height: 50px;
}
#reference-overlapped-red {
position: absolute;
background-color: red;
width: 100px;
height: 100px;
z-index: -1;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="reference-overlapped-red"></div>
<div style="display:flex; flex-direction: column; width: 100px; background: green">
<div style="max-width: 50px; line-height: 0px;">
<!-- An engine where these inline blocks don't wrap will give green height 50px. -->
<div class=inline-block></div><div class=inline-block></div>
</div>
</div>
<!DOCTYPE html>
<title>item's min/max cross sizes</title>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#definite-sizes" title="Bullet 1">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="flags" content="" />
<meta name="assert" content="specified max cross size on ortho stretched items is honored pre-flexing" />
<style>
.inline-block {
display: inline-block;
width: 50px;
height: 55px;
}
#reference-overlapped-red {
position: absolute;
background-color: red;
width: 100px;
height: 100px;
z-index: -1;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="reference-overlapped-red"></div>
<div style="display:flex; height: 110px;">
<div style="writing-mode: vertical-lr; max-height: 100px; line-height: 0px; background: green;">
<div class=inline-block></div><div class=inline-block></div>
</div>
</div>
<!DOCTYPE html>
<title>item's min/max cross sizes</title>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#definite-sizes" title="Bullet 1">
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<meta name="flags" content="" />
<meta name="assert" content="specified min cross size on stretched items is honored pre-flexing" />
<style>
.inline-block {
display: inline-block;
width: 1px;
height: 100px;
}
</style>
<p>Test passes if there is a filled green square.</p>
<div style="display:flex; flex-direction: column; width: 0px;">
<div style="background: green; min-width: 100px; line-height: 0px;">
<div class=inline-block></div><div class=inline-block></div>
</div>
</div>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment