Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (284683 => 284684)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2021-10-22 15:17:11 UTC (rev 284683)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2021-10-22 15:50:23 UTC (rev 284684)
@@ -2904,12 +2904,12 @@
widget->setOverlapTestResult(false);
}
-void RenderLayer::clipToRect(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule)
+void RenderLayer::clipToRect(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, EventRegionContextStateSaver& eventRegionStateSaver, const LayerPaintingInfo& paintingInfo, OptionSet<PaintBehavior> paintBehavior, const ClipRect& clipRect, BorderRadiusClippingRule rule)
{
float deviceScaleFactor = renderer().document().deviceScaleFactor();
bool needsClipping = !clipRect.isInfinite() && clipRect.rect() != paintingInfo.paintDirtyRect;
if (needsClipping || clipRect.affectedByRadius())
- context.save();
+ stateSaver.save();
if (needsClipping) {
LayoutRect adjustedClipRect = clipRect.rect();
@@ -2916,9 +2916,7 @@
adjustedClipRect.move(paintingInfo.subpixelOffset);
auto snappedClipRect = snapRectToDevicePixels(adjustedClipRect, deviceScaleFactor);
context.clip(snappedClipRect);
-
- if (paintingInfo.eventRegionContext)
- paintingInfo.eventRegionContext->pushClip(enclosingIntRect(snappedClipRect));
+ eventRegionStateSaver.pushClip(enclosingIntRect(snappedClipRect));
}
if (clipRect.affectedByRadius()) {
@@ -2945,16 +2943,6 @@
}
}
-void RenderLayer::restoreClip(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, const ClipRect& clipRect)
-{
- bool needsClipping = !clipRect.isInfinite() && clipRect.rect() != paintingInfo.paintDirtyRect;
- if (needsClipping || clipRect.affectedByRadius())
- context.restore();
-
- if (needsClipping && paintingInfo.eventRegionContext)
- paintingInfo.eventRegionContext->popClip();
-}
-
static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
{
if (overlapTestRequests.isEmpty())
@@ -3071,6 +3059,8 @@
// Make sure the parent's clip rects have been calculated.
ClipRect clipRect = paintingInfo.paintDirtyRect;
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
if (parent()) {
ClipRectsContext clipRectsContext(paintingInfo.rootLayer, (paintFlags & PaintLayerFlag::TemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerFlag::PaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
@@ -3082,15 +3072,10 @@
paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
// Push the parent coordinate space's clip.
- parent()->clipToRect(context, paintingInfo, paintBehavior, clipRect);
+ parent()->clipToRect(context, stateSaver, eventRegionStateSaver, paintingInfo, paintBehavior, clipRect);
}
paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
-
- // Restore the clip.
- if (parent())
- parent()->restoreClip(context, paintingInfo, clipRect);
-
return;
}
@@ -3171,14 +3156,14 @@
return { Path(), WindRule::NonZero };
}
-bool RenderLayer::setupClipPath(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot)
+void RenderLayer::setupClipPath(GraphicsContext& context, GraphicsContextStateSaver& stateSaver, const LayerPaintingInfo& paintingInfo, const LayoutSize& offsetFromRoot)
{
if (!renderer().hasClipPath() || context.paintingDisabled() || paintingInfo.paintDirtyRect.isEmpty())
- return false;
+ return;
// SVG elements get clipped in SVG code.
if (is<RenderSVGRoot>(renderer()))
- return false;
+ return;
auto clippedContentBounds = calculateLayerBounds(paintingInfo.rootLayer, offsetFromRoot, { UseLocalClipRectIfPossible });
@@ -3188,9 +3173,8 @@
if (is<ShapeClipPathOperation>(*style.clipPath()) || (is<BoxClipPathOperation>(*style.clipPath()) && is<RenderBox>(renderer()))) {
// clippedContentBounds is used as the reference box for inlines, which is also poorly specified: https://github.com/w3c/csswg-drafts/issues/6383.
auto [path, windRule] = computeClipPath(paintingOffsetFromRoot, clippedContentBounds);
- context.save();
+ stateSaver.save();
context.clipPath(path, windRule);
- return true;
}
if (is<ReferenceClipPathOperation>(style.clipPath())) {
@@ -3205,16 +3189,13 @@
auto snappedClippingBounds = snapRectToDevicePixels(clippedContentBounds, renderer().document().deviceScaleFactor());
snappedClippingBounds.moveBy(-offset);
- context.save();
+ stateSaver.save();
context.translate(offset);
FloatRect clipPathReferenceBox { { }, referenceBox.size() };
clipperRenderer->applyClippingToContext(context, renderer(), clipPathReferenceBox, snappedClippingBounds, renderer().style().effectiveZoom());
context.translate(-offset);
- return true;
}
}
-
- return false;
}
RenderLayerFilters* RenderLayer::filtersForPainting(GraphicsContext& context, OptionSet<PaintLayerFlag> paintFlags) const
@@ -3265,9 +3246,12 @@
{
// FIXME: Handle more than one fragment.
ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
- clipToRect(originalContext, paintingInfo, behavior, backgroundRect);
+
+ GraphicsContextStateSaver stateSaver(originalContext, false);
+ EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
+
+ clipToRect(originalContext, stateSaver, eventRegionStateSaver, paintingInfo, behavior, backgroundRect);
m_filters->applyFilterEffect(originalContext);
- restoreClip(originalContext, paintingInfo, backgroundRect);
}
void RenderLayer::paintLayerContents(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags)
@@ -3326,9 +3310,9 @@
if (renderer().enclosingFragmentedFlow() && (renderer().hasClipPath() || filtersForPainting(context, paintFlags)))
columnAwareOffsetFromRoot = toLayoutSize(convertToLayerCoords(paintingInfo.rootLayer, LayoutPoint(), AdjustForColumns));
- bool hasClipPath = false;
+ GraphicsContextStateSaver stateSaver(context, false);
if (shouldApplyClipPath(paintingInfo.paintBehavior, localPaintFlags))
- hasClipPath = setupClipPath(context, paintingInfo, columnAwareOffsetFromRoot);
+ setupClipPath(context, stateSaver, paintingInfo, columnAwareOffsetFromRoot);
bool selectionAndBackgroundsOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionAndBackgroundsOnly);
bool selectionOnly = paintingInfo.paintBehavior.contains(PaintBehavior::SelectionOnly);
@@ -3479,9 +3463,6 @@
// Re-set this to whatever it was before we painted the layer.
if (needToAdjustSubpixelQuantization)
context.setShouldSubpixelQuantizeFonts(didQuantizeFonts);
-
- if (hasClipPath)
- context.restore();
}
void RenderLayer::paintLayerByApplyingTransform(GraphicsContext& context, const LayerPaintingInfo& paintingInfo, OptionSet<PaintLayerFlag> paintFlags, const LayoutSize& translationOffset)
@@ -3732,9 +3713,11 @@
if (paintFlags.contains(PaintLayerFlag::PaintingOverflowContents))
paintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
- parent()->clipToRect(context, paintingInfo, paintBehavior, clipRect);
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(paintingInfo.eventRegionContext);
+
+ parent()->clipToRect(context, stateSaver, eventRegionStateSaver, paintingInfo, paintBehavior, clipRect);
paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
- parent()->restoreClip(context, paintingInfo, clipRect);
}
}
@@ -3750,10 +3733,13 @@
if (haveTransparency)
beginTransparencyLayers(contextForTransparencyLayer, localPaintingInfo, transparencyPaintDirtyRect);
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
if (localPaintingInfo.clipToDirtyRect) {
// Paint our background first, before painting any child layers.
// Establish the clip used to paint our background.
- clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
}
// Paint the background.
@@ -3760,9 +3746,6 @@
// FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::BlockBackground, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
-
- if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo, fragment.backgroundRect);
}
}
@@ -3801,13 +3784,13 @@
if (localPaintingInfo.paintBehavior & PaintBehavior::CompositedOverflowScrollContent)
localPaintBehavior.add(PaintBehavior::CompositedOverflowScrollContent);
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
// Optimize clipping for the single fragment case.
bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
- ClipRect clippedRect;
- if (shouldClip) {
- clippedRect = layerFragments[0].foregroundRect;
- clipToRect(context, localPaintingInfo, localPaintBehavior, clippedRect);
- }
+ if (shouldClip)
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, localPaintBehavior, layerFragments[0].foregroundRect);
// We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
// interleaving of the fragments to work properly.
@@ -3824,9 +3807,6 @@
paintForegroundForFragmentsWithPhase(PaintPhase::Foreground, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
paintForegroundForFragmentsWithPhase(PaintPhase::ChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, subtreePaintRootForRenderer);
}
-
- if (shouldClip)
- restoreClip(context, localPaintingInfo, clippedRect);
}
void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext& context,
@@ -3837,17 +3817,17 @@
for (const auto& fragment : layerFragments) {
if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
continue;
-
+
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
if (shouldClip)
- clipToRect(context, localPaintingInfo, paintBehavior, fragment.foregroundRect);
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.foregroundRect);
PaintInfo paintInfo(context, fragment.foregroundRect.rect(), phase, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this, localPaintingInfo.requireSecurityOriginAccessForWidgets);
if (phase == PaintPhase::Foreground)
paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
-
- if (shouldClip)
- restoreClip(context, localPaintingInfo, fragment.foregroundRect);
}
}
@@ -3860,9 +3840,12 @@
// Paint our own outline
PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::SelfOutline, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
- clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius);
+
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius);
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
- restoreClip(context, localPaintingInfo, fragment.backgroundRect);
}
}
@@ -3873,16 +3856,16 @@
if (!fragment.shouldPaintContent)
continue;
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(context, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
// Paint the mask.
// FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::Mask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
-
- if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo, fragment.backgroundRect);
}
}
@@ -3892,15 +3875,15 @@
if (!fragment.shouldPaintContent)
continue;
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
if (localPaintingInfo.clipToDirtyRect)
- clipToRect(context, localPaintingInfo, paintBehavior, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, paintBehavior, fragment.foregroundRect, IncludeSelfForBorderRadius); // Child clipping mask painting will handle clipping to self.
// Paint the clipped mask.
PaintInfo paintInfo(context, fragment.backgroundRect.rect(), PaintPhase::ClippingMask, paintBehavior, subtreePaintRootForRenderer, nullptr, nullptr, &localPaintingInfo.rootLayer->renderer(), this);
renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
-
- if (localPaintingInfo.clipToDirtyRect)
- restoreClip(context, localPaintingInfo, fragment.foregroundRect);
}
}
@@ -3911,10 +3894,12 @@
for (const auto& fragment : layerFragments) {
if (fragment.backgroundRect.isEmpty())
continue;
- clipToRect(context, localPaintingInfo, { }, fragment.backgroundRect);
- m_scrollableArea->paintOverflowControls(context, roundedIntPoint(toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)),
- snappedIntRect(fragment.backgroundRect.rect()), true);
- restoreClip(context, localPaintingInfo, fragment.backgroundRect);
+
+ GraphicsContextStateSaver stateSaver(context, false);
+ EventRegionContextStateSaver eventRegionStateSaver(localPaintingInfo.eventRegionContext);
+
+ clipToRect(context, stateSaver, eventRegionStateSaver, localPaintingInfo, { }, fragment.backgroundRect);
+ m_scrollableArea->paintOverflowControls(context, roundedIntPoint(toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset)), snappedIntRect(fragment.backgroundRect.rect()), true);
}
}