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 e1c8fdce368965828ee0faf852f8e417f6fe30fb..388ef49fd8c5c23e62d4c4ab754c3a035fd66f11 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintLayerPainter.cpp |
@@ -229,6 +229,27 @@ static bool shouldRepaintSubsequence( |
return needsRepaint; |
} |
+LayoutPoint PaintLayerPainter::fragmentOffsetForAncestorClipMask( |
+ const LayoutPoint& originalFragmentOffset) { |
+ // The clipping container that will be used to define the clip and the |
+ // child layer with respect to which the fragment offset is defined share |
+ // a layer root. When the clip is recorded we will be using the clipping |
+ // container's layer's offset to the root to position the clip. Hence we |
+ // must convert the fragment offset into a corresponding offset in the |
+ // clipping container's layer coordinates. To do that, we find the |
+ // originalFragmentOffset's coordinate in the root layer, fragmentDelta. |
+ // We also find the offset of the clipping container's origin in the root |
+ // layer's coordinates, clippingDelta. clippingDelta - fragmentDelta gives |
+ // the fragment's position in the root layer. But we need the position in |
+ // the clipping layer coords, and we subtract clippingDelta to get that. The |
+ // resulting offset is -fragmentDelta. |
+ DCHECK_EQ(m_paintLayer.root(), |
+ m_paintLayer.clippingContainer()->enclosingLayer()->root()); |
+ LayoutPoint fragmentDelta(originalFragmentOffset); |
+ m_paintLayer.convertToLayerCoords(m_paintLayer.root(), fragmentDelta); |
+ return LayoutPoint(-fragmentDelta.x(), -fragmentDelta.y()); |
+} |
+ |
PaintResult PaintLayerPainter::paintLayerContents( |
GraphicsContext& context, |
const PaintLayerPaintingInfo& paintingInfoArg, |
@@ -353,7 +374,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()); |
@@ -409,19 +431,48 @@ PaintResult PaintLayerPainter::paintLayerContents( |
// 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 |
+ PaintLayer* paintLayerForFragmentsAndClip = &m_paintLayer; |
+ LayoutPoint offsetFromRootForFragmentsAndClip = offsetFromRoot; |
+ if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { |
+ // Compute fragments and their clips with respect to the clipping |
+ // container, and then convert them back to this layer's space. |
+ // We need a new offset from root. |
+ paintLayerForFragmentsAndClip = |
+ m_paintLayer.clippingContainer()->enclosingLayer(); |
+ LayoutPoint clippersOffsetToRoot; |
+ paintLayerForFragmentsAndClip->convertToLayerCoords(m_paintLayer.root(), |
+ clippersOffsetToRoot); |
+ LayoutPoint thisOffsetToRoot; |
+ m_paintLayer.convertToLayerCoords(m_paintLayer.root(), thisOffsetToRoot); |
+ offsetFromRootForFragmentsAndClip = |
+ LayoutPoint(clippersOffsetToRoot.x() - thisOffsetToRoot.x(), |
+ clippersOffsetToRoot.y() - thisOffsetToRoot.y()); |
+ } |
+ |
if (fragmentPolicy == ForceSingleFragment || |
- RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
- m_paintLayer.appendSingleFragmentIgnoringPagination( |
+ RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
+ paintLayerForFragmentsAndClip->appendSingleFragmentIgnoringPagination( |
layerFragments, localPaintingInfo.rootLayer, |
localPaintingInfo.paintDirtyRect, cacheSlot, |
- IgnoreOverlayScrollbarSize, respectOverflowClip, &offsetFromRoot, |
+ IgnoreOverlayScrollbarSize, respectOverflowClip, |
+ &offsetFromRootForFragmentsAndClip, |
localPaintingInfo.subPixelAccumulation); |
- else |
- m_paintLayer.collectFragments(layerFragments, localPaintingInfo.rootLayer, |
- localPaintingInfo.paintDirtyRect, cacheSlot, |
- IgnoreOverlayScrollbarSize, |
- respectOverflowClip, &offsetFromRoot, |
- localPaintingInfo.subPixelAccumulation); |
+ } else { |
+ paintLayerForFragmentsAndClip->collectFragments( |
+ layerFragments, localPaintingInfo.rootLayer, |
+ localPaintingInfo.paintDirtyRect, cacheSlot, |
+ IgnoreOverlayScrollbarSize, respectOverflowClip, |
+ &offsetFromRootForFragmentsAndClip, |
+ localPaintingInfo.subPixelAccumulation); |
+ } |
+ |
+ // Reset the layerBounds because they were set using the clipper's layer |
+ if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { |
+ for (auto& fragment : layerFragments) { |
+ fragment.layerBounds = |
+ LayoutRect(offsetFromRoot, LayoutSize(m_paintLayer.size())); |
+ } |
+ } |
if (shouldPaintContent) { |
// TODO(wangxianzhu): This is for old slow scrolling. Implement similar |
@@ -525,7 +576,8 @@ PaintResult PaintLayerPainter::paintLayerContents( |
shouldPaintContent && m_paintLayer.layoutObject()->hasMask() && |
!selectionOnly; |
bool shouldPaintClippingMask = |
- (paintFlags & PaintLayerPaintingChildClippingMaskPhase) && |
+ (paintFlags & (PaintLayerPaintingChildClippingMaskPhase | |
+ PaintLayerPaintingAncestorClippingMaskPhase)) && |
shouldPaintContent && !selectionOnly; |
if (shouldPaintMask) |
@@ -604,6 +656,7 @@ PaintResult PaintLayerPainter::paintLayerWithTransform( |
object->container() == view && view->pageLogicalHeight(); |
PaintLayer* paginationLayer = m_paintLayer.enclosingPaginationLayer(); |
PaintLayerFragments fragments; |
+ |
// TODO(crbug.com/619094): Figure out the correct behaviour for fixed position |
// objects in paged media with vertical writing modes. |
if (isFixedPosObjectInPagedMedia && view->isHorizontalWritingMode()) { |
@@ -888,9 +941,21 @@ void PaintLayerPainter::paintFragmentWithPhase( |
break; |
} |
- clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, |
- clipRect, &paintingInfo, fragment.paginationOffset, |
- paintFlags, clippingRule); |
+ // When painting the clipping mask for a composited child, we pass |
+ // the clipping container object as the layoutObject to provide the clip. |
+ // The recorder assumes the fragment is positioned in that objects's |
+ // layer coordinates, so we also convert that. |
+ if (paintFlags & PaintLayerPaintingAncestorClippingMaskPhase) { |
+ clipRecorder.emplace( |
+ context, *(toLayoutBoxModelObject(m_paintLayer.clippingContainer())), |
+ clipType, clipRect, &paintingInfo, |
+ fragmentOffsetForAncestorClipMask(fragment.paginationOffset), |
+ paintFlags, clippingRule); |
+ } else { |
+ clipRecorder.emplace(context, *m_paintLayer.layoutObject(), clipType, |
+ clipRect, &paintingInfo, fragment.paginationOffset, |
+ paintFlags, clippingRule); |
+ } |
} |
LayoutRect newCullRect(clipRect.rect()); |