Title: [281967] trunk
Revision
281967
Author
simon.fra...@apple.com
Date
2021-09-02 16:54:29 -0700 (Thu, 02 Sep 2021)

Log Message

Changes to clip-path and filter SVG elements referenced by CSS don't trigger repaints
https://bugs.webkit.org/show_bug.cgi?id=204204

Reviewed by Antti Koivisto.

Source/WebCore:

Create a mechanism that allows SVG clipping and filter resources referenced from
CSS to trigger repaints when they change. This fixes bugs where change to the
SVG, via script or animations, failed to cause CSS-rendered elements that
reference them, via clip-path:url(#foo) or filter:url(#foo) to repaint.

The key is that SVGElement stores a set of SVGResourceElementClients, as it does for
element references which are the equivalent for intra-SVG resource refs.

RenderElementRareData holds a ReferencedSVGResources class, which stores a map
of resourceID -> SVGResourceElementClient, and its implementation of SVGResourceElementClients
triggers the repaint.

ReferencedSVGResources are updated after a style change, which works because
they only ever find elements, not SVG renderers.

Change filter and clip-path code go via ReferencedSVGResources to find their
appropriate filter element or clipping renderer, for cleanliness.

Tests: css3/filters/reference-filter-change-repaint.html
       css3/masking/reference-clip-path-animate-transform-repaint.html
       css3/masking/reference-clip-path-change-repaint.html

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::buildReferenceFilter): Remove some code related to looking
for resources in external documents, since this functionality was removed.
* rendering/ReferencedSVGResources.cpp: Added.
(WebCore::CSSSVGResourceElementClient::resourceChanged):
(WebCore::ReferencedSVGResources::ReferencedSVGResources):
(WebCore::ReferencedSVGResources::~ReferencedSVGResources):
(WebCore::ReferencedSVGResources::removeClientForTarget):
(WebCore::ReferencedSVGResources::referencedSVGResourceIDs):
(WebCore::ReferencedSVGResources::updateReferencedResources):
(WebCore::ReferencedSVGResources::elementForResourceID):
(WebCore::ReferencedSVGResources::referencedFilterElement):
(WebCore::ReferencedSVGResources::referencedClipperRenderer):
* rendering/ReferencedSVGResources.h: Added.
* rendering/RenderElement.cpp:
(WebCore::RenderElement::styleDidChange):
(WebCore::RenderElement::ensureReferencedSVGResources):
(WebCore::RenderElement::clearReferencedSVGResources):
(WebCore::RenderElement::updateReferencedSVGResources):
* rendering/RenderElement.h:
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::setupClipPath):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData):
* rendering/RenderObject.h:
(WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData): Deleted.
* rendering/svg/RenderSVGResource.cpp:
(WebCore::removeFromCacheAndInvalidateDependencies):
* svg/SVGElement.cpp:
(WebCore::SVGElement::referencingCSSClients const):
(WebCore::SVGElement::addReferencingCSSClient):
(WebCore::SVGElement::removeReferencingCSSClient):
* svg/SVGElement.h:
* svg/SVGElementRareData.h:
(WebCore::SVGElementRareData::addReferencingCSSClient):
(WebCore::SVGElementRareData::removeReferencingCSSClient):
(WebCore::SVGElementRareData::referencingCSSClients const):
* svg/SVGResourceElementClient.h: Added.

LayoutTests:

Repaint tests that detect repaints when referenced clips or filters change.

* css3/filters/reference-filter-change-repaint-expected.txt: Added.
* css3/filters/reference-filter-change-repaint.html: Added.
* css3/masking/clip-path-reference-local-url-with-base.html:
* css3/masking/reference-clip-path-animate-transform-repaint-expected.txt: Added.
* css3/masking/reference-clip-path-animate-transform-repaint.html: Added.
* css3/masking/reference-clip-path-change-repaint-expected.txt: Added.
* css3/masking/reference-clip-path-change-repaint.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (281966 => 281967)


--- trunk/LayoutTests/ChangeLog	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/LayoutTests/ChangeLog	2021-09-02 23:54:29 UTC (rev 281967)
@@ -1,3 +1,20 @@
+2021-09-02  Simon Fraser  <simon.fra...@apple.com>
+
+        Changes to clip-path and filter SVG elements referenced by CSS don't trigger repaints
+        https://bugs.webkit.org/show_bug.cgi?id=204204
+
+        Reviewed by Antti Koivisto.
+
+        Repaint tests that detect repaints when referenced clips or filters change.
+
+        * css3/filters/reference-filter-change-repaint-expected.txt: Added.
+        * css3/filters/reference-filter-change-repaint.html: Added.
+        * css3/masking/clip-path-reference-local-url-with-base.html:
+        * css3/masking/reference-clip-path-animate-transform-repaint-expected.txt: Added.
+        * css3/masking/reference-clip-path-animate-transform-repaint.html: Added.
+        * css3/masking/reference-clip-path-change-repaint-expected.txt: Added.
+        * css3/masking/reference-clip-path-change-repaint.html: Added.
+
 2021-09-02  Chris Dumez  <cdu...@apple.com>
 
         [ BigSur arm64 Debug EWS ] ASSERTION FAILED: m_uncommittedState.state == State::Provisional

Added: trunk/LayoutTests/css3/filters/reference-filter-change-repaint-expected.txt (0 => 281967)


--- trunk/LayoutTests/css3/filters/reference-filter-change-repaint-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/reference-filter-change-repaint-expected.txt	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,4 @@
+ (repaint rects
+  (rect 8 8 200 200)
+)
+

Added: trunk/LayoutTests/css3/filters/reference-filter-change-repaint.html (0 => 281967)


--- trunk/LayoutTests/css3/filters/reference-filter-change-repaint.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/reference-filter-change-repaint.html	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,47 @@
+<head>
+    <style>
+        .box {
+          width: 200px;
+          height: 200px;
+          background-color: silver;
+          filter: url(#filter);
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.dumpAsText();
+            testRunner.waitUntilDone();
+        }
+
+        function changeFilterAndFinish()
+        {
+            if (window.internals)
+                window.internals.startTrackingRepaints();
+        
+            document.getElementById('turbulence').setAttributeNS(null, 'seed', 6)
+        
+            if (window.internals)
+                document.getElementById('log').textContent = window.internals.repaintRectsAsText();
+            if (window.testRunner)
+                testRunner.notifyDone();
+        
+        }
+        window.addEventListener('load', () => {
+            setTimeout(() => {
+                changeFilterAndFinish()
+            }, 0);
+        }, false);
+    </script>
+</head>
+<body>
+   <svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1">
+    <defs>
+        <filter id="filter">
+            <feTurbulence id="turbulence" type="turbulence" baseFrequency="0.01" numOctaves="1" seed="5" stitchTiles="stitch"/>
+            <feColorMatrix type="saturate" values="0"/>
+        </filter>
+    </defs>
+  </svg>
+  <div class="box"></div>
+<pre id="log"></pre>
+</body>

Modified: trunk/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html (281966 => 281967)


--- trunk/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/LayoutTests/css3/masking/clip-path-reference-local-url-with-base.html	2021-09-02 23:54:29 UTC (rev 281967)
@@ -14,5 +14,5 @@
 <svg>
   <clipPath id="clip">
     <rect width="100" height="100"/>
-  </filter>
+  </clipPath>
 </svg>

Added: trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint-expected.txt (0 => 281967)


--- trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint-expected.txt	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,5 @@
+ PASS repaintRects.indexOf('rect 8 8 220 220') is not -1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint.html (0 => 281967)


--- trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/reference-clip-path-animate-transform-repaint.html	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+    width: 220px;
+    height: 220px;
+    background-color: green;
+    clip-path: url(#chevron);
+}
+svg {
+    height: 0px;
+    width: 0px;
+}
+</style>
+<script src=""
+<script>
+    jsTestIsAsync = true;
+    let repaintRects;
+
+    async function animationFrame()
+    {
+        return new Promise(requestAnimationFrame);
+    }
+
+    async function delayFor(ms)
+    {
+        return new Promise(resolve => setTimeout(resolve, ms));
+    }
+
+    async function renderingUpdate()
+    {
+        await animationFrame();
+        await delayFor(0);
+    }
+
+    async function changeClipPathAndFinish()
+    {
+        if (!window.internals)
+            return;
+
+        internals.startTrackingRepaints();
+        
+        await renderingUpdate();
+        await renderingUpdate();
+        await renderingUpdate();
+
+        repaintRects = internals.repaintRectsAsText();
+        // Look for at least one repaint.
+        shouldNotBe("repaintRects.indexOf('rect 8 8 220 220')", "-1");
+
+        internals.stopTrackingRepaints();
+        finishJSTest();
+    }
+
+    window.addEventListener('load', () => {
+        setTimeout(() => {
+            changeClipPathAndFinish()
+        }, 0);
+    }, false);
+</script>
+</head>
+<body>
+<div></div>
+<svg>
+    <clipPath id="chevron">
+        <polygon points="0,100 22.222,133.333 8.333,147.222 -13.889,113.889 -47.222,91.667 -33.333,77.778">
+        <animateTransform attributeType="XML" attributeName="transform" type="translate" 
+            values="0,100;144.444,-44.444" dur="0.5s" repeatCount="indefinite"/>
+        </polygon>
+    </clipPath>
+</svg>
+<div id="console"></div>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint-expected.txt (0 => 281967)


--- trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint-expected.txt	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,4 @@
+ (repaint rects
+  (rect 8 8 220 220)
+)
+

Added: trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint.html (0 => 281967)


--- trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint.html	                        (rev 0)
+++ trunk/LayoutTests/css3/masking/reference-clip-path-change-repaint.html	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+    width: 220px;
+    height: 220px;
+    background-color: green;
+    clip-path: url(#clip);
+}
+svg {
+    height: 0px;
+    width: 0px;
+}
+</style>
+<script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    function changeClipPathAndFinish()
+    {
+        if (window.internals)
+            window.internals.startTrackingRepaints();
+        
+        const rect = document.getElementById('rect');
+        rect.setAttribute('width', 100);
+        rect.setAttribute('height', 100);
+        
+        document.getElementById('log').textContent = window.internals.repaintRectsAsText();
+        if (window.testRunner)
+            testRunner.notifyDone();
+        
+    }
+    window.addEventListener('load', () => {
+        setTimeout(() => {
+            changeClipPathAndFinish()
+        }, 0);
+    }, false);
+</script>
+</head>
+<body>
+<div></div>
+<svg>
+  <clipPath id="clip">
+    <rect id="rect" width="200" height="200"/>
+  </clipPath>
+</svg>
+<pre id="log"></pre>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/win/TestExpectations (281966 => 281967)


--- trunk/LayoutTests/platform/win/TestExpectations	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/LayoutTests/platform/win/TestExpectations	2021-09-02 23:54:29 UTC (rev 281967)
@@ -1884,6 +1884,7 @@
 svg/animations/animate-text-nested-transforms.html [ Failure ]
 svg/repaint/text-mask-update.svg [ ImageOnlyFailure ]
 svg/text/lengthAdjust-text-metrics.html [ Failure ]
+css3/filters/reference-filter-change-repaint.html [ Failure ]
 
 # Weird black images
 imported/mozilla/svg/svg-effects-area-unzoomed.xhtml

Modified: trunk/Source/WebCore/ChangeLog (281966 => 281967)


--- trunk/Source/WebCore/ChangeLog	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/ChangeLog	2021-09-02 23:54:29 UTC (rev 281967)
@@ -1,3 +1,73 @@
+2021-09-02  Simon Fraser  <simon.fra...@apple.com>
+
+        Changes to clip-path and filter SVG elements referenced by CSS don't trigger repaints
+        https://bugs.webkit.org/show_bug.cgi?id=204204
+
+        Reviewed by Antti Koivisto.
+
+        Create a mechanism that allows SVG clipping and filter resources referenced from
+        CSS to trigger repaints when they change. This fixes bugs where change to the
+        SVG, via script or animations, failed to cause CSS-rendered elements that
+        reference them, via clip-path:url(#foo) or filter:url(#foo) to repaint.
+
+        The key is that SVGElement stores a set of SVGResourceElementClients, as it does for
+        element references which are the equivalent for intra-SVG resource refs.
+
+        RenderElementRareData holds a ReferencedSVGResources class, which stores a map
+        of resourceID -> SVGResourceElementClient, and its implementation of SVGResourceElementClients
+        triggers the repaint.
+
+        ReferencedSVGResources are updated after a style change, which works because
+        they only ever find elements, not SVG renderers.
+
+        Change filter and clip-path code go via ReferencedSVGResources to find their
+        appropriate filter element or clipping renderer, for cleanliness.
+
+        Tests: css3/filters/reference-filter-change-repaint.html
+               css3/masking/reference-clip-path-animate-transform-repaint.html
+               css3/masking/reference-clip-path-change-repaint.html
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/CSSFilter.cpp:
+        (WebCore::CSSFilter::buildReferenceFilter): Remove some code related to looking
+        for resources in external documents, since this functionality was removed.
+        * rendering/ReferencedSVGResources.cpp: Added.
+        (WebCore::CSSSVGResourceElementClient::resourceChanged):
+        (WebCore::ReferencedSVGResources::ReferencedSVGResources):
+        (WebCore::ReferencedSVGResources::~ReferencedSVGResources):
+        (WebCore::ReferencedSVGResources::removeClientForTarget):
+        (WebCore::ReferencedSVGResources::referencedSVGResourceIDs):
+        (WebCore::ReferencedSVGResources::updateReferencedResources):
+        (WebCore::ReferencedSVGResources::elementForResourceID):
+        (WebCore::ReferencedSVGResources::referencedFilterElement):
+        (WebCore::ReferencedSVGResources::referencedClipperRenderer):
+        * rendering/ReferencedSVGResources.h: Added.
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::styleDidChange):
+        (WebCore::RenderElement::ensureReferencedSVGResources):
+        (WebCore::RenderElement::clearReferencedSVGResources):
+        (WebCore::RenderElement::updateReferencedSVGResources):
+        * rendering/RenderElement.h:
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::setupClipPath):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData):
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::RenderObjectRareData::RenderObjectRareData): Deleted.
+        * rendering/svg/RenderSVGResource.cpp:
+        (WebCore::removeFromCacheAndInvalidateDependencies):
+        * svg/SVGElement.cpp:
+        (WebCore::SVGElement::referencingCSSClients const):
+        (WebCore::SVGElement::addReferencingCSSClient):
+        (WebCore::SVGElement::removeReferencingCSSClient):
+        * svg/SVGElement.h:
+        * svg/SVGElementRareData.h:
+        (WebCore::SVGElementRareData::addReferencingCSSClient):
+        (WebCore::SVGElementRareData::removeReferencingCSSClient):
+        (WebCore::SVGElementRareData::referencingCSSClients const):
+        * svg/SVGResourceElementClient.h: Added.
+
 2021-09-02  Aditya Keerthi  <akeer...@apple.com>
 
         [iOS] Simplify date picker logic for datetime-local inputs

Modified: trunk/Source/WebCore/Sources.txt (281966 => 281967)


--- trunk/Source/WebCore/Sources.txt	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/Sources.txt	2021-09-02 23:54:29 UTC (rev 281967)
@@ -2187,6 +2187,7 @@
 rendering/MarkedText.cpp
 rendering/OrderIterator.cpp
 rendering/PointerEventsHitRules.cpp
+rendering/ReferencedSVGResources.cpp
 rendering/RenderAttachment.cpp
 rendering/RenderBlock.cpp
 rendering/RenderBlockFlow.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (281966 => 281967)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-09-02 23:54:29 UTC (rev 281967)
@@ -6302,6 +6302,9 @@
 		0FBFCE26256CBD9A00A0B489 /* DisplayBoxClip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayBoxClip.h; sourceTree = "<group>"; };
 		0FC05168219B5EBE0031C39E /* ScrollingTreeOverflowScrollingNodeMac.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeOverflowScrollingNodeMac.mm; sourceTree = "<group>"; };
 		0FC0516A219B5EBE0031C39E /* ScrollingTreeOverflowScrollingNodeMac.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeOverflowScrollingNodeMac.h; sourceTree = "<group>"; };
+		0FC276B826DAF9B70093E8ED /* ReferencedSVGResources.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReferencedSVGResources.h; sourceTree = "<group>"; };
+		0FC276BA26DAF9E90093E8ED /* ReferencedSVGResources.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ReferencedSVGResources.cpp; sourceTree = "<group>"; };
+		0FC276BC26DB19000093E8ED /* SVGResourceElementClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SVGResourceElementClient.h; sourceTree = "<group>"; };
 		0FC4B00422B9A02C00CF3B1E /* ScrollingTreeOverflowScrollProxyNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollingTreeOverflowScrollProxyNode.h; sourceTree = "<group>"; };
 		0FC4B00522B9A02D00CF3B1E /* ScrollingTreeOverflowScrollProxyNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingTreeOverflowScrollProxyNode.mm; sourceTree = "<group>"; };
 		0FC692BA257C0F400098E3F9 /* ScrollAnimationKinetic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScrollAnimationKinetic.h; sourceTree = "<group>"; };
@@ -26362,6 +26365,7 @@
 				B22279090D00BF210071B782 /* SVGRectElement.idl */,
 				B222790A0D00BF210071B782 /* SVGRenderingIntent.h */,
 				B222790B0D00BF210071B782 /* SVGRenderingIntent.idl */,
+				0FC276BC26DB19000093E8ED /* SVGResourceElementClient.h */,
 				B222790C0D00BF210071B782 /* SVGScriptElement.cpp */,
 				B222790D0D00BF210071B782 /* SVGScriptElement.h */,
 				B222790E0D00BF210071B782 /* SVGScriptElement.idl */,
@@ -29591,6 +29595,8 @@
 				0885067E11DA045B00182B98 /* PaintPhase.h */,
 				B2B1F7140D00CAA8004AEA64 /* PointerEventsHitRules.cpp */,
 				B2B1F7150D00CAA8004AEA64 /* PointerEventsHitRules.h */,
+				0FC276BA26DAF9E90093E8ED /* ReferencedSVGResources.cpp */,
+				0FC276B826DAF9B70093E8ED /* ReferencedSVGResources.h */,
 				B59ED23A18272679006D564C /* RenderAncestorIterator.h */,
 				7CD494CA1A86EB1D000A87EC /* RenderAttachment.cpp */,
 				7CD494CB1A86EB1D000A87EC /* RenderAttachment.h */,

Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (281966 => 281967)


--- trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -37,6 +37,7 @@
 #include "FEMerge.h"
 #include "FilterEffectRenderer.h"
 #include "Logging.h"
+#include "ReferencedSVGResources.h"
 #include "RenderLayer.h"
 #include "SVGElement.h"
 #include "SVGFilterBuilder.h"
@@ -72,26 +73,14 @@
 
 RefPtr<FilterEffect> CSSFilter::buildReferenceFilter(RenderElement& renderer, FilterEffect& previousEffect, ReferenceFilterOperation& filterOperation)
 {
-    auto* cachedSVGDocumentReference = filterOperation.cachedSVGDocumentReference();
-    auto* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : nullptr;
-
-    // If we have an SVG document, this is an external reference. Otherwise
-    // we look up the referenced node in the current document.
-    Document* document;
-    if (!cachedSVGDocument)
-        document = &renderer.document();
-    else {
-        document = cachedSVGDocument->document();
-        if (!document)
-            return nullptr;
-    }
-
-    auto* filter = document->getElementById(filterOperation.fragment());
-    if (!filter) {
+    auto* filterElement = renderer.ensureReferencedSVGResources().referencedFilterElement(renderer.document(), filterOperation);
+    if (!filterElement) {
+        LOG_WITH_STREAM(Filters, stream << "CSSFilter " << this << " buildReferenceFilter: failed to find filter renderer, adding pending resource " << filterOperation.fragment());
         // Although we did not find the referenced filter, it might exist later in the document.
         // FIXME: This skips anonymous RenderObjects. <https://webkit.org/b/131085>
+        // FIXME: Unclear if this does anything.
         if (auto* element = renderer.element())
-            document->accessSVGExtensions().addPendingResource(filterOperation.fragment(), *element);
+            renderer.document().accessSVGExtensions().addPendingResource(filterOperation.fragment(), *element);
         return nullptr;
     }
 
@@ -101,7 +90,7 @@
     RefPtr<FilterEffect> effect;
     Vector<Ref<FilterEffect>> referenceEffects;
 
-    for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filter)) {
+    for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filterElement)) {
         effect = effectElement.build(builder.get(), *this);
         if (!effect) {
             LOG_WITH_STREAM(Filters, stream << "CSSFilter " << this << " buildReferenceFilter: failed to build effect from " << effectElement);

Added: trunk/Source/WebCore/rendering/ReferencedSVGResources.cpp (0 => 281967)


--- trunk/Source/WebCore/rendering/ReferencedSVGResources.cpp	                        (rev 0)
+++ trunk/Source/WebCore/rendering/ReferencedSVGResources.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ReferencedSVGResources.h"
+
+#include "ClipPathOperation.h"
+#include "FilterOperations.h"
+#include "RenderSVGResourceClipper.h"
+#include "RenderSVGResourceFilter.h"
+#include "RenderStyle.h"
+#include "SVGClipPathElement.h"
+#include "SVGResourceElementClient.h"
+
+namespace WebCore {
+
+class CSSSVGResourceElementClient final : public SVGResourceElementClient {
+    WTF_MAKE_ISO_ALLOCATED(CSSSVGResourceElementClient);
+public:
+    CSSSVGResourceElementClient(RenderElement& clientRenderer)
+        : m_clientRenderer(clientRenderer)
+    {
+    }
+
+    void resourceChanged(SVGElement&) final;
+
+private:
+    RenderElement& m_clientRenderer;
+};
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(CSSSVGResourceElementClient);
+
+void CSSSVGResourceElementClient::resourceChanged(SVGElement&)
+{
+    if (!m_clientRenderer.renderTreeBeingDestroyed())
+        m_clientRenderer.repaint();
+}
+
+WTF_MAKE_ISO_ALLOCATED_IMPL(ReferencedSVGResources);
+
+ReferencedSVGResources::ReferencedSVGResources(RenderElement& renderer)
+    : m_renderer(renderer)
+{
+}
+
+ReferencedSVGResources::~ReferencedSVGResources()
+{
+    auto& document = m_renderer.document();
+    
+    for (auto& targetID : copyToVector(m_elementClients.keys()))
+        removeClientForTarget(document, targetID);
+}
+
+void ReferencedSVGResources::addClientForTarget(SVGElement& targetElement, const AtomString& targetID)
+{
+    m_elementClients.ensure(targetID, [&] {
+        auto client = WTF::makeUnique<CSSSVGResourceElementClient>(m_renderer);
+        targetElement.addReferencingCSSClient(*client);
+        return client;
+    });
+}
+
+void ReferencedSVGResources::removeClientForTarget(Document& document, const AtomString& targetID)
+{
+    auto client = m_elementClients.take(targetID);
+
+    auto* targetElement = document.getElementById(targetID);
+    if (is<SVGElement>(targetElement))
+        downcast<SVGElement>(*targetElement).removeReferencingCSSClient(*client);
+}
+
+Vector<std::pair<AtomString, QualifiedName>> ReferencedSVGResources::referencedSVGResourceIDs(const RenderStyle& style)
+{
+    Vector<std::pair<AtomString, QualifiedName>> referencedResources;
+    if (is<ReferenceClipPathOperation>(style.clipPath())) {
+        auto& clipPath = downcast<ReferenceClipPathOperation>(*style.clipPath());
+        if (!clipPath.fragment().isEmpty())
+            referencedResources.append({ clipPath.fragment(), SVGNames::clipPathTag });
+    }
+
+    if (style.hasFilter()) {
+        const auto& filterOperations = style.filter();
+        for (auto& operation : filterOperations.operations()) {
+            auto& filterOperation = *operation;
+            if (filterOperation.type() == FilterOperation::REFERENCE) {
+                const auto& referenceFilterOperation = downcast<ReferenceFilterOperation>(filterOperation);
+                if (!referenceFilterOperation.fragment().isEmpty())
+                    referencedResources.append({ referenceFilterOperation.fragment(), SVGNames::filterTag });
+            }
+        }
+    }
+    
+    return referencedResources;
+}
+
+void ReferencedSVGResources::updateReferencedResources(Document& document, const Vector<std::pair<AtomString, QualifiedName>>& referencedResources)
+{
+    HashSet<AtomString> oldKeys;
+    for (auto& key : m_elementClients.keys())
+        oldKeys.add(key);
+
+    for (auto& [targetID, tagName] : referencedResources) {
+        auto* element = elementForResourceID(document, targetID, tagName);
+        if (!element)
+            continue;
+
+        addClientForTarget(*element, targetID);
+        oldKeys.remove(targetID);
+    }
+    
+    for (auto& targetID : oldKeys)
+        removeClientForTarget(document, targetID);
+}
+
+// SVG code uses getRenderSVGResourceById<>, but that works in terms of renderers. We need to find resources
+// before the render tree is fully constructed, so this works on Elements.
+SVGElement* ReferencedSVGResources::elementForResourceID(Document& document, const AtomString& resourceID, const QualifiedName& tagName)
+{
+    auto* element = document.getElementById(resourceID);
+    if (!element || !element->hasTagName(tagName))
+        return nullptr;
+
+    return downcast<SVGElement>(element);
+}
+
+SVGFilterElement* ReferencedSVGResources::referencedFilterElement(Document& document, const ReferenceFilterOperation& referenceFilter)
+{
+    if (referenceFilter.fragment().isEmpty())
+        return nullptr;
+    auto* element = elementForResourceID(document, referenceFilter.fragment(), SVGNames::filterTag);
+    return element ? downcast<SVGFilterElement>(element) : nullptr;
+}
+
+RenderSVGResourceClipper* ReferencedSVGResources::referencedClipperRenderer(Document& document, const ReferenceClipPathOperation& clipPath)
+{
+    if (clipPath.fragment().isEmpty())
+        return nullptr;
+    // For some reason, SVG stores a cache of id -> renderer, rather than just using getElementById() and renderer().
+    return getRenderSVGResourceById<RenderSVGResourceClipper>(document, clipPath.fragment());
+}
+
+} // namespace WebCore

Added: trunk/Source/WebCore/rendering/ReferencedSVGResources.h (0 => 281967)


--- trunk/Source/WebCore/rendering/ReferencedSVGResources.h	                        (rev 0)
+++ trunk/Source/WebCore/rendering/ReferencedSVGResources.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/FastMalloc.h>
+#include <wtf/HashMap.h>
+#include <wtf/text/AtomString.h>
+
+namespace WebCore {
+
+class CSSSVGResourceElementClient;
+class ReferenceClipPathOperation;
+class ReferenceFilterOperation;
+class RenderSVGResourceClipper;
+class RenderSVGResourceFilter;
+class RenderStyle;
+class QualifiedName;
+class SVGElement;
+class SVGFilterElement;
+
+class ReferencedSVGResources {
+    WTF_MAKE_ISO_ALLOCATED(ReferencedSVGResources);
+public:
+    ReferencedSVGResources(RenderElement&);
+    ~ReferencedSVGResources();
+
+    static Vector<std::pair<AtomString, QualifiedName>> referencedSVGResourceIDs(const RenderStyle&);
+    void updateReferencedResources(Document&, const Vector<std::pair<AtomString, QualifiedName>>&);
+
+    // Clipping needs a renderer, filters use an element.
+    RenderSVGResourceClipper* referencedClipperRenderer(Document&, const ReferenceClipPathOperation&);
+    SVGFilterElement* referencedFilterElement(Document&, const ReferenceFilterOperation&);
+
+private:
+    static SVGElement* elementForResourceID(Document&, const AtomString& resourceID, const QualifiedName& tagName);
+
+    void addClientForTarget(SVGElement& targetElement, const AtomString&);
+    void removeClientForTarget(Document&, const AtomString&);
+
+    RenderElement& m_renderer;
+    HashMap<AtomString, std::unique_ptr<CSSSVGResourceElementClient>> m_elementClients;
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (281966 => 281967)


--- trunk/Source/WebCore/rendering/RenderElement.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -46,6 +46,7 @@
 #include "Logging.h"
 #include "Page.h"
 #include "PathUtilities.h"
+#include "ReferencedSVGResources.h"
 #include "RenderBlock.h"
 #include "RenderChildIterator.h"
 #include "RenderCounter.h"
@@ -955,6 +956,9 @@
 
     SVGRenderSupport::styleChanged(*this, oldStyle);
 
+    if (diff >= StyleDifference::Repaint)
+        updateReferencedSVGResources();
+
     if (!m_parent)
         return;
     
@@ -2276,6 +2280,33 @@
         child.resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants(fragmentedFlow);
 }
 
+ReferencedSVGResources& RenderElement::ensureReferencedSVGResources()
+{
+    auto& rareData = ensureRareData();
+    if (!rareData.referencedSVGResources)
+        rareData.referencedSVGResources = WTF::makeUnique<ReferencedSVGResources>(*this);
+
+    return *rareData.referencedSVGResources;
+}
+
+void RenderElement::clearReferencedSVGResources()
+{
+    if (!hasRareData())
+        return;
+
+    ensureRareData().referencedSVGResources = nullptr;
+}
+
+// This needs to run when the entire render tree has been constructed, so can't be called from styleDidChange.
+void RenderElement::updateReferencedSVGResources()
+{
+    auto referencedElementIDs = ReferencedSVGResources::referencedSVGResourceIDs(style());
+    if (!referencedElementIDs.isEmpty())
+        ensureReferencedSVGResources().updateReferencedResources(document(), referencedElementIDs);
+    else
+        clearReferencedSVGResources();
+}
+
 #if ENABLE(TEXT_AUTOSIZING)
 static RenderObject::BlockContentHeightType includeNonFixedHeight(const RenderObject& renderer)
 {

Modified: trunk/Source/WebCore/rendering/RenderElement.h (281966 => 281967)


--- trunk/Source/WebCore/rendering/RenderElement.h	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/RenderElement.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -31,6 +31,7 @@
 class ContentData;
 class ControlStates;
 class KeyframeList;
+class ReferencedSVGResources;
 class RenderBlock;
 class RenderStyle;
 class RenderTreeBuilder;
@@ -262,6 +263,8 @@
     WeakPtr<RenderBlockFlow> backdropRenderer() const;
     void setBackdropRenderer(RenderBlockFlow&);
 
+    ReferencedSVGResources& ensureReferencedSVGResources();
+
 protected:
     enum BaseTypeFlag {
         RenderLayerModelObjectFlag  = 1 << 0,
@@ -361,6 +364,9 @@
     
     bool shouldWillChangeCreateStackingContext() const;
     void issueRepaintForOutlineAuto(float outlineSize);
+    
+    void updateReferencedSVGResources();
+    void clearReferencedSVGResources();
 
     unsigned m_baseTypeFlags : 6;
     unsigned m_ancestorLineBoxDirty : 1;

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (281966 => 281967)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -87,6 +87,7 @@
 #include "OverlapTestRequestClient.h"
 #include "Page.h"
 #include "PlatformMouseEvent.h"
+#include "ReferencedSVGResources.h"
 #include "RenderAncestorIterator.h"
 #include "RenderFlexibleBox.h"
 #include "RenderFragmentContainer.h"
@@ -3185,16 +3186,15 @@
         return true;
     }
 
-    if (style.clipPath()->type() == ClipPathOperation::Reference) {
-        ReferenceClipPathOperation* referenceClipPathOperation = static_cast<ReferenceClipPathOperation*>(style.clipPath());
-        Element* element = renderer().document().getElementById(referenceClipPathOperation->fragment());
-        if (element && element->renderer() && is<RenderSVGResourceClipper>(element->renderer())) {
+    if (is<ReferenceClipPathOperation>(style.clipPath())) {
+        auto& referenceClipPathOperation = downcast<ReferenceClipPathOperation>(*style.clipPath());
+        if (auto* clipperRenderer = renderer().ensureReferencedSVGResources().referencedClipperRenderer(renderer().document(), referenceClipPathOperation)) {
             context.save();
             auto referenceBox = snapRectToDevicePixels(rootRelativeBounds, renderer().document().deviceScaleFactor());
             auto offset = referenceBox.location();
             context.translate(offset);
             FloatRect svgReferenceBox { {}, referenceBox.size() };
-            downcast<RenderSVGResourceClipper>(*element->renderer()).applyClippingToContext(context, renderer(), svgReferenceBox, renderer().style().effectiveZoom());
+            clipperRenderer->applyClippingToContext(context, renderer(), svgReferenceBox, renderer().style().effectiveZoom());
             context.translate(-offset);
             return true;
         }

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (281966 => 281967)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -45,6 +45,7 @@
 #include "LogicalSelectionOffsetCaches.h"
 #include "Page.h"
 #include "PseudoElement.h"
+#include "ReferencedSVGResources.h"
 #include "RenderChildIterator.h"
 #include "RenderCounter.h"
 #include "RenderFragmentedFlow.h"
@@ -1946,6 +1947,15 @@
     setHasRareData(false);
 }
 
+RenderObject::RenderObjectRareData::RenderObjectRareData()
+    : m_hasReflection(false)
+    , m_isRenderFragmentedFlow(false)
+    , m_hasOutlineAutoAncestor(false)
+{
+}
+
+RenderObject::RenderObjectRareData::~RenderObjectRareData() = default;
+
 bool RenderObject::hasNonEmptyVisibleRectRespectingParentFrames() const
 {
     auto enclosingFrameRenderer = [] (const RenderObject& renderer) {

Modified: trunk/Source/WebCore/rendering/RenderObject.h (281966 => 281967)


--- trunk/Source/WebCore/rendering/RenderObject.h	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -56,6 +56,7 @@
 class LegacyInlineBox;
 class Path;
 class Position;
+class ReferencedSVGResources;
 class RenderBoxModelObject;
 class RenderInline;
 class RenderBlock;
@@ -927,12 +928,9 @@
     class RenderObjectRareData {
         WTF_MAKE_FAST_ALLOCATED;
     public:
-        RenderObjectRareData()
-            : m_hasReflection(false)
-            , m_isRenderFragmentedFlow(false)
-            , m_hasOutlineAutoAncestor(false)
-        {
-        }
+        RenderObjectRareData();
+        ~RenderObjectRareData();
+
         ADD_BOOLEAN_BITFIELD(hasReflection, HasReflection);
         ADD_BOOLEAN_BITFIELD(isRenderFragmentedFlow, IsRenderFragmentedFlow);
         ADD_BOOLEAN_BITFIELD(hasOutlineAutoAncestor, HasOutlineAutoAncestor);
@@ -939,6 +937,7 @@
 
         // From RenderElement
         std::unique_ptr<RenderStyle> cachedFirstLineStyle;
+        std::unique_ptr<ReferencedSVGResources> referencedSVGResources;
         WeakPtr<RenderBlockFlow> backdropRenderer;
     };
     

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp (281966 => 281967)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResource.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -31,6 +31,7 @@
 #include "RenderSVGResourceSolidColor.h"
 #include "RenderSVGRoot.h"
 #include "RenderView.h"
+#include "SVGResourceElementClient.h"
 #include "SVGResources.h"
 #include "SVGResourcesCache.h"
 #include "SVGURIReference.h"
@@ -153,7 +154,7 @@
     return s_sharedSolidPaintingResource;
 }
 
-static inline void removeFromCacheAndInvalidateDependencies(RenderElement& renderer, bool needsLayout)
+static void removeFromCacheAndInvalidateDependencies(RenderElement& renderer, bool needsLayout)
 {
     if (auto* resources = SVGResourcesCache::cachedResourcesForRenderer(renderer)) {
         if (RenderSVGResourceFilter* filter = resources->filter())
@@ -169,7 +170,9 @@
     if (!is<SVGElement>(renderer.element()))
         return;
 
-    for (auto& element : downcast<SVGElement>(*renderer.element()).referencingElements()) {
+    Ref svgElement = downcast<SVGElement>(*renderer.element());
+
+    for (auto& element : svgElement->referencingElements()) {
         if (auto* renderer = element->renderer()) {
             // We allow cycles in SVGDocumentExtensions reference sets in order to avoid expensive
             // reference graph adjustments on changes, so we need to break possible cycles here.
@@ -182,6 +185,12 @@
             invalidatingDependencies.get().remove(element.get());
         }
     }
+
+    for (auto& cssClient : svgElement->referencingCSSClients()) {
+        if (!cssClient)
+            continue;
+        cssClient->resourceChanged(svgElement.get());
+    }
 }
 
 void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject& object, bool needsLayout)

Modified: trunk/Source/WebCore/svg/SVGElement.cpp (281966 => 281967)


--- trunk/Source/WebCore/svg/SVGElement.cpp	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/svg/SVGElement.cpp	2021-09-02 23:54:29 UTC (rev 281967)
@@ -46,6 +46,7 @@
 #include "SVGPropertyAnimatorFactory.h"
 #include "SVGRenderStyle.h"
 #include "SVGRenderSupport.h"
+#include "SVGResourceElementClient.h"
 #include "SVGSVGElement.h"
 #include "SVGTitleElement.h"
 #include "SVGUseElement.h"
@@ -336,6 +337,25 @@
         destination->removeReferencingElement(*this);
 }
 
+Vector<WeakPtr<SVGResourceElementClient>> SVGElement::referencingCSSClients() const
+{
+    if (!m_svgRareData)
+        return { };
+    return copyToVector(m_svgRareData->referencingCSSClients());
+}
+
+void SVGElement::addReferencingCSSClient(SVGResourceElementClient& client)
+{
+    ensureSVGRareData().addReferencingCSSClient(client);
+}
+
+void SVGElement::removeReferencingCSSClient(SVGResourceElementClient& client)
+{
+    if (!m_svgRareData)
+        return;
+    ensureSVGRareData().removeReferencingCSSClient(client);
+}
+
 SVGElement* SVGElement::correspondingElement() const
 {
     return m_svgRareData ? m_svgRareData->correspondingElement() : nullptr;

Modified: trunk/Source/WebCore/svg/SVGElement.h (281966 => 281967)


--- trunk/Source/WebCore/svg/SVGElement.h	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/svg/SVGElement.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -41,6 +41,7 @@
 class SVGDocumentExtensions;
 class SVGElementRareData;
 class SVGPropertyAnimatorFactory;
+class SVGResourceElementClient;
 class SVGSVGElement;
 class SVGUseElement;
 
@@ -98,6 +99,11 @@
     void removeReferencingElement(SVGElement&);
     void removeElementReference();
 
+    Vector<WeakPtr<SVGResourceElementClient>> referencingCSSClients() const;
+    void addReferencingCSSClient(SVGResourceElementClient&);
+    void removeReferencingCSSClient(SVGResourceElementClient&);
+
+
     SVGElement* correspondingElement() const;
     RefPtr<SVGUseElement> correspondingUseElement() const;
 

Modified: trunk/Source/WebCore/svg/SVGElementRareData.h (281966 => 281967)


--- trunk/Source/WebCore/svg/SVGElementRareData.h	2021-09-02 23:39:39 UTC (rev 281966)
+++ trunk/Source/WebCore/svg/SVGElementRareData.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -19,6 +19,7 @@
 
 #pragma once
 
+#include "SVGResourceElementClient.h"
 #include "StyleProperties.h"
 #include "StyleResolver.h"
 #include <wtf/HashSet.h>
@@ -55,6 +56,10 @@
     SVGElement* referenceTarget() const { return m_referenceTarget.get(); }
     void setReferenceTarget(WeakPtr<SVGElement>&& element) { m_referenceTarget = WTFMove(element); }
 
+    void addReferencingCSSClient(SVGResourceElementClient& client) { m_referencingCSSClients.add(client); }
+    void removeReferencingCSSClient(SVGResourceElementClient& client) { m_referencingCSSClients.remove(client); }
+    const WeakHashSet<SVGResourceElementClient>& referencingCSSClients() const { return m_referencingCSSClients; }
+
     SVGElement* correspondingElement() { return m_correspondingElement.get(); }
     void setCorrespondingElement(SVGElement* correspondingElement) { m_correspondingElement = makeWeakPtr(correspondingElement); }
 
@@ -86,6 +91,9 @@
 private:
     WeakHashSet<SVGElement> m_referencingElements;
     WeakPtr<SVGElement> m_referenceTarget;
+
+    WeakHashSet<SVGResourceElementClient> m_referencingCSSClients;
+
     WeakHashSet<SVGElement> m_instances;
     WeakPtr<SVGElement> m_correspondingElement;
     bool m_instancesUpdatesBlocked : 1;

Added: trunk/Source/WebCore/svg/SVGResourceElementClient.h (0 => 281967)


--- trunk/Source/WebCore/svg/SVGResourceElementClient.h	                        (rev 0)
+++ trunk/Source/WebCore/svg/SVGResourceElementClient.h	2021-09-02 23:54:29 UTC (rev 281967)
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+
+class SVGElement;
+
+class SVGResourceElementClient : public CanMakeWeakPtr<SVGResourceElementClient> {
+public:
+    virtual ~SVGResourceElementClient() = default;
+
+    virtual void resourceChanged(SVGElement&) = 0;
+
+};
+
+} // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to