Commit 002d8b5c authored by Morten Stenshorne's avatar Morten Stenshorne Committed by Commit Bot

[LayoutNG] Ignore column underflow when balancing.

Whatever comes before the start of the column (due to negative margins)
shouldn't affect the block-size of balanced columns, since it won't
take up any space in them.

This fixes two tests, although that means that they'll now crash, :-P
because of incomplete fragment painting support. When loaded manually,
the tests pass, but when run by the test runner, they crash, presumably
due to differences in how the layout tree is treated after the page has
loaded and displayed, or because we're using a different allocator?
There's a pointer to a dead object in there; see crbug.com/994172

Bug: 829028
Change-Id: Ida3a5269f93672e01c3a7572fc919af0b8fede84
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1855739Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Commit-Queue: Morten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#705236}
parent 12d44ebe
......@@ -1984,6 +1984,33 @@ bool NGBlockLayoutAlgorithm::IsFragmentainerOutOfSpace(
return block_offset >= FragmentainerSpaceAvailable();
}
LayoutUnit NGBlockLayoutAlgorithm::OffsetFromFragmentainerStart() const {
DCHECK(container_builder_.BfcBlockOffset());
return ConstraintSpace().FragmentainerOffsetAtBfc() +
*container_builder_.BfcBlockOffset();
}
LayoutUnit NGBlockLayoutAlgorithm::PortionIntersectingWithFragmentainer(
LayoutUnit block_offset,
LayoutUnit block_size) const {
LayoutUnit offset_from_fragmentainer_start =
OffsetFromFragmentainerStart() + block_offset;
// Whatever is before the block-start of the fragmentainer isn't considered to
// intersect with the fragmentainer, so subtract it (by adding the negative
// offset).
if (offset_from_fragmentainer_start < LayoutUnit())
block_size += offset_from_fragmentainer_start;
return block_size;
}
void NGBlockLayoutAlgorithm::PropagateUnbreakableBlockSize(
LayoutUnit block_offset,
LayoutUnit block_size) {
DCHECK(ConstraintSpace().IsInitialColumnBalancingPass());
block_size = PortionIntersectingWithFragmentainer(block_offset, block_size);
container_builder_.PropagateTallestUnbreakableBlockSize(block_size);
}
bool NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
if (Node().ChildrenInline() && !early_break_) {
if (container_builder_.DidBreak() || first_overflowing_line_) {
......@@ -2105,8 +2132,7 @@ NGBlockLayoutAlgorithm::BreakBeforeChildIfNeeded(
// If this is the initial column balancing pass, attempt to make the
// column block-size at least as large as the tallest piece of
// monolithic content and/or block with break-inside:avoid.
container_builder_.PropagateTallestUnbreakableBlockSize(
fragment.BlockSize());
PropagateUnbreakableBlockSize(block_offset, fragment.BlockSize());
}
}
// We only care about soft breaks if we have a fragmentainer block-size.
......
......@@ -221,6 +221,21 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// whether fits within the fragmentainer or not.
bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const;
// Return the block-offset from the start of the fragmentainer, to this node.
LayoutUnit OffsetFromFragmentainerStart() const;
// Return the block-size of the portion that intersects with the
// fragmentainer. The block-offset is relative to this node.
LayoutUnit PortionIntersectingWithFragmentainer(LayoutUnit block_offset,
LayoutUnit block_size) const;
// Propagate the block-size of unbreakable content. This is used to inflate
// the initial minimal column block-size when balancing columns. Unbreakable
// content will actually fragment if the columns aren't large enough, and we
// want to prevent that, if possible.
void PropagateUnbreakableBlockSize(LayoutUnit block_offset,
LayoutUnit block_size);
// Final adjustments before fragment creation. We need to prevent the fragment
// from crossing fragmentainer boundaries, and rather create a break token if
// we're out of space. As part of finalizing we may also discover that we need
......
......@@ -3243,6 +3243,32 @@ TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingLinesAvoidBreakInside2) {
EXPECT_EQ(expectation, dump);
}
TEST_F(NGColumnLayoutAlgorithmTest, ColumnBalancingUnderflow) {
SetBodyInnerHTML(R"HTML(
<style>
#parent {
columns: 3;
column-gap: 10px;
width: 320px;
}
</style>
<div id="container">
<div id="parent">
<div style="break-inside:avoid; margin-top:-100px; width:55px; height:110px;"></div>
</div>
</div>
)HTML");
String dump = DumpFragmentTree(GetElementById("container"));
String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::.
offset:unplaced size:1000x10
offset:0,0 size:320x10
offset:0,0 size:100x10
offset:0,-100 size:55x110
)DUMP";
EXPECT_EQ(expectation, dump);
}
TEST_F(NGColumnLayoutAlgorithmTest, ClassCBreakPointBeforeBfc) {
SetBodyInnerHTML(R"HTML(
<style>
......
......@@ -1051,8 +1051,8 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-after-break.html [ Crash Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-float-with-margin-top-and-line-before-break.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-overflow.html [ Failure ]
crbug.com/829028 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-1.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-2.html [ Failure ]
crbug.com/994172 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-1.html [ Pass Crash ]
crbug.com/994172 virtual/layout_ng_experimental/fast/multicol/balance-line-underflow-2.html [ Pass Crash ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/basic-rtl.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/break-before-first-line-in-first-child.html [ Failure ]
crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/break-in-scrollable.html [ Failure ]
......
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