Skip to content
Permalink
Browse files
[Multicol] Incorrect clipping when a layer is present between the col…
…umn and the content layer

https://bugs.webkit.org/show_bug.cgi?id=238854

Reviewed by Darin Adler.

Multicol keeps track of both visual and layout overflow of children
to determine pagination clips for fragments. For layout overflow
this works fine, but for visual overflow RenderBox::addOverflowFromChild
skips self painting layers, needed amongst others for position:relative
elements, so this was not taken into account for pagination clipping.

Rework RenderBox::addOverflowFromChild to also take into account
visual overflow for elements that use a self painting layer, in order
to allow (visual) overflow of elements that do not cause column breaks
as specified in https://www.w3.org/TR/css-multicol-1/#overflow.

* LayoutTests/TestExpectations:
* LayoutTests/fast/multicol/positioned-split.html:
* LayoutTests/fast/multicol/positioned-split-expected.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/relative-child-overflowing-container-expected.xht: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/relative-child-overflowing-container.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/relative-child-overflowing-column-gap-expected.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/relative-child-overflowing-column-gap-ref.html: Added.
* LayoutTests/imported/w3c/web-platform-tests/css/css-multicol/relative-child-overflowing-column-gap.html: Added.
* LayoutTests/platform/glib/fast/multicol/positioned-split-expected.txt: Removed.
* LayoutTests/platform/gtk/fast/multicol/positioned-split-expected.png: Removed.
* LayoutTests/platform/ios/fast/multicol/positioned-split-expected.txt: Removed.
* LayoutTests/platform/mac/fast/multicol/positioned-split-expected.png: Removed.
* LayoutTests/platform/mac/fast/multicol/positioned-split-expected.txt: Removed.
* LayoutTests/platform/win/fast/multicol/positioned-split-expected.txt: Removed.
* LayoutTests/platform/wincairo/fast/multicol/positioned-split-expected.txt: Removed.
* Source/WebCore/rendering/RenderBlock.cpp:
(WebCore::RenderBlock::addOverflowFromChildren):
* Source/WebCore/rendering/RenderBox.cpp:
(WebCore::RenderBox::addOverflowFromChild):

Canonical link: https://commits.webkit.org/256953@main
  • Loading branch information
rwlbuis committed Nov 22, 2022
1 parent 7b53609 commit 3fc32a416db0c58ed77f9f3b7414e00c7eba9ebb
Show file tree
Hide file tree
Showing 17 changed files with 188 additions and 162 deletions.
@@ -4896,9 +4896,6 @@ webkit.org/b/241778 [ Debug ] imported/w3c/web-platform-tests/css/css-contain/co
# Flaky css-contain test
imported/w3c/web-platform-tests/css/css-contain/content-visibility/animation-display-lock.html [ Failure Pass ]

# Multicolumn does not paint the horizontal overflow area of a relative child.
webkit.org/b/41796 imported/w3c/web-platform-tests/css/css-contain/contain-size-monolithic-002.html [ ImageOnlyFailure ]

# Scrollbar displays are different.
imported/w3c/web-platform-tests/css/css-contain/contain-size-block-003.html [ ImageOnlyFailure ]
imported/w3c/web-platform-tests/css/css-contain/contain-size-inline-block-003.html [ ImageOnlyFailure ]
@@ -0,0 +1,32 @@
<!DOCTYPE html>
<style>
.columns {
position: relative;
border: 2px solid black;
height: 300px;
}
.abs1, .abs2 {
position: absolute;
background-color: lightgray;
width: 300px;
}
.abs1 {
height: 50px;
bottom: 0;
}
.abs2 {
left: 50%;
height: 150px;
}
</style>
<div class="columns">
<div class="abs1">
This text should paginate across the columns.<br>
This text should paginate across the columns.<br>
</div>
<div class="abs2">
This text should paginate across the columns.<br>
This text should paginate across the columns.<br>
This text should paginate across the columns.<br>
</div>
</div>
@@ -1,4 +1,4 @@
<div style="-webkit-column-count:2; -webkit-column-fill:auto; column-count:2; column-fill:auto; border:2px solid black; height:300px;">
<div style="-webkit-column-gap: 0; -webkit-column-count:2; -webkit-column-fill:auto; column-count:2; column-fill:auto; border:2px solid black; height:300px;">
<div style="height:250px"></div>
<div style="position:relative">
<div style="position:absolute;height:200px;width:300px;background-color:lightgray">
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<title>Relative child can overflow onto the column gap area</title>
<style>
body {
margin: 0px;
}

.child {
width: 100px;
height: 50px;
background: green;
}

.child2 {
width: 100px;
height: 50px;
background: green;
position: absolute;
left: 125px;
top: 0px;
}
</style>
<div class="child"></div>
<div class="child2"></div>
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<title>Relative child can overflow onto the column gap area</title>
<style>
body {
margin: 0px;
}

.child {
width: 100px;
height: 50px;
background: green;
}

.child2 {
width: 100px;
height: 50px;
background: green;
position: absolute;
left: 125px;
top: 0px;
}
</style>
<div class="child"></div>
<div class="child2"></div>
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<title>Relative child can overflow onto the column gap area</title>
<link rel="help" href="https://drafts.csswg.org/css-multicol/">
<link rel="match" href="relative-child-overflowing-column-gap-ref.html">

<style>
body {
margin: 0px;
}

.multicol {
width: 200px;
column-count: 2;
column-gap: 50px;
}

.relative-layer {
position: relative;
}

.child {
width: 100px;
height: 100px;
background: green;
}
</style>
<div class="multicol">
<div class="relative-layer">
<div class="child"></div>
</div>
</div>
@@ -0,0 +1,19 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
<style type="text/css"><![CDATA[
div
{
background-color: green;
height: 100px;
width: 100px;
}
]]></style>
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div></div>
</body>
</html>
@@ -0,0 +1,28 @@
<!DOCTYPE html>
<title>Relative child wider than the column container should overflow the container</title>
<link rel="help" href="https://drafts.csswg.org/css-multicol/">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">

<style>
.multicol {
width: 0px;
column-count: 2;
column-gap: 0px;
}

.relative-layer {
position: relative;
}

.child {
width: 100px;
height: 200px;
background: green;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div class="multicol">
<div class="relative-layer">
<div class="child"></div>
</div>
</div>

This file was deleted.

Binary file not shown.

This file was deleted.

Binary file not shown.

This file was deleted.

This file was deleted.

This file was deleted.

@@ -672,16 +672,16 @@ void RenderBlock::layoutBlock(bool, LayoutUnit)

void RenderBlock::addOverflowFromChildren()
{
if (childrenInline())
if (childrenInline()) {
addOverflowFromInlineChildren();
else
addOverflowFromBlockChildren();

// If this block is flowed inside a flow thread, make sure its overflow is propagated to the containing fragments.
if (m_overflow) {
if (RenderFragmentedFlow* containingFragmentedFlow = enclosingFragmentedFlow())
containingFragmentedFlow->addFragmentsVisualOverflow(this, m_overflow->visualOverflowRect());
}
// If this block is flowed inside a flow thread, make sure its overflow is propagated to the containing fragments.
if (m_overflow) {
if (auto* flow = enclosingFragmentedFlow())
flow->addFragmentsVisualOverflow(this, m_overflow->visualOverflowRect());
}
} else
addOverflowFromBlockChildren();
}

// Overflow is always relative to the border-box of the element in question.
@@ -4993,14 +4993,30 @@ void RenderBox::addOverflowFromChild(const RenderBox* child, const LayoutSize& d
if (paintContainmentApplies())
return;

// Add in visual overflow from the child. Even if the child clips its overflow, it may still
// Add in visual overflow from the child. Even if the child clips its overflow, it may still
// have visual overflow of its own set from box shadows or reflections. It is unnecessary to propagate this
// overflow if we are clipping our own overflow.
if (child->hasSelfPaintingLayer() || hasPotentiallyScrollableOverflow())
if (hasPotentiallyScrollableOverflow())
return;
LayoutRect childVisualOverflowRect = child->visualOverflowRectForPropagation(&style());
childVisualOverflowRect.move(delta);
addVisualOverflow(childVisualOverflowRect);

std::optional<LayoutRect> childVisualOverflowRect;
auto computeChildVisualOverflowRect = [&] () {
childVisualOverflowRect = child->visualOverflowRectForPropagation(&style());
childVisualOverflowRect->move(delta);
};
// If this block is flowed inside a flow thread, make sure its overflow is propagated to the containing fragments.
if (fragmentedFlow) {
computeChildVisualOverflowRect();
fragmentedFlow->addFragmentsVisualOverflow(this, *childVisualOverflowRect);
} else {
// Update our visual overflow in case the child spills out the block, but only if we were going to paint
// the child block ourselves.
if (child->hasSelfPaintingLayer())
return;
}
if (!childVisualOverflowRect)
computeChildVisualOverflowRect();
addVisualOverflow(*childVisualOverflowRect);
}

void RenderBox::addLayoutOverflow(const LayoutRect& rect)

0 comments on commit 3fc32a4

Please sign in to comment.