Commit e19d805c authored by Ian Kilpatrick's avatar Ian Kilpatrick Committed by Commit Bot

[LayoutNG] Fixes OOF min/max sizes for nodes w/ %-dependent children.

Previously we just passed in the containing block size, however this was
incorrect for the following case:
<div style="position: relative; height: 200px;">
  <div style="position: absolute; top: 0; bottom: 100px;">
    <canvas width=1 height=1 style="height: 100%;"></canvas>
  </div>
</div>

This pre-calculates the block-size of the OOF-positioned element, and
pass it into the NGBlockNode::MinMaxSizes pass.

Change-Id: I897dc6f9c157bfa1ae63f9821cdb6ed03a218322
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2122854
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: default avatarAleks Totic <atotic@chromium.org>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754763}
parent 955f3492
......@@ -1137,7 +1137,10 @@ LayoutUnit CalculateChildPercentageBlockSizeForMinMax(
const NGBoxStrut& border_padding,
LayoutUnit parent_percentage_block_size) {
// Anonymous block or spaces should pass the percent size straight through.
if (space.IsAnonymous() || node.IsAnonymousBlock())
// If this node is OOF-positioned, our size was pre-calculated and we should
// pass this through to our children.
if (space.IsAnonymous() || node.IsAnonymousBlock() ||
node.IsOutOfFlowPositioned())
return parent_percentage_block_size;
LayoutUnit block_size = ComputeBlockSizeForFragmentInternal(
......@@ -1152,8 +1155,7 @@ LayoutUnit CalculateChildPercentageBlockSizeForMinMax(
// For OOF-positioned nodes, use the parent (containing-block) size.
if (child_percentage_block_size == kIndefiniteSize &&
(node.UseParentPercentageResolutionBlockSizeForChildren() ||
node.IsOutOfFlowPositioned()))
node.UseParentPercentageResolutionBlockSizeForChildren())
child_percentage_block_size = parent_percentage_block_size;
return child_percentage_block_size;
......
......@@ -580,16 +580,32 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
// words, in that case, we may have to lay out, calculate the offset, and
// then lay out again at the correct block-offset.
NGLogicalOutOfFlowDimensions node_dimensions;
bool has_computed_block_dimensions = false;
bool is_replaced = node.IsReplaced();
bool should_be_considered_as_replaced = node.ShouldBeConsideredAsReplaced();
bool absolute_needs_child_block_size =
AbsoluteNeedsChildBlockSize(candidate_style);
if (AbsoluteNeedsChildInlineSize(candidate_style) ||
NeedMinMaxSize(candidate_style) || should_be_considered_as_replaced) {
min_max_sizes = node.ComputeMinMaxSizes(
candidate_writing_mode,
MinMaxSizesInput(
container_content_size_in_candidate_writing_mode.block_size),
&candidate_constraint_space);
MinMaxSizesInput input(kIndefiniteSize);
if (is_replaced) {
input.percentage_resolution_block_size =
container_content_size_in_candidate_writing_mode.block_size;
} else if (!absolute_needs_child_block_size) {
// If we can determine our block-size ahead of time (it doesn't depend on
// our content), we use this for our %-block-size.
ComputeOutOfFlowBlockDimensions(
candidate_constraint_space, candidate_style, border_padding,
candidate_static_position, base::nullopt, base::nullopt,
writing_mode_, container_direction, &node_dimensions);
has_computed_block_dimensions = true;
input.percentage_resolution_block_size = node_dimensions.size.block_size;
}
min_max_sizes = node.ComputeMinMaxSizes(candidate_writing_mode, input,
&candidate_constraint_space);
}
base::Optional<LogicalSize> replaced_size;
......@@ -614,7 +630,7 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
candidate_constraint_space.AvailableSize().inline_size),
kIndefiniteSize};
}
NGLogicalOutOfFlowDimensions node_dimensions;
ComputeOutOfFlowInlineDimensions(candidate_constraint_space, candidate_style,
border_padding, candidate_static_position,
min_max_sizes, replaced_size, writing_mode_,
......@@ -636,7 +652,8 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
replaced_aspect_ratio->inline_size)) +
border_padding.BlockSum());
}
if (AbsoluteNeedsChildBlockSize(candidate_style)) {
if (absolute_needs_child_block_size) {
DCHECK(!has_computed_block_dimensions);
layout_result =
GenerateFragment(node, container_content_size_in_candidate_writing_mode,
block_estimate, node_dimensions);
......@@ -650,12 +667,16 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
block_estimate = fragment.BlockSize();
}
// Calculate the offsets.
ComputeOutOfFlowBlockDimensions(candidate_constraint_space, candidate_style,
border_padding, candidate_static_position,
block_estimate, replaced_size, writing_mode_,
container_direction, &node_dimensions);
// We may have already pre-computed our block-dimensions when determining our
// |min_max_sizes|, only run if needed.
if (!has_computed_block_dimensions) {
ComputeOutOfFlowBlockDimensions(
candidate_constraint_space, candidate_style, border_padding,
candidate_static_position, block_estimate, replaced_size, writing_mode_,
container_direction, &node_dimensions);
}
// Calculate the offsets.
NGBoxStrut inset =
node_dimensions.inset
.ConvertToPhysical(candidate_writing_mode, candidate_direction)
......
......@@ -100,10 +100,13 @@ crbug.com/591099 external/wpt/css/css-shapes/shape-outside/supported-shapes/poly
crbug.com/591099 external/wpt/css/css-sizing/clone-nowrap-intrinsic-size-bidi.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-004.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-005.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-008.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-001.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-002.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-004.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-006.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-007.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-replaced-dynamic-008.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/whitespace-and-break.html [ Failure ]
crbug.com/591099 external/wpt/css/css-sizing/ortho-writing-mode-001.html [ Failure ]
......
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes">
<meta name="assert" content="Checks that a replaced element, with an aspect ratio, converts a percent height into an intrinsic width." />
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<style>
#container { position: relative; height: 200px; }
#abs { position: absolute; top: 0; bottom: 100px; background: green; }
canvas { height: 100%; }
</style>
<p>Test passes if there is a filled green square.</p>
<div id=container>
<div id=abs>
<canvas width=10 height=10></canvas>
</div>
</div>
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#intrinsic-sizes">
<meta name="assert" content="Checks that a replaced element, with an aspect ratio, converts a percent height into an intrinsic width." />
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<style>
#container { position: relative; width: 200px; height: 200px; }
#abs { writing-mode: vertical-lr; position: absolute; left: 0; right: 100px; background: green; }
canvas { width: 100%; }
</style>
<p>Test passes if there is a filled green square.</p>
<div id=container>
<div id=abs>
<canvas width=10 height=10></canvas>
</div>
</div>
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#intrinsic">
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<meta name="assert" content="This test checks that a dynamic change in the height of an element calculates the intrinsic min/max size correctly when a replaced element is present."/>
<p>Test passes if there is a filled green square.</p>
<div style="position: relative; width: 100px; height: 200px;">
<div id="target" style="position: absolute; top:0; bottom: 0; background: green;">
<canvas width="1" height="1" style="height: 100%;"></canvas>
</div>
</div>
<script>
document.body.offsetTop;
document.getElementById('target').style.bottom = '100px';
</script>
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#intrinsic">
<link rel="match" href="../reference/ref-filled-green-100px-square-only.html">
<meta name="assert" content="This test checks that a dynamic change in the height of an element calculates the intrinsic min/max size correctly when a replaced element is present."/>
<p>Test passes if there is a filled green square.</p>
<div style="position: relative; width: 200px; height: 200px;">
<div id="target" style="writing-mode: vertical-lr; position: absolute; left: 0; right: 0; background: green;">
<canvas width="1" height="1" style="width: 100%;"></canvas>
</div>
</div>
<script>
document.body.offsetTop;
document.getElementById('target').style.right = '100px';
</script>
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