Commit f6972714 authored by Benjamin Beaudry's avatar Benjamin Beaudry Committed by Chromium LUCI CQ

[LayoutNG] Fix incorrect start offset for nested abspos

In some specific cases, the offset of the innermost abspos was off by
exactly one fragmentainer block size. This CL fixes the issue.

Bug: 1157086
Change-Id: I9ee621e11d7e411de56a8d8c3da1561d2eb1f7e7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2602442
Commit-Queue: Benjamin Beaudry <benjamin.beaudry@microsoft.com>
Reviewed-by: default avatarAlison Maher <almaher@microsoft.com>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#840252}
parent a8e0a83a
......@@ -641,9 +641,6 @@ void NGOutOfFlowLayoutPart::LayoutFragmentainerDescendants(
for (auto& descendant : *descendants) {
scoped_refptr<const NGLayoutResult> result =
LayoutFragmentainerDescendant(descendant);
// TODO(bebeaudr): The final offset of the innermost abspos is wrong. It
// seems like it is off by exactly the offset of the outermost abspos.
// Don't we already take into account that value?
container_builder_->PropagateOOFPositionedFragmentainerDescendants(
result->PhysicalFragment(), result->OutOfFlowPositionedOffset());
}
......@@ -876,6 +873,7 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
container_writing_direction, &node_dimensions);
has_computed_block_dimensions = true;
}
block_estimate = node_dimensions.size.block_size;
// Calculate the offsets.
NGBoxStrut inset =
......@@ -896,7 +894,7 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
DCHECK_GT(num_children, 0u);
ComputeStartFragmentIndexAndRelativeOffset(
container_info, default_writing_direction.GetWritingMode(),
&start_index, &offset);
*block_estimate, &start_index, &offset);
}
if (!only_layout && !can_traverse_fragments_) {
......@@ -971,7 +969,6 @@ scoped_refptr<const NGLayoutResult> NGOutOfFlowLayoutPart::Layout(
// Skip this step if we produced a fragment that can be reused when
// estimating the block-size.
if (!layout_result) {
block_estimate = node_dimensions.size.block_size;
const NGConstraintSpace* fragmentainer_constraint_space =
is_fragmentainer_descendant
? &GetFragmentainerConstraintSpace(start_index)
......@@ -1254,6 +1251,7 @@ void NGOutOfFlowLayoutPart::AddOOFResultToFragmentainerResults(
void NGOutOfFlowLayoutPart::ComputeStartFragmentIndexAndRelativeOffset(
const ContainingBlockInfo& container_info,
WritingMode default_writing_mode,
LayoutUnit block_estimate,
wtf_size_t* start_index,
LogicalOffset* offset) const {
wtf_size_t child_index = 0;
......@@ -1272,7 +1270,16 @@ void NGOutOfFlowLayoutPart::ComputeStartFragmentIndexAndRelativeOffset(
.block_size;
current_max_block_size += fragmentainer_block_size;
if (offset->block_offset < current_max_block_size) {
// Edge case: an abspos with an height of 0 positioned exactly at the
// |current_max_block_size| won't be fragmented, so no break token will be
// produced - as we'd expect. However, the break token is used to compute
// the |fragmentainer_consumed_block_size_| stored on the
// |container_builder_| when we have a nested abspos. Because we use that
// value to position the nested abspos, its start offset would be off by
// exactly one fragmentainer block size.
if (offset->block_offset < current_max_block_size ||
(offset->block_offset == current_max_block_size &&
block_estimate == 0)) {
*start_index = child_index;
offset->block_offset -= used_block_size;
return;
......
......@@ -138,6 +138,7 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
void ComputeStartFragmentIndexAndRelativeOffset(
const ContainingBlockInfo& container_info,
WritingMode default_writing_mode,
LayoutUnit block_estimate,
wtf_size_t* start_index,
LogicalOffset* offset) const;
......
......@@ -1034,7 +1034,6 @@ virtual/layout_ng_block_frag/fast/multicol/vertical-rl/float-edge.html [ Pass ]
virtual/layout_ng_block_frag/fast/multicol/vertical-rl/nested-columns.html [ Pass ]
### Tests failing with LayoutNGBlockFragmentation enabled:
crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-break/block-end-aligned-abspos-nested.html [ Failure ]
crbug.com/1113911 virtual/layout_ng_block_frag/external/wpt/css/css-break/fieldset-001.html [ Failure ]
crbug.com/1154585 virtual/layout_ng_block_frag/external/wpt/css/css-break/ink-overflow-002.html [ Failure ]
crbug.com/1146973 virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html [ Failure ]
......
<!DOCTYPE html>
<link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<!-- Nested abspos with `height: auto` and positioned with the bottom property.
The innermost abspos only is fragmented. -->
<style>
#multicol {
column-count: 2;
width: 100px;
height: 100px;
column-fill: auto;
column-gap: 0px;
background-color: red;
}
.rel {
position: relative;
height: 100px;
width: 50px;
}
.abs {
position: absolute;
width: 50px;
background-color: green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="multicol">
<div class="rel">
<div class="abs" style="bottom: 0;">
<div class="abs" style="bottom: -100px;">
<div style="height: 200px;"></div>
</div>
</div>
</div>
</div>
\ No newline at end of file
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