0

[LayoutNG] Encompass fragmentainer in consumed block-size.

This doesn't make a lot of difference to the NG layout engine (except
that consumed block-size may now be larger than the block-size of the
preceding fragments combined). The reason for this change is so that
we'll write the correct offsets back to the legacy tree. This was wrong
for overflowing content whose containing block ended in an earlier
fragmentatainer, and that caused trouble for things like offsetTop.

This change requires us to replace some logic in the fieldset layout
algorithm that calculates the amount of space that a legend "eats" from
its containing fieldset. It's actually slightly simpler now. :)

Bug: 829028
Change-Id: I84c6188e61ee3e9eaff80f595935768fa68412bb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2429027
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Reviewed-by: Alison Maher <almaher@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#811630}
This commit is contained in:
Morten Stenshorne
2020-09-29 10:49:45 +00:00
committed by Commit Bot
parent 6e1885ac3e
commit cb23a832dd
3 changed files with 49 additions and 41 deletions

@ -157,6 +157,9 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
}
}
LogicalSize adjusted_padding_box_size =
ShrinkLogicalSize(border_box_size_, borders_);
NGBlockNode legend = Node().GetRenderedLegend();
if (legend) {
if (!IsResumingLayout(BreakToken()))
@ -168,40 +171,35 @@ NGBreakStatus NGFieldsetLayoutAlgorithm::LayoutChildren() {
minimum_border_box_block_size_ =
intrinsic_block_size_ + padding_.BlockSum() + borders_.block_end;
}
}
LogicalSize adjusted_padding_box_size =
ShrinkLogicalSize(border_box_size_, borders_);
if (adjusted_padding_box_size.block_size != kIndefiniteSize) {
DCHECK_NE(border_box_size_.block_size, kIndefiniteSize);
LayoutUnit legend_size_contribution;
if (IsResumingLayout(BreakToken())) {
// The legend has been laid out in previous fragments, and
// adjusted_padding_box_size will need to be adjusted further to account
// for block size taken up by the legend.
//
// To calculate its size contribution to the border block-start area,
// take the difference between the previously consumed block-size of the
// fieldset excluding its specified block-start border, and the consumed
// block-size of the contents wrapper.
LayoutUnit content_consumed_block_size =
content_break_token ? content_break_token->ConsumedBlockSize()
: LayoutUnit();
legend_size_contribution = consumed_block_size_ - borders_.block_start -
content_consumed_block_size;
} else {
// We're at the first fragment. The current layout position
// (intrinsic_block_size_) is at the outer block-end edge of the legend
// or just after the block-start border, whichever is larger.
legend_size_contribution = intrinsic_block_size_ - borders_.block_start;
}
// If the legend has been laid out in previous fragments,
// adjusted_padding_box_size will need to be adjusted further to account for
// block size taken up by the legend.
if (adjusted_padding_box_size.block_size != kIndefiniteSize && legend) {
LayoutUnit content_consumed_block_size =
content_break_token ? content_break_token->ConsumedBlockSize()
: LayoutUnit();
// Calculate the amount of the border block-start that was consumed in
// previous fragments.
LayoutUnit consumed_border_block_start =
borders_.block_start - intrinsic_block_size_;
// Calculate the amount of the border block-end that was consumed in
// previous fragments.
DCHECK_NE(border_box_size_.block_size, kIndefiniteSize);
LayoutUnit consumed_border_block_end =
std::max(consumed_block_size_ -
(border_box_size_.block_size - borders_.block_end),
LayoutUnit());
LayoutUnit legend_block_size =
consumed_block_size_ - content_consumed_block_size -
consumed_border_block_start - consumed_border_block_end;
DCHECK_GE(legend_block_size, LayoutUnit());
adjusted_padding_box_size.block_size =
std::max(padding_.BlockSum(),
adjusted_padding_box_size.block_size - legend_block_size);
adjusted_padding_box_size.block_size = std::max(
adjusted_padding_box_size.block_size - legend_size_contribution,
padding_.BlockSum());
}
}
// Proceed with normal fieldset children (excluding the rendered legend). They

@ -244,7 +244,13 @@ bool FinishFragmentation(NGBlockNode node,
LayoutUnit fragments_total_block_size = builder->FragmentsTotalBlockSize();
LayoutUnit desired_block_size =
fragments_total_block_size - previously_consumed_block_size;
DCHECK_GE(desired_block_size, LayoutUnit());
// Consumed block-size stored in the break tokens is always stretched to the
// fragmentainers. If this wasn't also the case for all previous fragments
// (because we reached the end of the node and were overflowing), we may end
// up with negative values here.
desired_block_size = desired_block_size.ClampNegativeToZero();
LayoutUnit intrinsic_block_size = builder->IntrinsicBlockSize();
LayoutUnit final_block_size = desired_block_size;
@ -318,8 +324,18 @@ bool FinishFragmentation(NGBlockNode node,
sides.block_end = false;
builder->SetSidesToInclude(sides);
builder->SetConsumedBlockSize(previously_consumed_block_size +
final_block_size);
LayoutUnit consumed_here = final_block_size;
if (builder->DidBreakSelf() || builder->HasChildBreakInside()) {
// If this node is to be resumed in the next fragmentainer, consumed
// block-size always includes the entire remainder of the fragmentainer. The
// frament itself will only do that unless we've reached the end of the node
// (and we are breaking because of overflow). We include the entire
// fragmentainer in consumed block-size in order to write offsets correctly
// back to legacy layout, which would otherwise become incorrect for
// overflowing content.
consumed_here = std::max(consumed_here, space_left);
}
builder->SetConsumedBlockSize(previously_consumed_block_size + consumed_here);
builder->SetFragmentBlockSize(final_block_size);
if (builder->FoundColumnSpanner())

@ -1083,11 +1083,6 @@ crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/event-offset-in-nest
crbug.com/1061423 virtual/layout_ng_block_frag/fast/multicol/flipped-blocks-hit-test.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary-fixed-multicol-height.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-moved-by-child-line-and-unbreakable.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-block-and-unbreakable.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-block.html [ Failure Timeout ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line-and-unbreakable.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/forced-break-in-nested-columns.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/forced-break-too-short-column.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/hit-test-above-or-below.html [ Failure ]
@ -1165,7 +1160,6 @@ crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/abspos-after-forced
crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ]
crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/content-preceding-first-fragmentainer.html [ Crash Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/float-after-forced-break.html [ Failure ]
crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/overflow-crossing-boundary.html [ Failure ]
crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/relayout-abspos.html [ Failure ]
### With LayoutNGFragmentTraversal (and LayoutNGFragmentItem) enabled: