Title: [281736] trunk
Revision
281736
Author
[email protected]
Date
2021-08-28 18:31:55 -0700 (Sat, 28 Aug 2021)

Log Message

Zooming browser does not properly scale SVG clip paths
https://bugs.webkit.org/show_bug.cgi?id=224795

Reviewed by Tim Horton.

Source/WebCore:

Clip-path and Command+ zooming were fixed in r268138, but that change didn't address
reference clip paths.

Fix by having effectiveZoom scale the clip in the two codepaths; the "clip via a path"
path, and the "clip by painting a mask" path that we fall into for more complex clips.

We only need to fix the userSpaceOnUse code path, since with objectBoundingBox clips
the input bounds has already been scaled.

Tests use the non-standard "zoom" property, so can't be WPT tests.

Tests: css3/masking/clip-path-reference-painted-mask-zoom.html
       css3/masking/clip-path-reference-zoom-objectBoundingBox.html
       css3/masking/clip-path-reference-zoom.html

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::setupClipPath):
* rendering/svg/RenderSVGResourceClipper.cpp:
(WebCore::RenderSVGResourceClipper::applyResource):
(WebCore::RenderSVGResourceClipper::pathOnlyClipping):
(WebCore::RenderSVGResourceClipper::applyClippingToContext):
(WebCore::RenderSVGResourceClipper::drawContentIntoMaskImage):
* rendering/svg/RenderSVGResourceClipper.h:

LayoutTests:

Tests for various clipping configurations which use the 'zoom' property which
has the same impact as Command+ zooming.

* css3/masking/clip-path-reference-painted-mask-zoom-expected.html: Added.
* css3/masking/clip-path-reference-painted-mask-zoom.html: Added.
* css3/masking/clip-path-reference-zoom-expected.html: Added.
* css3/masking/clip-path-reference-zoom-objectBoundingBox-expected.html: Added.
* css3/masking/clip-path-reference-zoom-objectBoundingBox.html: Added.
* css3/masking/clip-path-reference-zoom.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281735 => 281736)


--- trunk/LayoutTests/ChangeLog	2021-08-28 16:48:16 UTC (rev 281735)
+++ trunk/LayoutTests/ChangeLog	2021-08-29 01:31:55 UTC (rev 281736)
@@ -1,3 +1,20 @@
+2021-08-28  Simon Fraser  <[email protected]>
+
+        Zooming browser does not properly scale SVG clip paths
+        https://bugs.webkit.org/show_bug.cgi?id=224795
+
+        Reviewed by Tim Horton.
+        
+        Tests for various clipping configurations which use the 'zoom' property which
+        has the same impact as Command+ zooming.
+
+        * css3/masking/clip-path-reference-painted-mask-zoom-expected.html: Added.
+        * css3/masking/clip-path-reference-painted-mask-zoom.html: Added.
+        * css3/masking/clip-path-reference-zoom-expected.html: Added.
+        * css3/masking/clip-path-reference-zoom-objectBoundingBox-expected.html: Added.
+        * css3/masking/clip-path-reference-zoom-objectBoundingBox.html: Added.
+        * css3/masking/clip-path-reference-zoom.html: Added.
+
 2021-08-28  Alan Bujtas  <[email protected]>
 
         [LFC][IFC] Move content builder functionality to a dedicated class

Added: trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom-expected.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom-expected.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 40px;
+    left: 40px;
+    width: 360px;
+    height: 360px;
+    background-color: blue;
+    box-sizing: border-box;
+}
+
+#clip {
+    width: 64px;
+    height: 64px;
+    margin: 150px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-painted-mask-zoom.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 20px;
+    left: 20px;
+    width: 180px;
+    height: 180px;
+    background-color: blue;
+    box-sizing: border-box;
+    zoom: 2;
+}
+
+#clip {
+    width: 160px;
+    height: 160px;
+    margin: 10px;
+    background-color: green;
+    clip-path: url(#c2);
+}
+</style>
+</head>
+<body>
+<svg height="100" width="100">
+<clipPath id="c2">
+  <rect x="65" y="65" width="32" height="18"/>
+  <rect x="65" y="81" width="32" height="16"/>
+</clipPath>
+</svg>
+
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/clip-path-reference-zoom-expected.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-zoom-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-zoom-expected.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 40px;
+    left: 40px;
+    width: 360px;
+    height: 360px;
+    background-color: blue;
+    box-sizing: border-box;
+}
+
+#clip {
+    width: 64px;
+    height: 64px;
+    margin: 150px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox-expected.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox-expected.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 40px;
+    left: 40px;
+    width: 360px;
+    height: 360px;
+    background-color: blue;
+    box-sizing: border-box;
+}
+
+#clip {
+    width: 160px;
+    height: 160px;
+    margin: 100px;
+    background-color: green;
+}
+</style>
+</head>
+<body>
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-zoom-objectBoundingBox.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 20px;
+    left: 20px;
+    width: 180px;
+    height: 180px;
+    background-color: blue;
+    box-sizing: border-box;
+    zoom: 2;
+}
+
+#clip {
+    width: 160px;
+    height: 160px;
+    margin: 10px;
+    background-color: green;
+    clip-path: url(#c2);
+}
+</style>
+</head>
+<body>
+<svg height="100" width="100">
+<clipPath id="c2" clipPathUnits="objectBoundingBox">
+  <rect x="0.25" y="0.25" width="0.5" height="0.5"/>
+</clipPath>
+</svg>
+
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/clip-path-reference-zoom.html (0 => 281736)


--- trunk/LayoutTests/css3/masking/clip-path-reference-zoom.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-zoom.html	2021-08-29 01:31:55 UTC (rev 281736)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<style>
+#d {
+    position: absolute;
+    top: 20px;
+    left: 20px;
+    width: 180px;
+    height: 180px;
+    background-color: blue;
+    box-sizing: border-box;
+    zoom: 2;
+}
+
+#clip {
+    width: 160px;
+    height: 160px;
+    margin: 10px;
+    background-color: green;
+    clip-path: url(#c2);
+}
+</style>
+</head>
+<body>
+<svg height="100" width="100">
+<clipPath id="c2">
+  <rect x="65" y="65" width="32" height="32"/>
+</clipPath>
+</svg>
+
+<div id="d"><div id="clip"></div></div>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (281735 => 281736)


--- trunk/Source/WebCore/ChangeLog	2021-08-28 16:48:16 UTC (rev 281735)
+++ trunk/Source/WebCore/ChangeLog	2021-08-29 01:31:55 UTC (rev 281736)
@@ -1,3 +1,34 @@
+2021-08-28  Simon Fraser  <[email protected]>
+
+        Zooming browser does not properly scale SVG clip paths
+        https://bugs.webkit.org/show_bug.cgi?id=224795
+
+        Reviewed by Tim Horton.
+        
+        Clip-path and Command+ zooming were fixed in r268138, but that change didn't address
+        reference clip paths.
+        
+        Fix by having effectiveZoom scale the clip in the two codepaths; the "clip via a path"
+        path, and the "clip by painting a mask" path that we fall into for more complex clips.
+
+        We only need to fix the userSpaceOnUse code path, since with objectBoundingBox clips
+        the input bounds has already been scaled.
+
+        Tests use the non-standard "zoom" property, so can't be WPT tests.
+
+        Tests: css3/masking/clip-path-reference-painted-mask-zoom.html
+               css3/masking/clip-path-reference-zoom-objectBoundingBox.html
+               css3/masking/clip-path-reference-zoom.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::setupClipPath):
+        * rendering/svg/RenderSVGResourceClipper.cpp:
+        (WebCore::RenderSVGResourceClipper::applyResource):
+        (WebCore::RenderSVGResourceClipper::pathOnlyClipping):
+        (WebCore::RenderSVGResourceClipper::applyClippingToContext):
+        (WebCore::RenderSVGResourceClipper::drawContentIntoMaskImage):
+        * rendering/svg/RenderSVGResourceClipper.h:
+
 2021-08-28  Alan Bujtas  <[email protected]>
 
         [LFC][IFC] Move content builder functionality to a dedicated class

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (281735 => 281736)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2021-08-28 16:48:16 UTC (rev 281735)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2021-08-29 01:31:55 UTC (rev 281736)
@@ -3194,7 +3194,7 @@
             auto offset = referenceBox.location();
             context.translate(offset);
             FloatRect svgReferenceBox { {}, referenceBox.size() };
-            downcast<RenderSVGResourceClipper>(*element->renderer()).applyClippingToContext(renderer(), svgReferenceBox, context);
+            downcast<RenderSVGResourceClipper>(*element->renderer()).applyClippingToContext(context, renderer(), svgReferenceBox, renderer().style().effectiveZoom());
             context.translate(-offset);
             return true;
         }

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp (281735 => 281736)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp	2021-08-28 16:48:16 UTC (rev 281735)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp	2021-08-29 01:31:55 UTC (rev 281736)
@@ -76,10 +76,10 @@
     if (repaintRect.isEmpty())
         return true;
 
-    return applyClippingToContext(renderer, renderer.objectBoundingBox(), *context);
+    return applyClippingToContext(*context, renderer, renderer.objectBoundingBox());
 }
 
-bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext& context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox)
+bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext& context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox, float effectiveZoom)
 {
     // If the current clip-path gets clipped itself, we have to fall back to masking.
     if (style().clipPath())
@@ -120,6 +120,10 @@
         transform.translate(objectBoundingBox.location());
         transform.scale(objectBoundingBox.size());
         clipPath.transform(transform);
+    } else if (effectiveZoom != 1) {
+        AffineTransform transform;
+        transform.scale(effectiveZoom);
+        clipPath.transform(transform);
     }
 
     // Transform path by animatedLocalTransform.
@@ -132,7 +136,7 @@
     return true;
 }
 
-bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, const FloatRect& objectBoundingBox, GraphicsContext& context)
+bool RenderSVGResourceClipper::applyClippingToContext(GraphicsContext& context, RenderElement& renderer, const FloatRect& objectBoundingBox, float effectiveZoom)
 {
     ClipperData& clipperData = addRendererToClipper(renderer);
     
@@ -140,7 +144,7 @@
 
     AffineTransform animatedLocalTransform = clipPathElement().animatedLocalTransform();
 
-    if (!clipperData.imageBuffer && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
+    if (!clipperData.imageBuffer && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox, effectiveZoom))
         return true;
 
     AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
@@ -162,13 +166,13 @@
         if (resources && (clipper = resources->clipper())) {
             GraphicsContextStateSaver stateSaver(maskContext);
 
-            if (!clipper->applyClippingToContext(*this, objectBoundingBox, maskContext))
+            if (!clipper->applyClippingToContext(maskContext, *this, objectBoundingBox))
                 return false;
 
-            succeeded = drawContentIntoMaskImage(*clipperData.imageBuffer, objectBoundingBox);
+            succeeded = drawContentIntoMaskImage(*clipperData.imageBuffer, objectBoundingBox, effectiveZoom);
             // The context restore applies the clipping on non-CG platforms.
         } else
-            succeeded = drawContentIntoMaskImage(*clipperData.imageBuffer, objectBoundingBox);
+            succeeded = drawContentIntoMaskImage(*clipperData.imageBuffer, objectBoundingBox, effectiveZoom);
 
         if (!succeeded)
             clipperData = { };
@@ -181,7 +185,7 @@
     return true;
 }
 
-bool RenderSVGResourceClipper::drawContentIntoMaskImage(ImageBuffer& maskImageBuffer, const FloatRect& objectBoundingBox)
+bool RenderSVGResourceClipper::drawContentIntoMaskImage(ImageBuffer& maskImageBuffer, const FloatRect& objectBoundingBox, float effectiveZoom)
 {
     GraphicsContext& maskContext = maskImageBuffer.context();
 
@@ -190,6 +194,9 @@
         maskContentTransformation.translate(objectBoundingBox.location());
         maskContentTransformation.scale(objectBoundingBox.size());
         maskContext.concatCTM(maskContentTransformation);
+    } else if (effectiveZoom != 1) {
+        maskContentTransformation.scale(effectiveZoom);
+        maskContext.concatCTM(maskContentTransformation);
     }
 
     // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h (281735 => 281736)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h	2021-08-28 16:48:16 UTC (rev 281735)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.h	2021-08-29 01:31:55 UTC (rev 281736)
@@ -45,7 +45,7 @@
     // clipPath can be clipped too, but don't have a boundingBox or repaintRect. So we can't call
     // applyResource directly and use the rects from the object, since they are empty for RenderSVGResources
     // FIXME: We made applyClippingToContext public because we cannot call applyResource on HTML elements (it asserts on RenderObject::objectBoundingBox)
-    bool applyClippingToContext(RenderElement&, const FloatRect&, GraphicsContext&);
+    bool applyClippingToContext(GraphicsContext&, RenderElement&, const FloatRect&, float effectiveZoom = 1);
     FloatRect resourceBoundingBox(const RenderObject&) override;
 
     RenderSVGResourceType resourceType() const override { return ClipperResourceType; }
@@ -81,8 +81,8 @@
     const char* renderName() const override { return "RenderSVGResourceClipper"; }
     bool isSVGResourceClipper() const override { return true; }
 
-    bool pathOnlyClipping(GraphicsContext&, const AffineTransform&, const FloatRect&);
-    bool drawContentIntoMaskImage(ImageBuffer&, const FloatRect& objectBoundingBox);
+    bool pathOnlyClipping(GraphicsContext&, const AffineTransform&, const FloatRect&, float effectiveZoom);
+    bool drawContentIntoMaskImage(ImageBuffer&, const FloatRect& objectBoundingBox, float effectiveZoom);
     void calculateClipContentRepaintRect();
     ClipperData& addRendererToClipper(const RenderObject&);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to