Commit b95a476f authored by Alison Maher's avatar Alison Maher Committed by Chromium LUCI CQ

[LayoutNG] Paint for abspos elements inside a spanner

In CL:2568852, the containing block chain for spanners was updated in
NG to skip directly to the multi-column container. However, during
paint, this resulted in calculating the incorrect containing layer,
which in certain cases caused us to not paint the abspos element.

This change fixes this by using the more expensive path for
calculating the containing layer when an OOF positioned element is
nested inside of a multi-column.

Bug: 1079031
Change-Id: I5bce5333efbd59d1e58ee5f2ddf43bb539fa9bd7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2580940
Commit-Queue: Alison Maher <almaher@microsoft.com>
Reviewed-by: default avatarMorten Stenshorne <mstensho@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835961}
parent f669bcf1
...@@ -137,6 +137,25 @@ inline PhysicalRect PhysicalVisualOverflowRectAllowingUnset( ...@@ -137,6 +137,25 @@ inline PhysicalRect PhysicalVisualOverflowRectAllowingUnset(
return layout_object.PhysicalVisualOverflowRect(); return layout_object.PhysicalVisualOverflowRect();
} }
PaintLayer* SlowContainingLayer(const PaintLayer* ancestor,
bool* skipped_ancestor,
LayoutObject* layout_object) {
// This is a universal approach to find the containing layer, but it is
// slower.
base::Optional<LayoutObject::AncestorSkipInfo> skip_info;
if (skipped_ancestor)
skip_info.emplace(&ancestor->GetLayoutObject());
while (auto* container = layout_object->Container(
skipped_ancestor ? &*skip_info : nullptr)) {
if (skipped_ancestor && skip_info->AncestorSkipped())
*skipped_ancestor = true;
if (container->HasLayer())
return To<LayoutBoxModelObject>(container)->Layer();
layout_object = container;
}
return nullptr;
}
} // namespace } // namespace
PaintLayerRareData::PaintLayerRareData() PaintLayerRareData::PaintLayerRareData()
...@@ -889,6 +908,14 @@ PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor, ...@@ -889,6 +908,14 @@ PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor,
LayoutObject& layout_object = GetLayoutObject(); LayoutObject& layout_object = GetLayoutObject();
if (layout_object.IsOutOfFlowPositioned()) { if (layout_object.IsOutOfFlowPositioned()) {
// In NG, the containing block chain goes directly from a column spanner to
// the multi-column container. Thus, for an OOF nested inside a spanner, we
// need to find its containing layer through its containing block to handle
// this case correctly. Therefore, we technically only need to take this
// path for OOFs inside an NG spanner. However, doing so for all OOF
// descendants of a multicol container is reasonable enough.
if (layout_object.IsInsideFlowThread())
return SlowContainingLayer(ancestor, skipped_ancestor, &layout_object);
auto can_contain_this_layer = auto can_contain_this_layer =
layout_object.IsFixedPositioned() layout_object.IsFixedPositioned()
? &LayoutObject::CanContainFixedPositionObjects ? &LayoutObject::CanContainFixedPositionObjects
...@@ -914,21 +941,7 @@ PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor, ...@@ -914,21 +941,7 @@ PaintLayer* PaintLayer::ContainingLayer(const PaintLayer* ancestor,
!layout_object.IsColumnSpanAll() && !layout_object.IsRenderedLegend()) !layout_object.IsColumnSpanAll() && !layout_object.IsRenderedLegend())
return Parent(); return Parent();
// This is a universal approach to find containing layer, but is slower than return SlowContainingLayer(ancestor, skipped_ancestor, &layout_object);
// the earlier code.
base::Optional<LayoutObject::AncestorSkipInfo> skip_info;
if (skipped_ancestor)
skip_info.emplace(&ancestor->GetLayoutObject());
auto* object = &layout_object;
while (auto* container =
object->Container(skipped_ancestor ? &*skip_info : nullptr)) {
if (skipped_ancestor && skip_info->AncestorSkipped())
*skipped_ancestor = true;
if (container->HasLayer())
return To<LayoutBoxModelObject>(container)->Layer();
object = container;
}
return nullptr;
} }
PhysicalOffset PaintLayer::ComputeOffsetFromAncestor( PhysicalOffset PaintLayer::ComputeOffsetFromAncestor(
......
<!DOCTYPE html> <!DOCTYPE html>
<br><br><br><br><br>
<p>There should be no red.</p> <p>There should be no red.</p>
<div style="position:absolute; top:0; left:0; background-color:green; height:100px; width:100px;"></div> <div style="position:absolute; top:0; left:0; background-color:green; height:100px; width:100px;"></div>
<div style="position:absolute; bottom:0; right:0; background-color:green; height:100px; width:100px;"></div> <div style="position:absolute; bottom:0; right:0; background-color:green; height:100px; width:100px;"></div>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<title>Abspos elements nested inside a column spanner</title> <title>Abspos elements nested inside a column spanner</title>
<link rel="help" href="href=https://drafts.csswg.org/css-multicol/"> <link rel="help" href="href=https://drafts.csswg.org/css-multicol/">
<link rel="match" href="abspos-containing-block-outside-spanner-ref.html"> <link rel="match" href="abspos-containing-block-outside-spanner-ref.html">
<br><br><br><br><br>
<p>There should be no red.</p> <p>There should be no red.</p>
<div style="position:absolute; top:0; left:0; background-color:red; height:100px; width:100px;"></div> <div style="position:absolute; top:0; left:0; background-color:red; height:100px; width:100px;"></div>
<div style="position:absolute; bottom:0; right:0; background-color:red; height:100px; width:100px;"></div> <div style="position:absolute; bottom:0; right:0; background-color:red; height:100px; width:100px;"></div>
......
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