Commit e4208d10 authored by schenney's avatar schenney Committed by Commit Bot

Fix nested border radius with composited child.

Walk up the layer tree from a layer that needs an
AncestorChildClippingMaskLayer to find all border radius clips to
apply. Several auxiliary changes were required. The code in CLM for
determining if a mask layer is needed has also been reworked to
test against all clips.

Make LayerClipRecorder::CollectRoundedRectClips a public static member
so that CLM can use it to determine if the mask layer is required. Also
expand the conditions in which LayerClipRecorder uses the method to
catch all cases where masks need rounded clips.

Make several PaintLayer methods const, because they can be and we need
them so.

New tests for various cases of border radius where not just the parent
layer needs checking, or where we need to skip over the parent layer and
still check.

R=chrishtr@chromium.org
BUG=672561
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2

Review-Url: https://codereview.chromium.org/2923683002
Cr-Commit-Position: refs/heads/master@{#478814}
parent fc37c219
......@@ -1978,6 +1978,9 @@ crbug.com/157218 compositing/overflow/siblings-composited-with-border-radius-anc
crbug.com/157218 compositing/overflow/grandchild-composited-with-border-radius-ancestor.html [ Failure ]
crbug.com/157218 compositing/overflow/grandchild-with-border-radius-ancestor.html [ Failure ]
crbug.com/157218 compositing/overflow/siblings-composited-with-border-radius-ancestor-one-clipped.html [ Failure ]
crbug.com/157218 compositing/overflow/border-radius-on-grandparent-composited-grandchild.html [ Failure ]
crbug.com/157218 compositing/overflow/border-radius-on-parent-composited-grandchild.html [ Failure ]
crbug.com/157218 compositing/overflow/border-radius-on-two-ancestors-composited-grandchild.html [ Failure ]
# Notes about rebaselined tests:
#
......
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x600
LayoutBlockFlow {HTML} at (0,0) size 800x600
LayoutBlockFlow {BODY} at (8,8) size 784x584
layer at (8,8) size 208x208 clip at (12,12) size 200x200 scrollWidth 308 scrollHeight 308
LayoutBlockFlow {DIV} at (0,0) size 208x208 [border: (4px solid #000000)]
layer at (112,112) size 208x208 backgroundClip at (112,112) size 100x100 clip at (116,116) size 96x96 scrollHeight 408
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 208x208 [bgcolor=#000088] [border: (4px solid #888888)]
layer at (136,16) size 88x408 backgroundClip at (116,116) size 96x96 clip at (116,116) size 96x96
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 88x408 [bgcolor=#008800] [border: (4px solid #AAAAAA)]
<style>
.outermost {
border: 4px solid #000;
width: 200px;
height: 200px;
border-radius: 40px;
overflow: hidden;
}
.middle {
border: 4px solid #888;
background-color: #008;
width: 200px;
height: 200px;
position: relative;
left: 100px;
top: 100px;
overflow: hidden;
}
.inner {
border: 4px solid #AAA;
width: 80px;
height: 400px;
background-color: #080;
position: relative;
left: 20px;
top: -100px;
will-change: transform;
}
</style>
<div class="outermost">
<div class="middle">
<div class="inner">
</div>
</div>
</div>
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x600
LayoutBlockFlow {HTML} at (0,0) size 800x600
LayoutBlockFlow {BODY} at (8,8) size 784x584
layer at (8,8) size 208x208 clip at (12,12) size 200x200 scrollWidth 308 scrollHeight 308
LayoutBlockFlow {DIV} at (0,0) size 208x208 [border: (4px solid #000000)]
layer at (112,112) size 208x208 backgroundClip at (112,112) size 100x100 clip at (116,116) size 96x96 scrollHeight 408
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 208x208 [bgcolor=#000088] [border: (4px solid #888888)]
layer at (136,16) size 88x408 backgroundClip at (116,116) size 96x96 clip at (116,116) size 96x96
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 88x408 [bgcolor=#008800] [border: (4px solid #AAAAAA)]
<style>
.outermost {
border: 4px solid #000;
width: 200px;
height: 200px;
overflow: hidden;
}
.middle {
border: 4px solid #888;
border-radius: 60px;
background-color: #008;
width: 200px;
height: 200px;
position: relative;
left: 100px;
top: 100px;
overflow: hidden;
}
.inner {
border: 4px solid #AAA;
width: 80px;
height: 400px;
background-color: #080;
position: relative;
left: 20px;
top: -100px;
will-change: transform;
}
</style>
<div class="outermost">
<div class="middle">
<div class="inner">
</div>
</div>
</div>
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x600
LayoutBlockFlow {HTML} at (0,0) size 800x600
LayoutBlockFlow {BODY} at (8,8) size 784x584
layer at (8,8) size 208x208 clip at (12,12) size 200x200 scrollWidth 308 scrollHeight 308
LayoutBlockFlow {DIV} at (0,0) size 208x208 [border: (4px solid #000000)]
layer at (112,112) size 208x208 backgroundClip at (112,112) size 100x100 clip at (116,116) size 96x96 scrollHeight 408
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 208x208 [bgcolor=#000088] [border: (4px solid #888888)]
layer at (136,16) size 88x408 backgroundClip at (116,116) size 96x96 clip at (116,116) size 96x96
LayoutBlockFlow (relative positioned) {DIV} at (4,4) size 88x408 [bgcolor=#008800] [border: (4px solid #AAAAAA)]
<style>
.outermost {
border: 4px solid #000;
width: 200px;
height: 200px;
border-radius: 40px;
overflow: hidden;
}
.middle {
border: 4px solid #888;
border-radius: 60px;
background-color: #008;
width: 200px;
height: 200px;
position: relative;
left: 100px;
top: 100px;
overflow: hidden;
}
.inner {
border: 4px solid #AAA;
width: 80px;
height: 400px;
background-color: #080;
position: relative;
left: 20px;
top: -100px;
will-change: transform;
}
</style>
<div class="outermost">
<div class="middle">
<div class="inner">
</div>
</div>
</div>
......@@ -26,7 +26,14 @@
{
"name": "Ancestor Clipping Layer",
"bounds": [285, 300],
"shouldFlattenTransform": false
"shouldFlattenTransform": false,
"maskLayer": [
{
"name": "Ancestor Clipping Mask Layer",
"bounds": [285, 300],
"drawsContent": true
}
]
},
{
"name": "LayoutBlockFlow DIV id='content'",
......
......@@ -55,6 +55,7 @@
#include "core/page/scrolling/StickyPositionScrollingConstraints.h"
#include "core/page/scrolling/TopDocumentRootScrollerController.h"
#include "core/paint/FramePaintTiming.h"
#include "core/paint/LayerClipRecorder.h"
#include "core/paint/ObjectPaintInvalidator.h"
#include "core/paint/PaintInfo.h"
#include "core/paint/PaintLayerPainter.h"
......@@ -507,23 +508,31 @@ void CompositedLayerMapping::UpdateCompositingReasons() {
}
bool CompositedLayerMapping::AncestorRoundedCornersWontClip(
const LayoutBoxModelObject& child,
const LayoutBoxModelObject& clipping_ancestor) {
LayoutRect local_visual_rect = composited_bounds_;
child.MapToVisualRectInAncestorSpace(&clipping_ancestor, local_visual_rect);
FloatRoundedRect rounded_clip_rect =
clipping_ancestor.Style()->GetRoundedInnerBorderFor(
clipping_ancestor.LocalVisualRect());
FloatRect inner_clip_rect = rounded_clip_rect.RadiusCenterRect();
// The first condition catches cases where the child is certainly inside
// the rounded corner portion of the border, and cannot be clipped by
// the rounded portion. The second catches cases where the child is
// entirely outside the rectangular border (ignoring rounded corners) so
// is also unaffected by the rounded corners. In both cases the existing
// rectangular clip is adequate and the mask is unnecessary.
return inner_clip_rect.Contains(FloatRect(local_visual_rect)) ||
!local_visual_rect.Intersects(
EnclosingLayoutRect(rounded_clip_rect.Rect()));
const PaintLayer* compositing_ancestor) {
// Find all clips up to the ancestor compositing container to correctly
// handle nested clips.
LayoutPoint offset_to_clipper;
owning_layer_.ConvertToLayerCoords(compositing_ancestor, offset_to_clipper);
Vector<FloatRoundedRect> rounded_rect_clips;
LayerClipRecorder::CollectRoundedRectClips(
owning_layer_, compositing_ancestor, -offset_to_clipper, true,
LayerClipRecorder::kDoNotIncludeSelfForBorderRadius, rounded_rect_clips);
for (auto clip_rect : rounded_rect_clips) {
FloatRect inner_clip_rect = clip_rect.RadiusCenterRect();
// The first condition catches cases where the child is certainly inside
// the rounded corner portion of the border, and cannot be clipped by
// the rounded portion. The second catches cases where the child is
// entirely outside the rectangular border (ignoring rounded corners) so
// is also unaffected by the rounded corners. In both cases the existing
// rectangular clip is adequate and the mask is unnecessary.
if (!(inner_clip_rect.Contains(FloatRect(composited_bounds_)) ||
!composited_bounds_.Intersects(
EnclosingLayoutRect(clip_rect.Rect())))) {
return false;
}
}
return true;
}
void CompositedLayerMapping::
......@@ -575,11 +584,10 @@ void CompositedLayerMapping::
// TODO(schenney): CSS clips are not applied to composited children, and
// should be via mask or by compositing the parent too.
// https://bugs.chromium.org/p/chromium/issues/detail?id=615870
DCHECK(clipping_container->Style());
owning_layer_is_masked =
owning_layer_is_clipped &&
clipping_container->Style()->HasBorderRadius() &&
!AncestorRoundedCornersWontClip(GetLayoutObject(), *clipping_container);
if (owning_layer_is_clipped) {
owning_layer_is_masked =
!AncestorRoundedCornersWontClip(compositing_ancestor);
}
}
const PaintLayer* CompositedLayerMapping::ScrollParent() {
......
......@@ -488,15 +488,16 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const GraphicsLayerPaintInfo&,
const Vector<GraphicsLayerPaintInfo>& layers);
// Conservatively check that a border-radius clip does not clip a child.
// Conservatively check that a sequence of border-radius clips do not clip
// this layer. The compositing_ancestor is the nearest compositing ancestor
// layer and we can stop checking clips at that layer because higher layer
// clips will be applied elsewhere.
// This is a fast approximate test. Depending on the shape of the child and
// the size of the border radius, this method may return false when in fact
// the size of the clips, this method may return false when in fact
// the child is not clipped. We accept the approximation because most border
// radii are small and the outcome is used to reduce the number of layers,
// not influence correctness.
bool AncestorRoundedCornersWontClip(
const LayoutBoxModelObject& child,
const LayoutBoxModelObject& clipping_ancestor);
bool AncestorRoundedCornersWontClip(const PaintLayer* compositing_ancestor);
// Return true in |owningLayerIsClipped| iff |m_owningLayer|'s compositing
// ancestor is not a descendant (inclusive) of the clipping container for
......
......@@ -1392,6 +1392,199 @@ TEST_P(CompositedLayerMappingTest, AncestorClipMaskRequiredByBorderRadius) {
EXPECT_TRUE(child_mapping->AncestorClippingMaskLayer());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskNotRequiredByNestedBorderRadius) {
// This case has the child within all ancestors and does not require a
// mask.
SetBodyInnerHTML(
"<style>"
" #grandparent {"
" width: 200px; height: 200px; overflow: hidden; border-radius: 25px;"
" }"
" #parent { position: relative; left: 40px; top: 40px; width: 120px;"
" height: 120px; border-radius: 10px; overflow: hidden;"
" }"
" #child { position: relative; left: 10px; top: 10px; width: 100px;"
" height: 100px; background-color: green;"
" will-change: transform;"
" }"
"</style>"
"<div id='grandparent'>"
" <div id='parent'>"
" <div id='child'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
PaintLayer* child_paint_layer =
ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
child_paint_layer->GetCompositedLayerMapping();
ASSERT_TRUE(child_mapping);
EXPECT_TRUE(child_mapping->AncestorClippingLayer());
EXPECT_FALSE(child_mapping->AncestorClippingLayer()->MaskLayer());
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskRequiredByParentBorderRadius) {
// This case has the child within the grandparent but not the parent, and does
// require a mask so that the parent will clip the corners.
SetBodyInnerHTML(
"<style>"
" #grandparent {"
" width: 200px; height: 200px; overflow: hidden; border-radius: 25px;"
" }"
" #parent { position: relative; left: 40px; top: 40px; width: 120px;"
" height: 120px; border-radius: 10px; overflow: hidden;"
" }"
" #child { position: relative; left: 1px; top: 1px; width: 118px;"
" height: 118px; background-color: green;"
" will-change: transform;"
" }"
"</style>"
"<div id='grandparent'>"
" <div id='parent'>"
" <div id='child'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
PaintLayer* child_paint_layer =
ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
child_paint_layer->GetCompositedLayerMapping();
ASSERT_TRUE(child_mapping);
ASSERT_TRUE(child_mapping->AncestorClippingLayer());
EXPECT_TRUE(child_mapping->AncestorClippingLayer()->MaskLayer());
ASSERT_TRUE(child_mapping->AncestorClippingMaskLayer());
const FloatSize layer_size =
child_mapping->AncestorClippingMaskLayer()->Size();
EXPECT_EQ(120, layer_size.Width());
EXPECT_EQ(120, layer_size.Height());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskNotRequiredByParentBorderRadius) {
// This case has the child within the grandparent but not the parent, and does
// not require a mask because the parent does not have border radius
SetBodyInnerHTML(
"<style>"
" #grandparent {"
" width: 200px; height: 200px; overflow: hidden; border-radius: 25px;"
" }"
" #parent { position: relative; left: 40px; top: 40px; width: 120px;"
" height: 120px; overflow: hidden;"
" }"
" #child { position: relative; left: -10px; top: -10px; width: 140px;"
" height: 140px; background-color: green;"
" will-change: transform;"
" }"
"</style>"
"<div id='grandparent'>"
" <div id='parent'>"
" <div id='child'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
PaintLayer* child_paint_layer =
ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
child_paint_layer->GetCompositedLayerMapping();
ASSERT_TRUE(child_mapping);
EXPECT_TRUE(child_mapping->AncestorClippingLayer());
EXPECT_FALSE(child_mapping->AncestorClippingLayer()->MaskLayer());
EXPECT_FALSE(child_mapping->AncestorClippingMaskLayer());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskRequiredByGrandparentBorderRadius1) {
// This case has the child clipped by the grandparent border radius but not
// the parent, and requires a mask to clip to the grandparent. Although in
// an optimized world we would not need this because the parent clips out
// the child before it is clipped by the grandparent.
SetBodyInnerHTML(
"<style>"
" #grandparent {"
" width: 200px; height: 200px; overflow: hidden; border-radius: 25px;"
" }"
" #parent { position: relative; left: 40px; top: 40px; width: 120px;"
" height: 120px; overflow: hidden;"
" }"
" #child { position: relative; left: -10px; top: -10px; width: 180px;"
" height: 180px; background-color: green;"
" will-change: transform;"
" }"
"</style>"
"<div id='grandparent'>"
" <div id='parent'>"
" <div id='child'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
PaintLayer* child_paint_layer =
ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
child_paint_layer->GetCompositedLayerMapping();
ASSERT_TRUE(child_mapping);
ASSERT_TRUE(child_mapping->AncestorClippingLayer());
EXPECT_TRUE(child_mapping->AncestorClippingLayer()->MaskLayer());
ASSERT_TRUE(child_mapping->AncestorClippingMaskLayer());
const FloatSize layer_size =
child_mapping->AncestorClippingMaskLayer()->Size();
EXPECT_EQ(120, layer_size.Width());
EXPECT_EQ(120, layer_size.Height());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskRequiredByGrandparentBorderRadius2) {
// Similar to the previous case, but here we really do need the mask.
SetBodyInnerHTML(
"<style>"
" #grandparent {"
" width: 200px; height: 200px; overflow: hidden; border-radius: 25px;"
" }"
" #parent { position: relative; left: 40px; top: 40px; width: 180px;"
" height: 180px; overflow: hidden;"
" }"
" #child { position: relative; left: -10px; top: -10px; width: 180px;"
" height: 180px; background-color: green;"
" will-change: transform;"
" }"
"</style>"
"<div id='grandparent'>"
" <div id='parent'>"
" <div id='child'></div>"
"</div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
ASSERT_TRUE(child);
PaintLayer* child_paint_layer =
ToLayoutBoxModelObject(child->GetLayoutObject())->Layer();
ASSERT_TRUE(child_paint_layer);
CompositedLayerMapping* child_mapping =
child_paint_layer->GetCompositedLayerMapping();
ASSERT_TRUE(child_mapping);
ASSERT_TRUE(child_mapping->AncestorClippingLayer());
EXPECT_TRUE(child_mapping->AncestorClippingLayer()->MaskLayer());
ASSERT_TRUE(child_mapping->AncestorClippingMaskLayer());
const FloatSize layer_size =
child_mapping->AncestorClippingMaskLayer()->Size();
EXPECT_EQ(160, layer_size.Width());
EXPECT_EQ(160, layer_size.Height());
}
TEST_P(CompositedLayerMappingTest,
AncestorClipMaskNotRequiredByBorderRadiusInside) {
// Verify that we do not create the mask layer when the child is contained
......
......@@ -29,10 +29,13 @@ LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphics_context,
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
bool painting_masks =
(paint_flags & kPaintLayerPaintingChildClippingMaskPhase ||
paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase);
Vector<FloatRoundedRect> rounded_rects;
if (clip_root && clip_rect.HasRadius()) {
CollectRoundedRectClips(*layout_object.Layer(), clip_root, graphics_context,
fragment_offset, paint_flags, rule, rounded_rects);
if (clip_root && (clip_rect.HasRadius() || painting_masks)) {
CollectRoundedRectClips(*layout_object.Layer(), clip_root, fragment_offset,
painting_masks, rule, rounded_rects);
}
graphics_context_.GetPaintController().CreateAndAppend<ClipDisplayItem>(
......@@ -59,9 +62,8 @@ static bool InContainingBlockChain(PaintLayer* start_layer,
void LayerClipRecorder::CollectRoundedRectClips(
PaintLayer& paint_layer,
const PaintLayer* clip_root,
GraphicsContext& context,
const LayoutPoint& fragment_offset,
PaintLayerFlags paint_flags,
const LayoutPoint& offset_within_layer,
bool cross_composited_scrollers,
BorderRadiusClippingRule rule,
Vector<FloatRoundedRect>& rounded_rect_clips) {
// If the clip rect has been tainted by a border radius, then we have to walk
......@@ -78,15 +80,13 @@ void LayerClipRecorder::CollectRoundedRectClips(
// frame to update the clip. We only want to make sure that the mask layer
// is properly clipped so that it can in turn clip the scrolled contents in
// the compositor.
if (layer->NeedsCompositedScrolling() &&
!(paint_flags & kPaintLayerPaintingChildClippingMaskPhase ||
paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase))
if (!cross_composited_scrollers && layer->NeedsCompositedScrolling())
break;
if (layer->GetLayoutObject().HasOverflowClip() &&
layer->GetLayoutObject().Style()->HasBorderRadius() &&
InContainingBlockChain(&paint_layer, layer)) {
LayoutPoint delta(fragment_offset);
LayoutPoint delta(offset_within_layer);
layer->ConvertToLayerCoords(clip_root, delta);
// The PaintLayer's size is pixel-snapped if it is a LayoutBox. We can't
......
......@@ -53,15 +53,25 @@ class CORE_EXPORT LayerClipRecorder {
~LayerClipRecorder();
private:
void CollectRoundedRectClips(PaintLayer&,
const PaintLayer* clip_root,
GraphicsContext&,
const LayoutPoint& fragment_offset,
PaintLayerFlags,
BorderRadiusClippingRule,
Vector<FloatRoundedRect>& rounded_rect_clips);
// Build a vector of the border radius clips that should be applied to
// the given PaintLayer, walking up the paint layer tree to the clip_root.
// The offset_within_layer is an offset to apply to the clip to position it
// in the required clipping coordinates (for cases when the painting
// coordinate system is offset from the layer coordinate system).
// cross_composited_scrollers should be true when the search for clips should
// continue even if the clipping layer is painting into a composited scrolling
// layer, as when painting a mask for a child of the scroller.
// The BorderRadiusClippingRule defines whether clips on the PaintLayer itself
// are included. Output is appended to rounded_rect_clips.
static void CollectRoundedRectClips(
PaintLayer&,
const PaintLayer* clip_root,
const LayoutPoint& offset_within_layer,
bool cross_composited_scrollers,
BorderRadiusClippingRule,
Vector<FloatRoundedRect>& rounded_rect_clips);
private:
GraphicsContext& graphics_context_;
const LayoutBoxModelObject& layout_object_;
DisplayItem::Type clip_type_;
......
......@@ -1591,7 +1591,7 @@ void PaintLayer::AppendSingleFragmentIgnoringPagination(
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
const LayoutSize& sub_pixel_accumulation) {
const LayoutSize& sub_pixel_accumulation) const {
PaintLayerFragment fragment;
ClipRectsContext clip_rects_context(root_layer, clip_rects_cache_slot,
overlay_scrollbar_clip_behavior,
......@@ -1622,7 +1622,7 @@ void PaintLayer::CollectFragments(
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
const LayoutSize& sub_pixel_accumulation,
const LayoutRect* layer_bounding_box) {
const LayoutRect* layer_bounding_box) const {
// For unpaginated layers, there is only one fragment. We also avoid
// fragmentation when compositing, due to implementation limitations.
if (!EnclosingPaginationLayer() ||
......
......@@ -875,7 +875,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = 0,
const LayoutSize& sub_pixel_accumulation = LayoutSize());
const LayoutSize& sub_pixel_accumulation = LayoutSize()) const;
void CollectFragments(
PaintLayerFragments&,
const PaintLayer* root_layer,
......@@ -886,7 +886,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = 0,
const LayoutSize& sub_pixel_accumulation = LayoutSize(),
const LayoutRect* layer_bounding_box = 0);
const LayoutRect* layer_bounding_box = 0) const;
LayoutPoint LayoutBoxLocation() const {
return GetLayoutObject().IsBox() ? ToLayoutBox(GetLayoutObject()).Location()
......
......@@ -427,15 +427,18 @@ PaintResult PaintLayerPainter::PaintLayerContents(
? kUncachedClipRects
: kPaintingClipRects;
LayoutPoint offset_to_clipper;
PaintLayer* paint_layer_for_fragments = &paint_layer_;
const PaintLayer* paint_layer_for_fragments = &paint_layer_;
if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase) {
// Compute fragments and their clips with respect to the clipping
// container. The paint rect is in this layer's space, so convert it
// to the clipper's layer's space. The rootLayer is also changed to
// the clipper's layer to simplify coordinate system adjustments.
// The change to rootLayer must persist to correctly record the clips.
// Compute fragments and their clips with respect to the outermost
// clipping container. This handles nested border radius by including
// all of them in the mask.
//
// The paint rect is in this layer's space, so convert it to the clipper's
// layer's space. The rootLayer is also changed to the clipper's layer to
// simplify coordinate system adjustments. The change to rootLayer must
// persist to correctly record the clips.
paint_layer_for_fragments =
paint_layer_.ClippingContainer()->EnclosingLayer();
paint_layer_.EnclosingLayerWithCompositedLayerMapping(kExcludeSelf);
local_painting_info.root_layer = paint_layer_for_fragments;
paint_layer_.ConvertToLayerCoords(local_painting_info.root_layer,
offset_to_clipper);
......@@ -1010,9 +1013,6 @@ void PaintLayerPainter::PaintFragmentWithPhase(
break;
}
// TODO(schenney): Nested border-radius clips are not applied to composited
// children, probably due to an incorrect clipRoot.
// https://bugs.chromium.org/p/chromium/issues/detail?id=672561
clip_recorder.emplace(context, paint_layer_.GetLayoutObject(), clip_type,
clip_rect, painting_info.root_layer,
fragment.pagination_offset, paint_flags,
......
......@@ -96,7 +96,7 @@ struct PaintLayerPaintingInfo {
GlobalPaintFlags GetGlobalPaintFlags() const { return global_paint_flags_; }
// TODO(jchaffraix): We should encapsulate all these fields.
PaintLayer* root_layer;
const PaintLayer* root_layer;
LayoutRect paint_dirty_rect; // relative to rootLayer;
LayoutSize sub_pixel_accumulation;
IntSize scroll_offset_accumulation;
......
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