Index: third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
index 93fc1fc50f8104c5db3e548ec07256bf3fd67305..d1230d559749ac8654ac950300551e1afe27aacc 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
@@ -9,6 +9,7 @@ |
#include "core/paint/ClipPathClipper.h" |
#include "core/paint/FilterPainter.h" |
#include "core/paint/LayerClipRecorder.h" |
+#include "core/paint/LayoutObjectDrawingRecorder.h" |
#include "core/paint/ObjectPaintProperties.h" |
#include "core/paint/PaintInfo.h" |
#include "core/paint/PaintLayer.h" |
@@ -361,7 +362,8 @@ PaintResult PaintLayerPainter::paintLayerContents( |
// scrolling contents and scrollbars. |
if (m_paintLayer.layoutObject()->hasClipPath() && |
(!m_paintLayer.needsCompositedScrolling() || |
- (paintFlags & PaintLayerPaintingChildClippingMaskPhase))) { |
+ (paintFlags & (PaintLayerPaintingChildClippingMaskPhase | |
+ PaintLayerPaintingAncestorClippingMaskPhase)))) { |
paintingInfo.ancestorHasClipPathClipping = true; |
LayoutRect referenceBox(m_paintLayer.boxForClipPath()); |
@@ -412,19 +414,35 @@ PaintResult PaintLayerPainter::paintLayerContents( |
ClipRectsCacheSlot cacheSlot = (paintFlags & PaintLayerUncachedClipRects) |
? UncachedClipRects |
: PaintingClipRects; |
+ LayoutPoint offsetToClipper; |
+ PaintLayer* paintLayerForFragments = &m_paintLayer; |
+ if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { |
+ // 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. |
+ paintLayerForFragments = |
+ m_paintLayer.clippingContainer()->enclosingLayer(); |
+ localPaintingInfo.rootLayer = paintLayerForFragments; |
+ m_paintLayer.convertToLayerCoords(localPaintingInfo.rootLayer, |
+ offsetToClipper); |
+ localPaintingInfo.paintDirtyRect.moveBy(offsetToClipper); |
+ } |
+ |
// TODO(trchen): We haven't decided how to handle visual fragmentation with |
// SPv2. Related thread |
// https://groups.google.com/a/chromium.org/forum/#!topic/graphics-dev/81XuWFf-mxM |
if (fragmentPolicy == ForceSingleFragment || |
RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
- m_paintLayer.appendSingleFragmentIgnoringPagination( |
+ paintLayerForFragments->appendSingleFragmentIgnoringPagination( |
layerFragments, localPaintingInfo.rootLayer, |
localPaintingInfo.paintDirtyRect, cacheSlot, |
IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
localPaintingInfo.subPixelAccumulation); |
} else if (isFixedPositionObjectInPagedMedia()) { |
PaintLayerFragments singleFragment; |
- m_paintLayer.appendSingleFragmentIgnoringPagination( |
+ paintLayerForFragments->appendSingleFragmentIgnoringPagination( |
singleFragment, localPaintingInfo.rootLayer, |
localPaintingInfo.paintDirtyRect, cacheSlot, |
IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
@@ -432,11 +450,23 @@ PaintResult PaintLayerPainter::paintLayerContents( |
repeatFixedPositionObjectInPages(singleFragment[0], paintingInfo, |
layerFragments); |
} else { |
- m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
- localPaintingInfo.paintDirtyRect, cacheSlot, |
- IgnoreOverlayScrollbarSize, |
- respectOverflowClip, &offsetFromRoot, |
- localPaintingInfo.subPixelAccumulation); |
+ paintLayerForFragments->collectFragments( |
+ layerFragments, localPaintingInfo.rootLayer, |
+ localPaintingInfo.paintDirtyRect, cacheSlot, |
+ IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
+ localPaintingInfo.subPixelAccumulation); |
+ } |
+ |
+ if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { |
+ // Fragment offsets have been computed in the clipping container's |
+ // layer's coordinate system, but for the rest of painting we need |
+ // them in the layer coordinate. So move them and the foreground rect |
+ // that is also in the clipper's space. |
+ LayoutSize negativeOffset(-offsetToClipper.x(), -offsetToClipper.y()); |
+ for (auto& fragment : layerFragments) { |
+ fragment.foregroundRect.move(negativeOffset); |
+ fragment.paginationOffset.move(negativeOffset); |
+ } |
} |
if (shouldPaintContent) { |
@@ -537,7 +567,8 @@ PaintResult PaintLayerPainter::paintLayerContents( |
shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && |
!selectionOnly; |
bool shouldPaintClippingMask = |
- (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && |
+ (paintFlags & (PaintLayerPaintingChildClippingMaskPhase | |
+ PaintLayerPaintingAncestorClippingMaskPhase)) && |
shouldPaintContent && !selectionOnly; |
if (shouldPaintMask) |
@@ -722,7 +753,7 @@ PaintResult PaintLayerPainter::paintLayerWithTransform( |
if (needsToClip(paintingInfo, clipRectForFragment)) { |
clipRecorder.emplace(context, *parentLayer->layoutObject(), |
DisplayItem::kClipLayerParent, clipRectForFragment, |
- &paintingInfo, fragment.paginationOffset, |
+ paintingInfo.rootLayer, fragment.paginationOffset, |
paintFlags); |
} |
} |
@@ -860,7 +891,7 @@ void PaintLayerPainter::paintOverflowControlsForFragments( |
if (needsToClip(localPaintingInfo, fragment.backgroundRect)) { |
clipRecorder.emplace(context, *m_paintLayer.layoutObject(), |
DisplayItem::kClipLayerOverflowControls, |
- fragment.backgroundRect, &localPaintingInfo, |
+ fragment.backgroundRect, localPaintingInfo.rootLayer, |
fragment.paginationOffset, paintFlags); |
} |
@@ -910,9 +941,21 @@ 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 |
clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, |
- clipRect, &paintingInfo, fragment.paginationOffset, |
- paintFlags, clippingRule); |
+ clipRect, paintingInfo.rootLayer, |
+ fragment.paginationOffset, paintFlags, clippingRule); |
+ } |
+ |
+ // If we are painting a mask for any reason and we have already processed the |
+ // clips, there is no need to go through the remaining painting pipeline. |
+ // We know that the mask just needs the area bounded by the clip rects to be |
+ // filled with black. |
+ if (clipRecorder && phase == PaintPhaseClippingMask) { |
+ fillMaskingFragment(context, clipRect); |
+ return; |
} |
LayoutRect newCullRect(clipRect.rect()); |
@@ -984,7 +1027,8 @@ void PaintLayerPainter::paintForegroundForFragments( |
needsToClip(localPaintingInfo, layerFragments[0].foregroundRect)) { |
clipRecorder.emplace(context, *m_paintLayer.layoutObject(), |
DisplayItem::kClipLayerForeground, |
- layerFragments[0].foregroundRect, &localPaintingInfo, |
+ layerFragments[0].foregroundRect, |
+ localPaintingInfo.rootLayer, |
layerFragments[0].paginationOffset, paintFlags); |
clipState = HasClipped; |
} |
@@ -1130,4 +1174,17 @@ void PaintLayerPainter::paintOverlayScrollbars( |
m_paintLayer.setContainsDirtyOverlayScrollbars(false); |
} |
+void PaintLayerPainter::fillMaskingFragment(GraphicsContext& context, |
+ const ClipRect& clipRect) { |
+ const LayoutBox* layoutBox = toLayoutBox(m_paintLayer.layoutObject()); |
+ if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible( |
+ context, *layoutBox, PaintPhaseClippingMask)) |
+ return; |
+ |
+ IntRect snappedClipRect = pixelSnappedIntRect(clipRect.rect()); |
+ LayoutObjectDrawingRecorder drawingRecorder( |
+ context, *layoutBox, PaintPhaseClippingMask, snappedClipRect); |
+ context.fillRect(snappedClipRect, Color::black); |
+} |
+ |
} // namespace blink |