[css-masking] Fully support -webkit-clip-path on SVG elements
authorkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 14 Jul 2018 09:19:46 +0000 (09:19 +0000)
committerkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 14 Jul 2018 09:19:46 +0000 (09:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185829

Reviewed by Simon Fraser.

Source/WebCore:

-webkit-clip-path contributes to SVG elements with boxes, shapes and now with
element references to <clipPath> elements as well. Make sure that all types
contribute to hit-testing of the SVG element as well as they should.

Tests: svg/clip-path/webkit-clip-path-after-expected.svg
       svg/clip-path/webkit-clip-path-after.svg
       svg/clip-path/webkit-clip-path-before-expected.svg
       svg/clip-path/webkit-clip-path-before.svg
       svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html
       svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html
       svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html
       svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html

* rendering/svg/SVGRenderSupport.cpp: Share code as much as possible.
(WebCore::clipPathReferenceBox):
(WebCore::isPointInCSSClippingArea): Take -webkit-clip-path into account.
(WebCore::SVGRenderSupport::clipContextToCSSClippingArea):
(WebCore::SVGRenderSupport::pointInClippingArea):
* rendering/svg/SVGRenderSupport.h:
* rendering/svg/SVGRenderingContext.cpp: Clip to -webkit-clip-path boxes, shapes and references.
(WebCore::SVGRenderingContext::prepareToRenderSVGContent):
* rendering/svg/SVGResources.cpp: Add -webkit-clip-path references to cached resources. Mimic SVG clip-path.
(WebCore::SVGResources::buildCachedResources):

LayoutTests:

Test -webkit-clip-path element references on SVG elements. Make sure, -webkit-clip-path
contributes to hit testing for element references and basic shapes.

* svg/clip-path/webkit-clip-path-after-expected.svg: Added.
* svg/clip-path/webkit-clip-path-after.svg: Added.
* svg/clip-path/webkit-clip-path-before-expected.svg: Added.
* svg/clip-path/webkit-clip-path-before.svg: Added.
* svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting-expected.txt: Added.
* svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html: Added.
* svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting-expected.txt: Added.
* svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html: Added.
* svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting-expected.txt: Added.
* svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html: Added.
* svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting-expected.txt: Added.
* svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@233835 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/ios-wk2/TestExpectations
LayoutTests/svg/clip-path/webkit-clip-path-after-expected.svg [new file with mode: 0644]
LayoutTests/svg/clip-path/webkit-clip-path-after.svg [new file with mode: 0644]
LayoutTests/svg/clip-path/webkit-clip-path-before-expected.svg [new file with mode: 0644]
LayoutTests/svg/clip-path/webkit-clip-path-before.svg [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting-expected.txt [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting-expected.txt [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting-expected.txt [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting-expected.txt [new file with mode: 0644]
LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/svg/SVGRenderSupport.cpp
Source/WebCore/rendering/svg/SVGRenderSupport.h
Source/WebCore/rendering/svg/SVGRenderingContext.cpp
Source/WebCore/rendering/svg/SVGResources.cpp

index e124aaf..7bcdddc 100644 (file)
@@ -1,3 +1,26 @@
+2018-07-14  Dirk Schulze  <krit@webkit.org>
+
+        [css-masking] Fully support -webkit-clip-path on SVG elements
+        https://bugs.webkit.org/show_bug.cgi?id=185829
+
+        Reviewed by Simon Fraser.
+
+        Test -webkit-clip-path element references on SVG elements. Make sure, -webkit-clip-path
+        contributes to hit testing for element references and basic shapes.
+
+        * svg/clip-path/webkit-clip-path-after-expected.svg: Added.
+        * svg/clip-path/webkit-clip-path-after.svg: Added.
+        * svg/clip-path/webkit-clip-path-before-expected.svg: Added.
+        * svg/clip-path/webkit-clip-path-before.svg: Added.
+        * svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting-expected.txt: Added.
+        * svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html: Added.
+        * svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting-expected.txt: Added.
+        * svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html: Added.
+        * svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting-expected.txt: Added.
+        * svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html: Added.
+        * svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting-expected.txt: Added.
+        * svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html: Added.
+
 2018-07-13  Ryan Haddad  <ryanhaddad@apple.com>
 
         Add TestExpectations and baselines for iOS 12
index d82ad47..d1249b4 100644 (file)
@@ -251,6 +251,10 @@ svg/dynamic-updates/SVGAElement-svgdom-href-prop.html
 svg/dynamic-updates/SVGAElement-svgdom-target-prop.html
 svg/dynamic-updates/SVGClipPath-influences-hitTesting.html
 svg/dynamic-updates/SVGClipPathElement-css-transform-influences-hitTesting.html
+svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html
+svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html
+svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html
+svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html
 svg/dynamic-updates/SVGClipPathElement-transform-influences-hitTesting.html
 svg/custom/linking-a-03-b-all.svg
 
diff --git a/LayoutTests/svg/clip-path/webkit-clip-path-after-expected.svg b/LayoutTests/svg/clip-path/webkit-clip-path-after-expected.svg
new file mode 100644 (file)
index 0000000..75471ca
--- /dev/null
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<circle cx="100" cy="100" r="100" fill="green"/>
+</svg>
\ No newline at end of file
diff --git a/LayoutTests/svg/clip-path/webkit-clip-path-after.svg b/LayoutTests/svg/clip-path/webkit-clip-path-after.svg
new file mode 100644 (file)
index 0000000..036c0e9
--- /dev/null
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<rect width="200" height="200" fill="green" style="-webkit-clip-path: url(#clip1)"/>
+<clipPath id="clip1">
+  <circle cx="100" cy="100" r="100"/>
+</clipPath>
+</svg>
\ No newline at end of file
diff --git a/LayoutTests/svg/clip-path/webkit-clip-path-before-expected.svg b/LayoutTests/svg/clip-path/webkit-clip-path-before-expected.svg
new file mode 100644 (file)
index 0000000..75471ca
--- /dev/null
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<circle cx="100" cy="100" r="100" fill="green"/>
+</svg>
\ No newline at end of file
diff --git a/LayoutTests/svg/clip-path/webkit-clip-path-before.svg b/LayoutTests/svg/clip-path/webkit-clip-path-before.svg
new file mode 100644 (file)
index 0000000..0110e23
--- /dev/null
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg">
+<clipPath id="clip1">
+  <circle cx="100" cy="100" r="100"/>
+</clipPath>
+<rect width="200" height="200" fill="green" style="-webkit-clip-path: url(#clip1)"/>
+</svg>
\ No newline at end of file
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting-expected.txt b/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting-expected.txt
new file mode 100644 (file)
index 0000000..5b11bd7
--- /dev/null
@@ -0,0 +1,12 @@
+SVG 1.1 dynamic update tests
+
+Tests hitTesting on clipped Elements. Clipped areas shouldn't throw a hit.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hit thrown on not clipped area of rect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html b/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html
new file mode 100644 (file)
index 0000000..78a8275
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/SVGTestCase.js"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../../fast/repaint/resources/repaint.js"></script>
+</head>
+<body onload="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+// [Name] SVGClipPathElement-svgdom-clipPathUnits-prop.js
+// [Expected rendering result] green circle - and a series of PASS messages
+
+description("Tests hitTesting on clipped Elements. Clipped areas shouldn't throw a hit.")
+createSVGTestCase();
+
+var defsElement = createSVGElement("defs");
+rootSVGElement.appendChild(defsElement);
+
+var clipPathElement = createSVGElement("clipPath");
+clipPathElement.setAttribute("id", "clipper");
+
+var clipRectElement = createSVGElement("rect");
+clipRectElement.setAttribute("width", "50");
+clipRectElement.setAttribute("height", "100");
+clipPathElement.appendChild(clipRectElement);
+
+defsElement.appendChild(clipPathElement);
+
+var backgroundRect = createSVGElement("rect");
+backgroundRect.setAttribute("width", "100");
+backgroundRect.setAttribute("height", "100");
+backgroundRect.setAttribute("fill", "green");
+backgroundRect.setAttribute("onclick", "testPassed('Hit thrown on not clipped area of rect.'); completeTest()");
+rootSVGElement.appendChild(backgroundRect);
+
+var foregroundRect = createSVGElement("rect");
+foregroundRect.setAttribute("width", "100");
+foregroundRect.setAttribute("height", "100");
+foregroundRect.setAttribute("fill", "green");
+foregroundRect.setAttribute("style", "-webkit-clip-path: url(#clipper)");
+foregroundRect.setAttribute("onclick", "testFailed('Clipped are of rect throw a hit'); completeTest();");
+rootSVGElement.appendChild(foregroundRect);
+
+// Two rects are drawn. One in the background and one in the foreground. The rect
+// in the foreground gets clipped, so on hittesting, the background rect should
+// throw a hit.
+function repaintTest() {
+    clickAt(75, 50);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting-expected.txt b/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting-expected.txt
new file mode 100644 (file)
index 0000000..5b11bd7
--- /dev/null
@@ -0,0 +1,12 @@
+SVG 1.1 dynamic update tests
+
+Tests hitTesting on clipped Elements. Clipped areas shouldn't throw a hit.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hit thrown on not clipped area of rect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html b/LayoutTests/svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html
new file mode 100644 (file)
index 0000000..f83e2df
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/SVGTestCase.js"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../../fast/repaint/resources/repaint.js"></script>
+</head>
+<body onload="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+// [Name] SVGClipPathElement-svgdom-clipPathUnits-prop.js
+// [Expected rendering result] green circle - and a series of PASS messages
+
+description("Tests hitTesting on clipped Elements. Clipped areas shouldn't throw a hit.")
+createSVGTestCase();
+
+var backgroundRect = createSVGElement("rect");
+backgroundRect.setAttribute("width", "100");
+backgroundRect.setAttribute("height", "100");
+backgroundRect.setAttribute("fill", "green");
+backgroundRect.setAttribute("onclick", "testPassed('Hit thrown on not clipped area of rect.'); completeTest()");
+rootSVGElement.appendChild(backgroundRect);
+
+var foregroundRect = createSVGElement("rect");
+foregroundRect.setAttribute("width", "100");
+foregroundRect.setAttribute("height", "100");
+foregroundRect.setAttribute("fill", "green");
+foregroundRect.setAttribute("style", "-webkit-clip-path: path('M0,0L50,0L50,100L0,100z')");
+foregroundRect.setAttribute("onclick", "testFailed('Clipped are of rect throw a hit'); completeTest();");
+rootSVGElement.appendChild(foregroundRect);
+
+// Two rects are drawn. One in the background and one in the foreground. The rect
+// in the foreground gets clipped, so on hittesting, the background rect should
+// throw a hit.
+function repaintTest() {
+    clickAt(75, 50);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting-expected.txt b/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting-expected.txt
new file mode 100644 (file)
index 0000000..6952d30
--- /dev/null
@@ -0,0 +1,12 @@
+SVG 1.1 dynamic update tests
+
+Tests hitTesting on clipped Elements. Clip-path gets CSS transformed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hit thrown on not clipped area of rect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html b/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html
new file mode 100644 (file)
index 0000000..edc83dc
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/SVGTestCase.js"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../../fast/repaint/resources/repaint.js"></script>
+</head>
+<body onload="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+// [Name] SVGClipPathElement-transform-influences-hitTesting.js
+// [Expected rendering result] green circle - and a series of PASS messages
+
+description("Tests hitTesting on clipped Elements. Clip-path gets CSS transformed.")
+createSVGTestCase();
+
+var defsElement = createSVGElement("defs");
+rootSVGElement.appendChild(defsElement);
+
+var clipPathElement = createSVGElement("clipPath");
+clipPathElement.setAttribute("id", "clipper");
+
+var clipRectElement = createSVGElement("rect");
+clipRectElement.setAttribute("width", "5");
+clipRectElement.setAttribute("height", "5");
+clipRectElement.setAttribute("style", "-webkit-transform: scale(20)");
+clipPathElement.appendChild(clipRectElement);
+
+defsElement.appendChild(clipPathElement);
+
+var foregroundRect = createSVGElement("rect");
+foregroundRect.setAttribute("width", "100");
+foregroundRect.setAttribute("height", "100");
+foregroundRect.setAttribute("fill", "green");
+foregroundRect.setAttribute("style", "-webkit-clip-path: url(#clipper)");
+foregroundRect.setAttribute("onclick", "testPassed('Hit thrown on not clipped area of rect.'); completeTest();");
+rootSVGElement.appendChild(foregroundRect);
+
+// The clipPath gets scaled by 20. This should influence the hit testing,
+// since the area of the clipped content is affected as well. 
+function repaintTest() {
+    clickAt(75, 50);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting-expected.txt b/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting-expected.txt
new file mode 100644 (file)
index 0000000..11e4d9d
--- /dev/null
@@ -0,0 +1,12 @@
+SVG 1.1 dynamic update tests
+
+Tests hitTesting on clipped Elements. Clip-path gets transformed.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Hit thrown on not clipped area of rect.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html b/LayoutTests/svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html
new file mode 100644 (file)
index 0000000..b7dfb24
--- /dev/null
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/SVGTestCase.js"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../../fast/repaint/resources/repaint.js"></script>
+</head>
+<body onload="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script>
+// [Name] SVGClipPathElement-transform-influences-hitTesting.js
+// [Expected rendering result] green circle - and a series of PASS messages
+
+description("Tests hitTesting on clipped Elements. Clip-path gets transformed.")
+createSVGTestCase();
+
+var defsElement = createSVGElement("defs");
+rootSVGElement.appendChild(defsElement);
+
+var clipPathElement = createSVGElement("clipPath");
+clipPathElement.setAttribute("id", "clipper");
+
+var clipRectElement = createSVGElement("rect");
+clipRectElement.setAttribute("width", "5");
+clipRectElement.setAttribute("height", "5");
+clipRectElement.setAttribute("transform", "scale(20)");
+clipPathElement.appendChild(clipRectElement);
+
+defsElement.appendChild(clipPathElement);
+
+var foregroundRect = createSVGElement("rect");
+foregroundRect.setAttribute("width", "100");
+foregroundRect.setAttribute("height", "100");
+foregroundRect.setAttribute("fill", "green");
+foregroundRect.setAttribute("style", "-webkit-clip-path: url(#clipper)");
+foregroundRect.setAttribute("onclick", "testPassed('Hit thrown on not clipped area of rect.'); completeTest();");
+rootSVGElement.appendChild(foregroundRect);
+
+// The clipPath gets scaled by 20. This should influence the hit testing,
+// since the area of the clipped content is affected as well. 
+function repaintTest() {
+    clickAt(75, 50);
+}
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>
index ee5a457..487a630 100644 (file)
@@ -1,3 +1,34 @@
+2018-07-14  Dirk Schulze  <krit@webkit.org>
+
+        [css-masking] Fully support -webkit-clip-path on SVG elements
+        https://bugs.webkit.org/show_bug.cgi?id=185829
+
+        Reviewed by Simon Fraser.
+
+        -webkit-clip-path contributes to SVG elements with boxes, shapes and now with
+        element references to <clipPath> elements as well. Make sure that all types
+        contribute to hit-testing of the SVG element as well as they should.
+
+        Tests: svg/clip-path/webkit-clip-path-after-expected.svg
+               svg/clip-path/webkit-clip-path-after.svg
+               svg/clip-path/webkit-clip-path-before-expected.svg
+               svg/clip-path/webkit-clip-path-before.svg
+               svg/dynamic-updates/SVGClipPath-prefixed-influences-hitTesting.html
+               svg/dynamic-updates/SVGClipPath-prefixed-path-influences-hitTesting.html
+               svg/dynamic-updates/SVGClipPathElement-prefixed-css-transform-influences-hitTesting.html
+               svg/dynamic-updates/SVGClipPathElement-prefixed-transform-influences-hitTesting.html
+
+        * rendering/svg/SVGRenderSupport.cpp: Share code as much as possible.
+        (WebCore::clipPathReferenceBox):
+        (WebCore::isPointInCSSClippingArea): Take -webkit-clip-path into account.
+        (WebCore::SVGRenderSupport::clipContextToCSSClippingArea):
+        (WebCore::SVGRenderSupport::pointInClippingArea):
+        * rendering/svg/SVGRenderSupport.h:
+        * rendering/svg/SVGRenderingContext.cpp: Clip to -webkit-clip-path boxes, shapes and references.
+        (WebCore::SVGRenderingContext::prepareToRenderSVGContent):
+        * rendering/svg/SVGResources.cpp: Add -webkit-clip-path references to cached resources. Mimic SVG clip-path.
+        (WebCore::SVGResources::buildCachedResources):
+
 2018-07-13  Simon Fraser  <simon.fraser@apple.com>
 
         Avoid fetching visitedDependentColor() so many times in editing code
index 0864587..971cb1a 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2009 Google, Inc.  All rights reserved.
  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ * Copyright (C) 2018 Adobe Systems Incorporated. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -404,8 +405,76 @@ bool SVGRenderSupport::filtersForceContainerLayout(const RenderElement& renderer
     return true;
 }
 
+inline FloatRect clipPathReferenceBox(const RenderElement& renderer, CSSBoxType boxType)
+{
+    FloatRect referenceBox;
+    switch (boxType) {
+    case CSSBoxType::BorderBox:
+    case CSSBoxType::MarginBox:
+    case CSSBoxType::StrokeBox:
+        // FIXME: strokeBoundingBox() takes dasharray into account but shouldn't.
+        referenceBox = renderer.strokeBoundingBox();
+        break;
+    case CSSBoxType::ViewBox:
+        if (renderer.element()) {
+            FloatSize viewportSize;
+            SVGLengthContext(downcast<SVGElement>(renderer.element())).determineViewport(viewportSize);
+            referenceBox.setSize(viewportSize);
+            break;
+        }
+        FALLTHROUGH;
+    case CSSBoxType::ContentBox:
+    case CSSBoxType::FillBox:
+    case CSSBoxType::PaddingBox:
+    case CSSBoxType::BoxMissing:
+        referenceBox = renderer.objectBoundingBox();
+        break;
+    }
+    return referenceBox;
+}
+
+inline bool isPointInCSSClippingArea(const RenderElement& renderer, const FloatPoint& point)
+{
+    ClipPathOperation* clipPathOperation = renderer.style().clipPath();
+    if (is<ShapeClipPathOperation>(clipPathOperation)) {
+        auto& clipPath = downcast<ShapeClipPathOperation>(*clipPathOperation);
+        FloatRect referenceBox = clipPathReferenceBox(renderer, clipPath.referenceBox());
+        if (!referenceBox.contains(point))
+            return false;
+        return clipPath.pathForReferenceRect(referenceBox).contains(point, clipPath.windRule());
+    }
+    if (is<BoxClipPathOperation>(clipPathOperation)) {
+        auto& clipPath = downcast<BoxClipPathOperation>(*clipPathOperation);
+        FloatRect referenceBox = clipPathReferenceBox(renderer, clipPath.referenceBox());
+        if (!referenceBox.contains(point))
+            return false;
+        return clipPath.pathForReferenceRect(FloatRoundedRect {referenceBox}).contains(point);
+    }
+
+    return true;
+}
+
+void SVGRenderSupport::clipContextToCSSClippingArea(GraphicsContext& context, const RenderElement& renderer)
+{
+    ClipPathOperation* clipPathOperation = renderer.style().clipPath();
+    if (is<ShapeClipPathOperation>(clipPathOperation)) {
+        auto& clipPath = downcast<ShapeClipPathOperation>(*clipPathOperation);
+        FloatRect referenceBox = clipPathReferenceBox(renderer, clipPath.referenceBox());
+        context.clipPath(clipPath.pathForReferenceRect(referenceBox), clipPath.windRule());
+    }
+    if (is<BoxClipPathOperation>(clipPathOperation)) {
+        auto& clipPath = downcast<BoxClipPathOperation>(*clipPathOperation);
+        FloatRect referenceBox = clipPathReferenceBox(renderer, clipPath.referenceBox());
+        context.clipPath(clipPath.pathForReferenceRect(FloatRoundedRect {referenceBox}));
+    }
+}
+
 bool SVGRenderSupport::pointInClippingArea(const RenderElement& renderer, const FloatPoint& point)
 {
+    ClipPathOperation* clipPathOperation = renderer.style().clipPath();
+    if (is<ShapeClipPathOperation>(clipPathOperation) || is<BoxClipPathOperation>(clipPathOperation))
+        return isPointInCSSClippingArea(renderer, point);
+
     // We just take clippers into account to determine if a point is on the node. The Specification may
     // change later and we also need to check maskers.
     auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer);
index d6ff72d..b353339 100644 (file)
@@ -80,6 +80,8 @@ public:
     // Determines if any ancestor's transform has changed.
     static bool transformToRootChanged(RenderElement*);
 
+    static void clipContextToCSSClippingArea(GraphicsContext&, const RenderElement& renderer);
+
     // Helper functions to keep track of whether a renderer has an SVG shadow applied.
     static bool rendererHasSVGShadow(const RenderObject&);
     static void setRendererHasSVGShadow(RenderObject&, bool hasShadow);
index 7642489..2baa2f1 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (C) 2009 Google, Inc.  All rights reserved.
  * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
  * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ * Copyright (C) 2018 Adobe Systems Incorporated. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -134,23 +135,9 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
     }
 
     ClipPathOperation* clipPathOperation = style.clipPath();
-    if (is<ShapeClipPathOperation>(clipPathOperation)) {
-        auto& clipPath = downcast<ShapeClipPathOperation>(*clipPathOperation);
-        FloatRect referenceBox;
-        if (clipPath.referenceBox() == CSSBoxType::StrokeBox || clipPath.referenceBox() == CSSBoxType::MarginBox
-            || clipPath.referenceBox() == CSSBoxType::BorderBox)
-        {
-            // FIXME: strokeBoundingBox() takes dasharray into account but shouldn't.
-            referenceBox = renderer.strokeBoundingBox();
-        } else if (clipPath.referenceBox() == CSSBoxType::ViewBox && renderer.element()) {
-            FloatSize viewportSize;
-            SVGLengthContext(downcast<SVGElement>(renderer.element())).determineViewport(viewportSize);
-            referenceBox.setWidth(viewportSize.width());
-            referenceBox.setHeight(viewportSize.height());
-        } else
-            referenceBox = renderer.objectBoundingBox();
-        m_paintInfo->context().clipPath(clipPath.pathForReferenceRect(referenceBox), clipPath.windRule());
-    }
+    bool hasCSSClipping = is<ShapeClipPathOperation>(clipPathOperation) || is<BoxClipPathOperation>(clipPathOperation);
+    if (hasCSSClipping)
+        SVGRenderSupport::clipContextToCSSClippingArea(m_paintInfo->context(), renderer);
 
     auto* resources = SVGResourcesCache::cachedResourcesForRenderer(*m_renderer);
     if (!resources) {
@@ -172,7 +159,7 @@ void SVGRenderingContext::prepareToRenderSVGContent(RenderElement& renderer, Pai
     }
 
     RenderSVGResourceClipper* clipper = resources->clipper();
-    if (!clipPathOperation && clipper) {
+    if (!hasCSSClipping && clipper) {
         GraphicsContext* contextPtr = &m_paintInfo->context();
         bool result = clipper->applyResource(*m_renderer, style, contextPtr, RenderSVGResourceMode::ApplyToDefault);
         m_paintInfo->setContext(*contextPtr);
index 68fae61..a2cc4ba 100644 (file)
@@ -20,6 +20,7 @@
 #include "config.h"
 #include "SVGResources.h"
 
+#include "ClipPathOperation.h"
 #include "FilterOperation.h"
 #include "RenderSVGResourceClipper.h"
 #include "RenderSVGResourceFilter.h"
@@ -220,6 +221,15 @@ bool SVGResources::buildCachedResources(const RenderElement& renderer, const Ren
                 foundResources = true;
             else
                 registerPendingResource(extensions, id, element);
+        } else if (is<ReferenceClipPathOperation>(style.clipPath())) {
+            // FIXME: -webkit-clip-path should support external resources
+            // https://bugs.webkit.org/show_bug.cgi?id=127032
+            auto& clipPath = downcast<ReferenceClipPathOperation>(*style.clipPath());
+            AtomicString id(clipPath.fragment());
+            if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
+                foundResources = true;
+            else
+                registerPendingResource(extensions, id, element);
         }
 
         if (style.hasFilter()) {