Skip to content

Commit

Permalink
[LBSE] Rework SVG resource invalidation
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=264230

Reviewed by Rob Buis.

Overhaul of repainting / resource invalidating logic for LBSE.

- Stop communicating resource invalidation via layout(). The legacy
  SVG engine used to relayout all resource clients upon resource
  changes. This is very inefficient, and leads to lots of unnecessary
  layouts.

  `RenderElement::styleDidChange` is the main entry point for resource
  invalidation -- re-using the existing concept from CSS. After the
  difference between the old and new RenderStyle is computed, we know
  if a layout needs to be performed (~ 'StyleDifference::Layout') or
  if a repaint is sufficient (~ 'StyleDifference::Repaint').

  e.g. Changing the 'x' attribute of a SVGRectElement results in a
       'StyleDifference::Layout' asynchronously requesting a relayout
       of the affected rectangle. Changing only the e.g. 'fill' color
       will lead to a 'StyleDifference::Repaint' indicating that repaint
       is sufficient, and a costly layout can be avoided.

  Inject a call to 'repaintClientsOfReferencedSVGResources()' in
  'RenderElement::styleDidChange()' if the style change leads to a
  repaint. Whenever a renderer needs a repaint, we have to check if
  it is a RenderSVGResourceContainer (such as RenderSVGResourceClipper)
  or enclosed by a RenderSVGResourceContainer. If true, the clients
  that reference the RenderSVGResourceContainer are the renderers that
  need a repaint, not the original renderer, whose style got changed.

  'RenderElement::repaintClientsOfReferencedSVGResources()' queries
  'SVGElement::referencingCSSClients()' to lookup all SVG DOM elements
  that reference the element, associated with the renderer. These clients
  are asked to repaint themselves, if they've got an associated renderer.

- Get rid of TreeScope::addPendingSVGResource & friends for LBSE.
  The code remains only for the legacy SVG engine. LBSE will
  exclusively rely on 'ReferencedSVGResources' for tracking SVG
  resources <-> ID mapping based on the DOM tree, not render tree.

- Teach ReferencedSVGResources about marker/mask references - clipPath
  were already supported.

- Move RenderLayer::clipperFromStyle() -> RenderLayerModelObject::svgClipperResourceFromStyle().
  This method shall be used to get access to the RenderSVGResourceClipper in LBSE, properly taking
  care of 'pending resource handling' (if the requested resource, is not found in the DOM tree,
  we remember that, and notify the renderer that wanted to use the not-yet-existing-resource, once
  it appears).

- Make sure there are no more "LegacyRenderSVGResource::markForLayoutAndParentResourceInvalidation"
  sledgehammer calls in LBSE -- only careful case-by-case decisions on what we need to do.

- Stop inheriting RenderSVGResourceContainer from LegacySVGResource. Stop using SVGResources
  and SVGResourcesCache in LBSE -- place RELEASE_ASSERTS in prominent places to be sure this is
  all no longer used for LBSE.

This work will be completed, once all resources are converted to the new mechanisms in LBSE.

Covered by existing tests -- progressions with LBSE.

* LayoutTests/platform/mac-sonoma-wk2-lbse-text/svg/custom/svg-fonts-in-html-expected.png: Added.
* LayoutTests/platform/mac-sonoma-wk2-lbse-text/svg/custom/svg-fonts-in-html-expected.txt:
* LayoutTests/platform/mac-sonoma-wk2-lbse-text/svg/repaint/repaint-non-scaling-stroke-text-decoration-expected.txt:
* LayoutTests/platform/mac-sonoma-wk2-lbse-text/svg/repaint/repaint-non-scaling-stroke-text-expected.txt:
* LayoutTests/svg/repaint/clip-path-object-bounding-box-expected.txt:
* LayoutTests/svg/repaint/clip-path-object-bounding-box-shrink-expected.txt:
* LayoutTests/svg/repaint/clip-path-object-bounding-box-shrink.html:
* LayoutTests/svg/repaint/clip-path-object-bounding-box-transformed-expected.txt:
* LayoutTests/svg/repaint/clip-path-user-space-on-use-expected.txt:
* LayoutTests/svg/repaint/clip-path-user-space-on-use-shrink-expected.txt:
* LayoutTests/svg/repaint/clip-path-user-space-on-use-shrink.html:
* LayoutTests/svg/repaint/clip-path-user-space-on-use-transformed-expected.txt:
* LayoutTests/svg/resource-invalidation/clip-path-resource-invalidation-expected.html: Fix incorrect expectation, due to duplicated 'c6' element.
* LayoutTests/svg/resource-invalidation/clip-path-resource-invalidation.html: Make testcase work in browser, not only in the test runner.
* Source/WebCore/dom/TreeScope.cpp:
(WebCore::TreeScope::removeSVGResource):
(WebCore::TreeScope::lookupSVGResourceById const): Deleted.
* Source/WebCore/dom/TreeScope.h:
* Source/WebCore/rendering/ReferencedSVGResources.cpp:
(WebCore::ReferencedSVGResources::referencedMarkerElement):
(WebCore::ReferencedSVGResources::referencedMaskElement):
* Source/WebCore/rendering/ReferencedSVGResources.h:
* Source/WebCore/rendering/RenderElement.cpp:
(WebCore::RenderElement::styleDidChange):
(WebCore::RenderElement::repaintRendererOrClientsOfReferencedSVGResources const):
(WebCore::RenderElement::repaintClientsOfReferencedSVGResources const):
* Source/WebCore/rendering/RenderElement.h:
* Source/WebCore/rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintSVGResourceLayer):
(WebCore::RenderLayer::setupClipPath):
(WebCore::RenderLayer::calculateClipRects const):
* Source/WebCore/rendering/RenderLayer.h:
* Source/WebCore/rendering/RenderLayerInlines.h:
(WebCore::RenderLayer::hasNonOpacityTransparency const):
* Source/WebCore/rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::svgClipperResourceFromStyle const):
(WebCore::RenderLayerModelObject::repaintOrRelayoutAfterSVGTransformChange):
* Source/WebCore/rendering/RenderLayerModelObject.h:
* Source/WebCore/rendering/RenderObject.h:
(WebCore::RenderObject::isLegacyRenderSVGResourceMarker const):
* Source/WebCore/rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::layoutChildren):
* Source/WebCore/rendering/svg/RenderSVGImage.cpp:
(WebCore::RenderSVGImage::imageChanged):
* Source/WebCore/rendering/svg/RenderSVGPath.cpp:
(WebCore::RenderSVGPath::shouldGenerateMarkerPositions const):
(WebCore::RenderSVGPath::drawMarkers):
(WebCore::RenderSVGPath::computeMarkerBoundingBox const):
(WebCore::RenderSVGPath::processMarkerPositions):
* Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp:
(WebCore::RenderSVGResourceClipper::applyMaskClipping):
(WebCore::RenderSVGResourceClipper::resourceBoundingBox):
* Source/WebCore/rendering/svg/RenderSVGResourceClipper.h:
* Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp:
(WebCore::RenderSVGResourceContainer::willBeDestroyed):
(WebCore::RenderSVGResourceContainer::idChanged):
(WebCore::RenderSVGResourceContainer::registerResource):
(WebCore::RenderSVGResourceContainer::repaintAllClients const):
* Source/WebCore/rendering/svg/RenderSVGResourceContainer.h:
* Source/WebCore/rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::layoutChildren):
(WebCore::RenderSVGRoot::paintObject):
* Source/WebCore/rendering/svg/SVGBoundingBoxComputation.cpp:
(WebCore::SVGBoundingBoxComputation::adjustBoxForClippingAndEffects const):
* Source/WebCore/rendering/svg/SVGContainerLayout.cpp:
(WebCore::SVGContainerLayout::layoutChildren):
(WebCore::SVGContainerLayout::layoutDifferentRootIfNeeded): Deleted.
(WebCore::SVGContainerLayout::invalidateResourcesOfChildren): Deleted.
* Source/WebCore/rendering/svg/SVGContainerLayout.h:
* Source/WebCore/rendering/svg/SVGRenderSupport.cpp:
(WebCore::SVGRenderSupport::pointInClippingArea):
(WebCore::SVGRenderSupport::paintSVGClippingMask):
* Source/WebCore/rendering/svg/SVGRenderSupport.h:
* Source/WebCore/rendering/svg/SVGRenderingContext.cpp:
(WebCore::SVGRenderingContext::prepareToRenderSVGContent):
* Source/WebCore/rendering/svg/SVGResourcesCache.cpp:
(WebCore::SVGResourcesCache::addResourcesFromRenderer):
(WebCore::SVGResourcesCache::removeResourcesFromRenderer):
(WebCore::resourcesCacheFromRenderer):
(WebCore::SVGResourcesCache::clientLayoutChanged):
(WebCore::SVGResourcesCache::clientStyleChanged):
(WebCore::SVGResourcesCache::clientWasAddedToTree):
(WebCore::SVGResourcesCache::clientWillBeRemovedFromTree):
(WebCore::SVGResourcesCache::clientDestroyed):
(WebCore::SVGResourcesCache::resourceDestroyed):
(WebCore::SVGResourcesCache::SetStyleForScope::setStyle):
* Source/WebCore/rendering/svg/SVGResourcesCycleSolver.cpp:
(WebCore::SVGResourcesCycleSolver::resolveCycles):
* Source/WebCore/rendering/svg/legacy/LegacyRenderSVGResource.cpp:
(WebCore::requestPaintingResource):
(WebCore::LegacyRenderSVGResource::markForLayoutAndParentResourceInvalidationIfNeeded):
* Source/WebCore/rendering/svg/legacy/LegacyRenderSVGResourceMarker.h:
(isType):
* Source/WebCore/rendering/updating/RenderTreeUpdater.cpp:
(WebCore::RenderTreeUpdater::updateSVGRenderer):
* Source/WebCore/svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::notifyFinished):
* Source/WebCore/svg/SVGSVGElement.cpp:
(WebCore::SVGSVGElement::scrollToFragment):
(WebCore::SVGSVGElement::resetScrollAnchor):

Canonical link: https://commits.webkit.org/270992@main
  • Loading branch information
nikolaszimmermann committed Nov 21, 2023
1 parent e3fed8d commit 4e52435
Show file tree
Hide file tree
Showing 47 changed files with 425 additions and 246 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ layer at (173,32) size 454x454
layer at (173,47) size 454x190
RenderBlock (positioned) {H1} at (0,15) size 454x191 [color=#DD9955]
RenderInline {SPAN} at (0,0) size 343x192
RenderText {#text} at (62,-1) size 343x192
text run at (62,-1) width 165: "CSS"
RenderText {#text} at (63,-1) size 343x192
text run at (63,-1) width 164: "CSS"
text run at (198,-1) width 193: " ZEN"
text run at (55,94) width 343: "GARDEN"
layer at (173,119) size 454x21
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Hello
(repaint rects
(rect 13 16 40 22)
(rect 9 12 48 30)
)

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
Hello
(repaint rects
(rect 13 16 40 22)
(rect 9 12 48 30)
)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(repaint rects
(rect 0 0 100 100)
(rect 25 25 50 50)
)

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
(repaint rects
(rect 0 0 100 100)
(rect 50 50 50 50)
(rect 0 0 50 50)
)

Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
<svg style="position: absolute; top: 0px; left: 0px; width: 500px; height: 200px">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<rect id="clipContent" x="0" y="0" width="1" height="1"></rect>
<rect id="clipContent" x="0.5" y="0.5" width="0.5" height="0.5"></rect>
</clipPath>
</defs>
<rect id="target" x="0" y="0" width="100" height="100" clip-path="url(#clip)" fill="red"/>
</svg>
<script>
function repaintTest() {
document.getElementById("clipContent").setAttribute('x', '.25');
document.getElementById("clipContent").setAttribute('y', '.25');
document.getElementById("clipContent").setAttribute('width', '.5');
document.getElementById("clipContent").setAttribute('height', '.5');
document.getElementById("clipContent").setAttribute('x', '0');
document.getElementById("clipContent").setAttribute('y', '0');
}
</script>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
(repaint rects
(rect 25 25 50 50)
)

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(repaint rects
(rect 0 0 100 100)
(rect 25 25 50 50)
)

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
(repaint rects
(rect 0 0 100 100)
(rect 50 50 50 50)
(rect 0 0 50 50)
)

Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,15 @@
<svg style="position: absolute; top: 0px; left: 0px; width: 500px; height: 200px">
<defs>
<clipPath id="clip" clipPathUnits="userSpaceOnUse">
<rect id="clipContent" x="0" y="0" width="100" height="100"></rect>
<rect id="clipContent" x="50" y="50" width="50" height="50"></rect>
</clipPath>
</defs>
<rect id="target" x="0" y="0" width="100" height="100" clip-path="url(#clip)" fill="red"/>
</svg>
<script>
function repaintTest() {
document.getElementById("clipContent").setAttribute('x', '25');
document.getElementById("clipContent").setAttribute('y', '25');
document.getElementById("clipContent").setAttribute('width', '50');
document.getElementById("clipContent").setAttribute('height', '50');
document.getElementById("clipContent").setAttribute('x', '0');
document.getElementById("clipContent").setAttribute('y', '0');
}
</script>
</body>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
(repaint rects
(rect 25 25 50 50)
)

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
<clipPath id="c6" clipPathUnits="objectBoundingBox">
<rect width="0.5" height="0.5"/>
</clipPath>
<clipPath id="c6" clipPathUnits="objectBoundingBox">
<rect width="175" height="175"/>
</clipPath>
<clipPath id="c7" clipPathUnits="objectBoundingBox">
<rect width="0.5" height="0.5"/>
</clipPath>
Expand All @@ -38,7 +35,7 @@
<rect id="r3" x="250" y="50" width="50" height="50"/>
<rect id="r4" x="350" y="50" width="50" height="50" clip-path="url(#c4)" fill="blue"/>
<rect id="r5" x="50" y="150" width="75" height="50" clip-path="url(#c5)"/>
<rect id="r6" x="150" y="150" width="50" height="50" clip-path="url(#c6)"/>
<rect id="r6" x="150" y="150" width="100" height="100" clip-path="url(#c6)"/>
<rect id="r7" x="250" y="150" width="50" height="50" clip-path="url(#c7)"/>
<rect id="r8" x="350" y="150" width="50" height="50" clip-path="url(#c8)"/>
</svg>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html> <!-- webkit-test-runner [ LayerBasedSVGEngineEnabled=true ] -->
<body onload="run();">
<svg width="450" height="250">
<defs>
Expand Down Expand Up @@ -42,19 +42,19 @@
</svg>
<script>
function run() {
if (window.testRunner) {
if (window.testRunner)
testRunner.waitUntilDone();
requestAnimationFrame(function() {
r1.setAttribute("clip-path", "url(#c1)"); // change from no clipPath to some clipPath
r2.setAttribute("clip-path", "url(#c2b)"); // change from one clipPath to another
r3.removeAttribute("clip-path"); // change from a clipPath to no clipPath
r4.setAttribute("fill", "blue"); // change style of clipPath resource client
r5.setAttribute("width", "75"); // change layout of clipPath resource client
c6.setAttribute("clipPathUnits", "objectBoundingBox"); // change clipPath attribute
c7.firstElementChild.setAttribute("visibility", "visible"); // change style of clipPath contents
c8.firstElementChild.setAttribute("width", "1"); // change other attribute of clipPath contents
requestAnimationFrame(function() {
r1.setAttribute("clip-path", "url(#c1)"); // change from no clipPath to some clipPath
r2.setAttribute("clip-path", "url(#c2b)"); // change from one clipPath to another
r3.removeAttribute("clip-path"); // change from a clipPath to no clipPath
r4.setAttribute("fill", "blue"); // change style of clipPath resource client
r5.setAttribute("width", "75"); // change layout of clipPath resource client
c6.setAttribute("clipPathUnits", "objectBoundingBox"); // change clipPath attribute
c7.firstElementChild.setAttribute("visibility", "visible"); // change style of clipPath contents
c8.firstElementChild.setAttribute("width", "1"); // change other attribute of clipPath contents
if (window.testRunner)
testRunner.notifyDone();
});
}
});
}
</script>
27 changes: 0 additions & 27 deletions Source/WebCore/dom/TreeScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,9 +640,6 @@ struct SVGResourcesMap {

MemoryCompactRobinHoodHashMap<AtomString, WeakHashSet<SVGElement, WeakPtrImplWithEventTargetData>> pendingResources;
MemoryCompactRobinHoodHashMap<AtomString, WeakHashSet<SVGElement, WeakPtrImplWithEventTargetData>> pendingResourcesForRemoval;
#if ENABLE(LAYER_BASED_SVG_ENGINE)
MemoryCompactRobinHoodHashMap<AtomString, RenderSVGResourceContainer*> resources;
#endif
MemoryCompactRobinHoodHashMap<AtomString, LegacyRenderSVGResourceContainer*> legacyResources;
};

Expand All @@ -653,17 +650,6 @@ SVGResourcesMap& TreeScope::svgResourcesMap() const
return *m_svgResourcesMap;
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
void TreeScope::addSVGResource(const AtomString& id, RenderSVGResourceContainer& resource)
{
if (id.isEmpty())
return;

// Replaces resource if already present, to handle potential id changes
svgResourcesMap().resources.set(id, &resource);
}
#endif

void TreeScope::addSVGResource(const AtomString& id, LegacyRenderSVGResourceContainer& resource)
{
if (id.isEmpty())
Expand All @@ -678,22 +664,9 @@ void TreeScope::removeSVGResource(const AtomString& id)
if (id.isEmpty())
return;

#if ENABLE(LAYER_BASED_SVG_ENGINE)
svgResourcesMap().resources.remove(id);
#endif
svgResourcesMap().legacyResources.remove(id);
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
RenderSVGResourceContainer* TreeScope::lookupSVGResourceById(const AtomString& id) const
{
if (id.isEmpty())
return nullptr;

return svgResourcesMap().resources.get(id);
}
#endif

LegacyRenderSVGResourceContainer* TreeScope::lookupLegacySVGResoureById(const AtomString& id) const
{
if (id.isEmpty())
Expand Down
7 changes: 0 additions & 7 deletions Source/WebCore/dom/TreeScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class LegacyRenderSVGResourceContainer;
class IdTargetObserverRegistry;
class Node;
class RadioButtonGroups;
class RenderSVGResourceContainer;
class SVGElement;
class ShadowRoot;
class TreeScopeOrderedMap;
Expand Down Expand Up @@ -143,14 +142,8 @@ class TreeScope {
std::span<const RefPtr<CSSStyleSheet>> adoptedStyleSheets() const;
ExceptionOr<void> setAdoptedStyleSheets(Vector<RefPtr<CSSStyleSheet>>&&);

#if ENABLE(LAYER_BASED_SVG_ENGINE)
void addSVGResource(const AtomString& id, RenderSVGResourceContainer&);
#endif
void addSVGResource(const AtomString& id, LegacyRenderSVGResourceContainer&);
void removeSVGResource(const AtomString& id);
#if ENABLE(LAYER_BASED_SVG_ENGINE)
RenderSVGResourceContainer* lookupSVGResourceById(const AtomString& id) const;
#endif
LegacyRenderSVGResourceContainer* lookupLegacySVGResoureById(const AtomString& id) const;

void addPendingSVGResource(const AtomString& id, SVGElement&);
Expand Down
28 changes: 28 additions & 0 deletions Source/WebCore/rendering/ReferencedSVGResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include "SVGClipPathElement.h"
#include "SVGElementTypeHelpers.h"
#include "SVGFilterElement.h"
#include "SVGMarkerElement.h"
#include "SVGMaskElement.h"
#include "SVGResourceElementClient.h"

#include <wtf/IsoMallocInlines.h>
Expand Down Expand Up @@ -146,6 +148,7 @@ RefPtr<SVGElement> ReferencedSVGResources::elementForResourceID(TreeScope& treeS
return downcast<SVGElement>(WTFMove(element));
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
RefPtr<SVGClipPathElement> ReferencedSVGResources::referencedClipPathElement(TreeScope& treeScope, const ReferencePathOperation& clipPath)
{
if (clipPath.fragment().isEmpty())
Expand All @@ -154,6 +157,31 @@ RefPtr<SVGClipPathElement> ReferencedSVGResources::referencedClipPathElement(Tre
return element ? downcast<SVGClipPathElement>(WTFMove(element)) : nullptr;
}

RefPtr<SVGMarkerElement> ReferencedSVGResources::referencedMarkerElement(TreeScope& treeScope, const String& markerResource)
{
auto resourceID = SVGURIReference::fragmentIdentifierFromIRIString(markerResource, treeScope.documentScope());
if (resourceID.isEmpty())
return nullptr;

RefPtr element = elementForResourceID(treeScope, resourceID, SVGNames::maskTag);
return element ? downcast<SVGMarkerElement>(WTFMove(element)) : nullptr;
}

RefPtr<SVGMaskElement> ReferencedSVGResources::referencedMaskElement(TreeScope& treeScope, const StyleImage& maskImage)
{
auto reresolvedURL = maskImage.reresolvedURL(treeScope.documentScope());
if (reresolvedURL.isEmpty())
return nullptr;

auto resourceID = SVGURIReference::fragmentIdentifierFromIRIString(reresolvedURL.string(), treeScope.documentScope());
if (resourceID.isEmpty())
return nullptr;

RefPtr element = elementForResourceID(treeScope, resourceID, SVGNames::maskTag);
return element ? downcast<SVGMaskElement>(WTFMove(element)) : nullptr;
}
#endif

RefPtr<SVGFilterElement> ReferencedSVGResources::referencedFilterElement(TreeScope& treeScope, const ReferenceFilterOperation& referenceFilter)
{
if (referenceFilter.fragment().isEmpty())
Expand Down
17 changes: 13 additions & 4 deletions Source/WebCore/rendering/ReferencedSVGResources.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,18 @@ class CSSSVGResourceElementClient;
class Document;
class LegacyRenderSVGResourceClipper;
class LegacyRenderSVGResourceContainer;
class ReferencePathOperation;
class QualifiedName;
class ReferenceFilterOperation;
class ReferencePathOperation;
class RenderElement;
class RenderSVGResourceFilter;
class RenderStyle;
class QualifiedName;
class SVGClipPathElement;
class SVGElement;
class SVGFilterElement;
class SVGMarkerElement;
class SVGMaskElement;
class StyleImage;
class TreeScope;

class ReferencedSVGResources {
Expand All @@ -57,13 +60,19 @@ class ReferencedSVGResources {
static Vector<std::pair<AtomString, QualifiedName>> referencedSVGResourceIDs(const RenderStyle&);
void updateReferencedResources(TreeScope&, const Vector<std::pair<AtomString, QualifiedName>>&);

// Clipping needs a renderer, filters use an element.
// Legacy: Clipping needs a renderer, filters use an element.
static LegacyRenderSVGResourceClipper* referencedClipperRenderer(TreeScope&, const ReferencePathOperation&);
static RefPtr<SVGClipPathElement> referencedClipPathElement(TreeScope&, const ReferencePathOperation&);
static RefPtr<SVGFilterElement> referencedFilterElement(TreeScope&, const ReferenceFilterOperation&);

static LegacyRenderSVGResourceContainer* referencedRenderResource(TreeScope&, const AtomString& fragment);

#if ENABLE(LAYER_BASED_SVG_ENGINE)
// LBSE: All element based.
static RefPtr<SVGClipPathElement> referencedClipPathElement(TreeScope&, const ReferencePathOperation&);
static RefPtr<SVGMarkerElement> referencedMarkerElement(TreeScope&, const String&);
static RefPtr<SVGMaskElement> referencedMaskElement(TreeScope&, const StyleImage&);
#endif

private:
static RefPtr<SVGElement> elementForResourceID(TreeScope&, const AtomString& resourceID, const QualifiedName& tagName);

Expand Down
31 changes: 30 additions & 1 deletion Source/WebCore/rendering/RenderElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
#include "RenderLineBreak.h"
#include "RenderListItem.h"
#include "RenderMultiColumnSpannerPlaceholder.h"
#include "RenderSVGResourceContainer.h"
#include "RenderSVGViewportContainer.h"
#include "RenderStyleSetters.h"
#include "RenderTableCaption.h"
Expand Down Expand Up @@ -970,8 +971,13 @@ void RenderElement::styleDidChange(StyleDifference diff, const RenderStyle* oldS

SVGRenderSupport::styleChanged(*this, oldStyle);

if (diff >= StyleDifference::Repaint)
if (diff >= StyleDifference::Repaint) {
updateReferencedSVGResources();
#if ENABLE(LAYER_BASED_SVG_ENGINE)
if (oldStyle && diff <= StyleDifference::RepaintLayer)
repaintClientsOfReferencedSVGResources();
#endif
}

if (!m_parent)
return;
Expand Down Expand Up @@ -2098,6 +2104,29 @@ void RenderElement::updateReferencedSVGResources()
clearReferencedSVGResources();
}

#if ENABLE(LAYER_BASED_SVG_ENGINE)
void RenderElement::repaintRendererOrClientsOfReferencedSVGResources() const
{
auto* enclosingResourceContainer = lineageOfType<RenderSVGResourceContainer>(*this).first();
if (!enclosingResourceContainer) {
repaint();
return;
}

// This implicitly checks if LBSE is activated. If not, no 'RenderSVGResourceContainer' objects are present in the render tree.
enclosingResourceContainer->repaintAllClients();
}

void RenderElement::repaintClientsOfReferencedSVGResources() const
{
if (!document().settings().layerBasedSVGEngineEnabled())
return;

if (auto* enclosingResourceContainer = lineageOfType<RenderSVGResourceContainer>(*this).first())
enclosingResourceContainer->repaintAllClients();
}
#endif

#if ENABLE(TEXT_AUTOSIZING)
static RenderObject::BlockContentHeightType includeNonFixedHeight(const RenderObject& renderer)
{
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/rendering/RenderElement.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ class RenderElement : public RenderObject {
enum class RequiresFullRepaint : bool { No, Yes };
bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, RequiresFullRepaint, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr);

#if ENABLE(LAYER_BASED_SVG_ENGINE)
void repaintClientsOfReferencedSVGResources() const;
void repaintRendererOrClientsOfReferencedSVGResources() const;
#endif

bool borderImageIsLoadedAndCanBeRendered() const;
bool isVisibleIgnoringGeometry() const;
bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
Expand Down
Loading

0 comments on commit 4e52435

Please sign in to comment.