Commit 969ccc73 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Don't skip fragment clip if there are other clips for composited layers

Composited layer under multicol is still not fully correctly
supported. Currently we don't allow fragmentation of composited layers,
and skip fragment clip for them. However, if there are other clips below
the fragment clip, we should not skip fragment clip to ensure the other
clips are correctly applied. This is still not fully correct (see the
comment in the code for details), but the result is less broken in many
cases. Hopefully we'll fully fix the issue in
CompositeAfterPaint+LayoutNG-box-fragments.

Bug: 976187
Change-Id: Ica9acc71f0d1204d6380f1bcac3e2159631d63e9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1670413
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarChris Harrelson <chrishtr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#671480}
parent 668b4fd1
...@@ -2491,38 +2491,48 @@ void PaintPropertyTreeBuilder::InitSingleFragmentFromParent( ...@@ -2491,38 +2491,48 @@ void PaintPropertyTreeBuilder::InitSingleFragmentFromParent(
// should also skip any fragment clip created by the skipped pagination // should also skip any fragment clip created by the skipped pagination
// container. We also need to skip fragment clip if the object is a paint // container. We also need to skip fragment clip if the object is a paint
// invalidation container which doesn't allow fragmentation. // invalidation container which doesn't allow fragmentation.
// TODO(crbug.com/803649): This may also skip necessary clips under the bool skip_fragment_clip_for_composited_layer =
// skipped fragment clip. !RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
if (object_.IsColumnSpanAll() || object_.IsPaintInvalidationContainer() &&
(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && ToLayoutBoxModelObject(object_).Layer()->EnclosingPaginationLayer();
object_.IsPaintInvalidationContainer() && if (!skip_fragment_clip_for_composited_layer && !object_.IsColumnSpanAll())
ToLayoutBoxModelObject(object_).Layer()->EnclosingPaginationLayer())) { return;
if (const auto* pagination_layer_in_tree_hierarchy =
object_.Parent()->EnclosingLayer()->EnclosingPaginationLayer()) { const auto* pagination_layer_in_tree_hierarchy =
const auto& clip_container = object_.Parent()->EnclosingLayer()->EnclosingPaginationLayer();
pagination_layer_in_tree_hierarchy->GetLayoutObject(); if (!pagination_layer_in_tree_hierarchy)
const auto* properties = clip_container.FirstFragment().PaintProperties(); return;
if (properties && properties->FragmentClip()) {
// However, because we don't allow an object's clip to escape the const auto& clip_container =
// output clip of the object's effect, we can't skip fragment clip if pagination_layer_in_tree_hierarchy->GetLayoutObject();
// between this object and the container there is any effect that has const auto* properties = clip_container.FirstFragment().PaintProperties();
// an output clip. TODO(crbug.com/803649): Fix this workaround. if (!properties || !properties->FragmentClip())
const auto& clip_container_effect = clip_container.FirstFragment() return;
.LocalBorderBoxProperties()
.Effect() // Skip fragment clip for composited layer only when there are no other clips.
.Unalias(); // TODO(crbug.com/803649): This is still incorrect if this object first
for (const auto* effect = // appear in the second or later fragment of its parent.
&context_.fragments[0].current_effect->Unalias(); if (skip_fragment_clip_for_composited_layer &&
effect && effect != &clip_container_effect; properties->FragmentClip() != context_.fragments[0].current.clip)
effect = SafeUnalias(effect->Parent())) { return;
if (effect->OutputClip())
return; // However, because we don't allow an object's clip to escape the
} // output clip of the object's effect, we can't skip fragment clip if
context_.fragments[0].current.clip = // between this object and the container there is any effect that has
properties->FragmentClip()->Parent(); // an output clip. TODO(crbug.com/803649): Fix this workaround.
} const auto& clip_container_effect = clip_container.FirstFragment()
} .LocalBorderBoxProperties()
.Effect()
.Unalias();
for (const auto* effect = &context_.fragments[0].current_effect->Unalias();
effect && effect != &clip_container_effect;
effect = SafeUnalias(effect->Parent())) {
if (effect->OutputClip())
return;
} }
// Skip the fragment clip.
context_.fragments[0].current.clip = properties->FragmentClip()->Parent();
} }
void PaintPropertyTreeBuilder::UpdateCompositedLayerPaginationOffset() { void PaintPropertyTreeBuilder::UpdateCompositedLayerPaginationOffset() {
......
...@@ -5841,6 +5841,28 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerSkipsFragmentClip) { ...@@ -5841,6 +5841,28 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerSkipsFragmentClip) {
.Clip()); .Clip());
} }
TEST_P(PaintPropertyTreeBuilderTest, CompositedLayerUnderClipUnerMulticol) {
SetBodyInnerHTML(R"HTML(
<div id="multicol" style="columns: 2">
<div id="clip" style="height: 100px; overflow: hidden">
<div id="composited"
style="width: 200px; height: 200px; will-change: transform">
</div>
</div>
</div>
)HTML");
const auto* flow_thread =
GetLayoutObjectByElementId("multicol")->SlowFirstChild();
const auto* fragment_clip =
flow_thread->FirstFragment().PaintProperties()->FragmentClip();
const auto* clip_properties = PaintPropertiesForElement("clip");
const auto* composited = GetLayoutObjectByElementId("composited");
EXPECT_EQ(clip_properties->OverflowClip(),
&composited->FirstFragment().LocalBorderBoxProperties().Clip());
EXPECT_EQ(fragment_clip, clip_properties->OverflowClip()->Parent());
}
TEST_P(PaintPropertyTreeBuilderTest, RepeatingFixedPositionInPagedMedia) { TEST_P(PaintPropertyTreeBuilderTest, RepeatingFixedPositionInPagedMedia) {
SetBodyInnerHTML(R"HTML( SetBodyInnerHTML(R"HTML(
<div id="fixed" style="position: fixed; top: 20px; left: 20px"> <div id="fixed" style="position: fixed; top: 20px; left: 20px">
......
<!DOCTYPE html>
<div style="width: 100px; height: 100px; background: green"></div>
<!DOCTYPE html>
<link rel="help" href="https://drafts.csswg.org/css-multicol">
<link rel="match" href="composited-under-clip-under-multicol-ref.html">
<meta name="assert" content="Test that clip under multicol is correctly applied on composited child">
<style>
.columns {
columns: 2;
column-gap: 20px;
width: 220px;
height: 100px;
}
.clip {
height: 100px;
overflow: hidden;
}
.composited {
will-change: transform;
margin-top: -20px;
margin-left: -20px;
border: 20px solid red;
width: 200px;
height: 200px;
background: green;
}
</style>
<div class="columns">
<div class="clip">
<div class="composited"></div>
</div>
<div class="clip"></div>
</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