Chromium Code Reviews| 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); |
|
Stephen Chennney
2017/01/04 19:22:46
This avoids all sorts of problems with coordinate
|
| + 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 |