Title: [286466] trunk/Source/WebCore
Revision
286466
Author
s...@apple.com
Date
2021-12-02 16:37:00 -0800 (Thu, 02 Dec 2021)

Log Message

[GPU Process] Move the FilterEffect boundaries to a new class FilterEffectGeometry
https://bugs.webkit.org/show_bug.cgi?id=233618
rdar://85881969

Reviewed by Cameron McCormack.

The plan is to have Filter own its geometry and the geometry of the
FilterEffects. So move the boundaries and their flags from FilterEffect
to a new class called FilterEffectGeometry.

SVGFilterBuilder will calculate the FilterEffectGeometry for each FilterEffect
and store it in map { key: FilterEffect, value: FilterEffectGeometry }.
Eventually this map is moved to SVGFilter which will be used in the
virtual function effectGeometry(). determineFilterPrimitiveSubregion()
will call this virtual function to calculate the primitive subregion.

* Headers.cmake:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/filters/Filter.h:
(WebCore::Filter::effectGeometry const):
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::determineFilterPrimitiveSubregion):
(WebCore::FilterEffect::apply):
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::hasX const): Deleted.
(WebCore::FilterEffect::setHasX): Deleted.
(WebCore::FilterEffect::hasY const): Deleted.
(WebCore::FilterEffect::setHasY): Deleted.
(WebCore::FilterEffect::hasWidth const): Deleted.
(WebCore::FilterEffect::setHasWidth): Deleted.
(WebCore::FilterEffect::hasHeight const): Deleted.
(WebCore::FilterEffect::setHasHeight): Deleted.
(WebCore::FilterEffect::effectBoundaries const): Deleted.
(WebCore::FilterEffect::setEffectBoundaries): Deleted.
* platform/graphics/filters/FilterEffectGeometry.h: Added.
(WebCore::FilterEffectGeometry::FilterEffectGeometry):
(WebCore::FilterEffectGeometry::x const):
(WebCore::FilterEffectGeometry::y const):
(WebCore::FilterEffectGeometry::width const):
(WebCore::FilterEffectGeometry::height const):
* svg/SVGFilterPrimitiveStandardAttributes.cpp:
(WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes const): Deleted.
* svg/SVGFilterPrimitiveStandardAttributes.h:
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::create):
(WebCore::SVGFilter::effectGeometry const):
* svg/graphics/filters/SVGFilter.h:
* svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::boundarySetFlagsForElement):
(WebCore::SVGFilterBuilder::buildFilterEffects):
* svg/graphics/filters/SVGFilterBuilder.h:
(WebCore::SVGFilterBuilder::takeEffectGeometryMap):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (286465 => 286466)


--- trunk/Source/WebCore/ChangeLog	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/ChangeLog	2021-12-03 00:37:00 UTC (rev 286466)
@@ -1,3 +1,58 @@
+2021-12-02  Said Abou-Hallawa  <s...@apple.com>
+
+        [GPU Process] Move the FilterEffect boundaries to a new class FilterEffectGeometry
+        https://bugs.webkit.org/show_bug.cgi?id=233618
+        rdar://85881969
+
+        Reviewed by Cameron McCormack.
+
+        The plan is to have Filter own its geometry and the geometry of the
+        FilterEffects. So move the boundaries and their flags from FilterEffect 
+        to a new class called FilterEffectGeometry. 
+
+        SVGFilterBuilder will calculate the FilterEffectGeometry for each FilterEffect
+        and store it in map { key: FilterEffect, value: FilterEffectGeometry }.
+        Eventually this map is moved to SVGFilter which will be used in the
+        virtual function effectGeometry(). determineFilterPrimitiveSubregion()
+        will call this virtual function to calculate the primitive subregion.
+
+        * Headers.cmake:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::effectGeometry const):
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::determineFilterPrimitiveSubregion):
+        (WebCore::FilterEffect::apply):
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::hasX const): Deleted.
+        (WebCore::FilterEffect::setHasX): Deleted.
+        (WebCore::FilterEffect::hasY const): Deleted.
+        (WebCore::FilterEffect::setHasY): Deleted.
+        (WebCore::FilterEffect::hasWidth const): Deleted.
+        (WebCore::FilterEffect::setHasWidth): Deleted.
+        (WebCore::FilterEffect::hasHeight const): Deleted.
+        (WebCore::FilterEffect::setHasHeight): Deleted.
+        (WebCore::FilterEffect::effectBoundaries const): Deleted.
+        (WebCore::FilterEffect::setEffectBoundaries): Deleted.
+        * platform/graphics/filters/FilterEffectGeometry.h: Added.
+        (WebCore::FilterEffectGeometry::FilterEffectGeometry):
+        (WebCore::FilterEffectGeometry::x const):
+        (WebCore::FilterEffectGeometry::y const):
+        (WebCore::FilterEffectGeometry::width const):
+        (WebCore::FilterEffectGeometry::height const):
+        * svg/SVGFilterPrimitiveStandardAttributes.cpp:
+        (WebCore::SVGFilterPrimitiveStandardAttributes::setStandardAttributes const): Deleted.
+        * svg/SVGFilterPrimitiveStandardAttributes.h:
+        * svg/graphics/filters/SVGFilter.cpp:
+        (WebCore::SVGFilter::create):
+        (WebCore::SVGFilter::effectGeometry const):
+        * svg/graphics/filters/SVGFilter.h:
+        * svg/graphics/filters/SVGFilterBuilder.cpp:
+        (WebCore::boundarySetFlagsForElement):
+        (WebCore::SVGFilterBuilder::buildFilterEffects):
+        * svg/graphics/filters/SVGFilterBuilder.h:
+        (WebCore::SVGFilterBuilder::takeEffectGeometryMap):
+
 2021-12-02  Chris Dumez  <cdu...@apple.com>
 
         Move Shared Worker classes to WebCore/workers/shared

Modified: trunk/Source/WebCore/Headers.cmake (286465 => 286466)


--- trunk/Source/WebCore/Headers.cmake	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/Headers.cmake	2021-12-03 00:37:00 UTC (rev 286466)
@@ -1561,6 +1561,7 @@
     platform/graphics/cv/ImageTransferSessionVT.h
 
     platform/graphics/filters/Filter.h
+    platform/graphics/filters/FilterEffectGeometry.h
     platform/graphics/filters/FilterFunction.h
     platform/graphics/filters/FilterImage.h
     platform/graphics/filters/FilterOperation.h

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (286465 => 286466)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2021-12-03 00:37:00 UTC (rev 286466)
@@ -2304,6 +2304,7 @@
 		724ED3321A3A8B2300F5F13C /* JSEXTBlendMinMax.h in Headers */ = {isa = PBXBuildFile; fileRef = 724ED3301A3A8B2300F5F13C /* JSEXTBlendMinMax.h */; };
 		724EE5501DC80D7F00A91FFB /* ActivityState.h in Headers */ = {isa = PBXBuildFile; fileRef = 724EE54E1DC7F25B00A91FFB /* ActivityState.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		724EE5511DC80D8400A91FFB /* ActivityStateChangeObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 724EE54F1DC7F25B00A91FFB /* ActivityStateChangeObserver.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		726CDE202759735000A445B2 /* FilterEffectGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = 729661A2275960A500E7DF9B /* FilterEffectGeometry.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		726D56E2253AE28D0002EF90 /* PlatformImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 726D56E1253AE0430002EF90 /* PlatformImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		726D56E3253AE3660002EF90 /* NativeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 55A336F61D8209F40022C4C7 /* NativeImage.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		727A7F3A24078B84004D2931 /* ImageBufferIOSurfaceBackend.h in Headers */ = {isa = PBXBuildFile; fileRef = 72BAC3AB23E1E544008D741C /* ImageBufferIOSurfaceBackend.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -11187,6 +11188,7 @@
 		727AFED11A2EA6A0000442E8 /* EXTsRGB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EXTsRGB.cpp; sourceTree = "<group>"; };
 		727AFED21A2EA6A0000442E8 /* EXTsRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTsRGB.h; sourceTree = "<group>"; };
 		727AFED31A2EA6A0000442E8 /* EXTsRGB.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = EXTsRGB.idl; sourceTree = "<group>"; };
+		729661A2275960A500E7DF9B /* FilterEffectGeometry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterEffectGeometry.h; sourceTree = "<group>"; };
 		7299BC6423D686A600CC6883 /* AlphaPremultiplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AlphaPremultiplication.h; sourceTree = "<group>"; };
 		7299BC6623D686C600CC6883 /* RenderingMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderingMode.h; sourceTree = "<group>"; };
 		729D052E25313E2600422098 /* RenderingResourceIdentifier.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderingResourceIdentifier.h; sourceTree = "<group>"; };
@@ -26640,6 +26642,7 @@
 				08C925170FCC7C4A00480DEC /* FilterEffect.cpp */,
 				08C925180FCC7C4A00480DEC /* FilterEffect.h */,
 				72A13A9F274C5CC700E2A88E /* FilterEffectApplier.h */,
+				729661A2275960A500E7DF9B /* FilterEffectGeometry.h */,
 				7214B9B7274458FA003BE6DF /* FilterEffectVector.h */,
 				7262D757272A174100C56A09 /* FilterFunction.cpp */,
 				7262D756272A174100C56A09 /* FilterFunction.h */,
@@ -34184,6 +34187,7 @@
 				712BE4831FE865DD002031CC /* FillMode.h in Headers */,
 				845E72F80FD261EE00A87D79 /* Filter.h in Headers */,
 				08C9251A0FCC7C4A00480DEC /* FilterEffect.h in Headers */,
+				726CDE202759735000A445B2 /* FilterEffectGeometry.h in Headers */,
 				72B8B0352753438600F752AA /* FilterFunction.h in Headers */,
 				72B8B0362753441400F752AA /* FilterImage.h in Headers */,
 				49ECEB6E1499790D00CDD3A4 /* FilterOperation.h in Headers */,

Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.h (286465 => 286466)


--- trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -21,6 +21,7 @@
 
 #pragma once
 
+#include "FilterEffectGeometry.h"
 #include "FilterFunction.h"
 #include "FloatRect.h"
 #include "GraphicsTypes.h"
@@ -29,6 +30,7 @@
 
 namespace WebCore {
 
+class FilterEffect;
 class FilterImage;
 
 class Filter : public FilterFunction {
@@ -60,6 +62,8 @@
     FloatSize scaledByFilterScale(const FloatSize&) const;
     FloatRect scaledByFilterScale(const FloatRect&) const;
 
+    virtual std::optional<FilterEffectGeometry> effectGeometry(FilterEffect&) const { return std::nullopt; }
+
     FloatRect maxEffectRect(const FloatRect& primitiveSubregion) const;
     FloatRect clipToMaxEffectRect(const FloatRect& imageRect, const FloatRect& primitiveSubregion) const;
 

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (286465 => 286466)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp	2021-12-03 00:37:00 UTC (rev 286466)
@@ -24,10 +24,8 @@
 #include "config.h"
 #include "FilterEffect.h"
 
-#include "Color.h"
 #include "Filter.h"
 #include "FilterEffectApplier.h"
-#include "GeometryUtilities.h"
 #include "ImageBuffer.h"
 #include "Logging.h"
 #include <wtf/text/TextStream.h>
@@ -44,43 +42,42 @@
 
 FloatRect FilterEffect::determineFilterPrimitiveSubregion(const Filter& filter)
 {
-    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
-    FloatRect subregion;
-    if (unsigned numberOfInputEffects = inputEffects().size()) {
-        subregion = inputEffect(0)->determineFilterPrimitiveSubregion(filter);
-        for (unsigned i = 1; i < numberOfInputEffects; ++i) {
-            auto inputPrimitiveSubregion = inputEffect(i)->determineFilterPrimitiveSubregion(filter);
-            subregion.unite(inputPrimitiveSubregion);
+    // This function implements https://www.w3.org/TR/filter-effects-1/#FilterPrimitiveSubRegion.
+    FloatRect primitiveSubregion;
+
+    // If there is no input effects, take the effect boundaries as unite rect.
+    if (!m_inputEffects.isEmpty()) {
+        for (auto& effect : m_inputEffects) {
+            auto inputPrimitiveSubregion = effect->determineFilterPrimitiveSubregion(filter);
+            primitiveSubregion.unite(inputPrimitiveSubregion);
         }
     } else
-        subregion = filter.filterRegion();
+        primitiveSubregion = filter.filterRegion();
 
-    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
+    // Don't use the input's subregion for FETile.
     if (filterType() == FilterEffect::Type::FETile)
-        subregion = filter.filterRegion();
+        primitiveSubregion = filter.filterRegion();
+    
+    // Clip the primitive subregion to the effect geometry.
+    if (auto geometry = filter.effectGeometry(*this)) {
+        if (auto x = geometry->x())
+            primitiveSubregion.setX(*x);
+        if (auto y = geometry->y())
+            primitiveSubregion.setY(*y);
+        if (auto width = geometry->width())
+            primitiveSubregion.setWidth(*width);
+        if (auto height = geometry->height())
+            primitiveSubregion.setHeight(*height);
+    }
 
-    auto boundaries = effectBoundaries();
-    if (hasX())
-        subregion.setX(boundaries.x());
-    if (hasY())
-        subregion.setY(boundaries.y());
-    if (hasWidth())
-        subregion.setWidth(boundaries.width());
-    if (hasHeight())
-        subregion.setHeight(boundaries.height());
+    // Clip every filter effect to the filter region.
+    auto absoluteMaxEffectRect = filter.maxEffectRect(primitiveSubregion);
+    absoluteMaxEffectRect.scale(filter.filterScale());
 
-    setFilterPrimitiveSubregion(subregion);
+    setFilterPrimitiveSubregion(primitiveSubregion);
+    setMaxEffectRect(absoluteMaxEffectRect);
 
-    auto absoluteSubregion = subregion;
-    absoluteSubregion.scale(filter.filterScale());
-
-    // Clip every filter effect to the filter region.
-    auto absoluteScaledFilterRegion = filter.filterRegion();
-    absoluteScaledFilterRegion.scale(filter.filterScale());
-    absoluteSubregion.intersect(absoluteScaledFilterRegion);
-
-    setMaxEffectRect(absoluteSubregion);
-    return subregion;
+    return primitiveSubregion;
 }
 
 FilterEffect* FilterEffect::inputEffect(unsigned number) const
@@ -129,7 +126,6 @@
     LOG_WITH_STREAM(Filters, stream
         << "FilterEffect " << filterName() << " " << this << " apply():"
         << "\n  filterPrimitiveSubregion " << m_filterPrimitiveSubregion
-        << "\n  effectBoundaries " << m_effectBoundaries
         << "\n  absolutePaintRect " << absoluteImageRect
         << "\n  maxEffectRect " << m_maxEffectRect
         << "\n  filter scale " << filter.filterScale());

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (286465 => 286466)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -27,7 +27,6 @@
 #include "FilterFunction.h"
 #include "FilterImage.h"
 #include "FilterImageVector.h"
-#include "IntRect.h"
 #include <wtf/Vector.h>
 
 namespace WTF {
@@ -38,7 +37,6 @@
 
 class Filter;
 class FilterEffectApplier;
-class ImageBuffer;
 
 class FilterEffect : public FilterFunction {
 public:
@@ -71,26 +69,9 @@
     enum class RepresentationType { TestOutput, Debugging };
     virtual WTF::TextStream& externalRepresentation(WTF::TextStream&, RepresentationType = RepresentationType::TestOutput) const;
 
-    // The following functions are SVG specific and will move to RenderSVGResourceFilterPrimitive.
-    // See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
-    bool hasX() const { return m_hasX; }
-    void setHasX(bool value) { m_hasX = value; }
-
-    bool hasY() const { return m_hasY; }
-    void setHasY(bool value) { m_hasY = value; }
-
-    bool hasWidth() const { return m_hasWidth; }
-    void setHasWidth(bool value) { m_hasWidth = value; }
-
-    bool hasHeight() const { return m_hasHeight; }
-    void setHasHeight(bool value) { m_hasHeight = value; }
-
     FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
     void setFilterPrimitiveSubregion(const FloatRect& filterPrimitiveSubregion) { m_filterPrimitiveSubregion = filterPrimitiveSubregion; }
 
-    FloatRect effectBoundaries() const { return m_effectBoundaries; }
-    void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
-    
     virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
 
     const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
@@ -102,7 +83,7 @@
 
     virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
     void transformResultColorSpace(const DestinationColorSpace&);
-    
+
 protected:
     using FilterFunction::FilterFunction;
 
@@ -123,15 +104,6 @@
     // This is SVG specific and needs to move to RenderSVGResourceFilterPrimitive.
     FloatRect m_filterPrimitiveSubregion;
 
-    // x, y, width and height of the actual SVGFE*Element. Is needed to determine the subregion of the
-    // filter primitive on a later step.
-    FloatRect m_effectBoundaries;
-    
-    bool m_hasX { false };
-    bool m_hasY { false };
-    bool m_hasWidth { false };
-    bool m_hasHeight { false };
-
     DestinationColorSpace m_operatingColorSpace { DestinationColorSpace::SRGB() };
 };
 

Added: trunk/Source/WebCore/platform/graphics/filters/FilterEffectGeometry.h (0 => 286466)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffectGeometry.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffectGeometry.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -0,0 +1,88 @@
+/*
+ * 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. ``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
+ * 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 "FloatRect.h"
+#include <wtf/OptionSet.h>
+#include <wtf/Ref.h>
+
+namespace WebCore {
+
+class FilterEffect;
+
+class FilterEffectGeometry {
+public:
+    enum class Flags {
+        HasX      = 1 << 0,
+        HasY      = 1 << 1,
+        HasWidth  = 1 << 2,
+        HasHeight = 1 << 3
+    };
+
+    FilterEffectGeometry() = default;
+
+    FilterEffectGeometry(const FloatRect& boundaries, OptionSet<Flags> flags)
+        : m_boundaries(boundaries)
+        , m_flags(flags)
+    {
+    }
+
+    std::optional<float> x() const
+    {
+        if (m_flags.contains(Flags::HasX))
+            return m_boundaries.x();
+        return std::nullopt;
+    }
+
+    std::optional<float> y() const
+    {
+        if (m_flags.contains(Flags::HasY))
+            return m_boundaries.y();
+        return std::nullopt;
+    }
+
+    std::optional<float> width() const
+    {
+        if (m_flags.contains(Flags::HasWidth))
+            return m_boundaries.width();
+        return std::nullopt;
+    }
+
+    std::optional<float> height() const
+    {
+        if (m_flags.contains(Flags::HasHeight))
+            return m_boundaries.height();
+        return std::nullopt;
+    }
+
+private:
+    FloatRect m_boundaries;
+    OptionSet<Flags> m_flags;
+};
+
+using FilterEffectGeometryMap = HashMap<Ref<FilterEffect>, FilterEffectGeometry>;
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp (286465 => 286466)


--- trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp	2021-12-03 00:37:00 UTC (rev 286466)
@@ -94,22 +94,6 @@
     invalidate();
 }
 
-void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(FilterEffect* filterEffect) const
-{
-    ASSERT(filterEffect);
-    if (!filterEffect)
-        return;
-
-    if (hasAttribute(SVGNames::xAttr))
-        filterEffect->setHasX(true);
-    if (hasAttribute(SVGNames::yAttr))
-        filterEffect->setHasY(true);
-    if (hasAttribute(SVGNames::widthAttr))
-        filterEffect->setHasWidth(true);
-    if (hasAttribute(SVGNames::heightAttr))
-        filterEffect->setHasHeight(true);
-}
-
 RenderPtr<RenderElement> SVGFilterPrimitiveStandardAttributes::createElementRenderer(RenderStyle&& style, const RenderTreePosition&)
 {
     return createRenderer<RenderSVGResourceFilterPrimitive>(*this, WTFMove(style));

Modified: trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h (286465 => 286466)


--- trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -36,8 +36,6 @@
 class SVGFilterPrimitiveStandardAttributes : public SVGElement {
     WTF_MAKE_ISO_ALLOCATED(SVGFilterPrimitiveStandardAttributes);
 public:
-    void setStandardAttributes(FilterEffect*) const;
-
     virtual RefPtr<FilterEffect> build(SVGFilterBuilder&) const = 0;
     // Returns true, if the new value is different from the old one.
     virtual bool setFilterEffectAttribute(FilterEffect*, const QualifiedName&);

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp (286465 => 286466)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp	2021-12-03 00:37:00 UTC (rev 286466)
@@ -51,8 +51,7 @@
     builder.setTargetBoundingBox(targetBoundingBox);
     builder.setPrimitiveUnits(filterElement.primitiveUnits());
 
-    auto lastEffect = builder.buildFilterEffects(filterElement);
-    if (!lastEffect)
+    if (!builder.buildFilterEffects(filterElement))
         return nullptr;
 
     FilterEffectVector _expression_;
@@ -61,7 +60,9 @@
 
     ASSERT(!_expression_.isEmpty());
     filter->setExpression(WTFMove(_expression_));
-    
+
+    filter->setEffectGeometryMap(builder.takeEffectGeometryMap());
+
 #if USE(CORE_IMAGE)
     if (!filter->supportsCoreImageRendering())
         filter->setRenderingMode(RenderingMode::Unaccelerated);
@@ -98,6 +99,14 @@
 }
 #endif
 
+std::optional<FilterEffectGeometry> SVGFilter::effectGeometry(FilterEffect& effect) const
+{
+    auto it = m_effectGeometryMap.find(effect);
+    if (it != m_effectGeometryMap.end())
+        return it->value;
+    return std::nullopt;
+}
+
 bool SVGFilter::apply(const Filter& filter)
 {
     setSourceImage({ filter.sourceImage() });

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h (286465 => 286466)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -42,19 +42,22 @@
 
     FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
 
-    void setExpression(FilterEffectVector&& _expression_) { m_expression = WTFMove(_expression_); }
     RefPtr<FilterEffect> lastEffect() const { return !m_expression.isEmpty() ? m_expression.last() : nullptr; }
 
-    FloatSize resolvedSize(const FloatSize&) const final;
-
     RefPtr<FilterImage> apply() override;
 
 private:
     SVGFilter(RenderingMode, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, ClipOperation, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits);
 
+    // FIXME: Merge the effectBoundaries in the _expression_ node.
+    void setExpression(FilterEffectVector&& _expression_) { m_expression = WTFMove(_expression_); }
+    void setEffectGeometryMap(FilterEffectGeometryMap&& effectGeometryMap) { m_effectGeometryMap = WTFMove(effectGeometryMap); }
+
 #if USE(CORE_IMAGE)
     bool supportsCoreImageRendering() const override;
 #endif
+    std::optional<FilterEffectGeometry> effectGeometry(FilterEffect&) const override;
+    FloatSize resolvedSize(const FloatSize&) const final;
 
     bool apply(const Filter&) override;
     IntOutsets outsets() const override;
@@ -63,7 +66,9 @@
     FloatRect m_targetBoundingBox;
     SVGUnitTypes::SVGUnitType m_primitiveUnits;
 
+    // FIXME: Make m_expression a Vector of the FilterEffect and the effectBoundaries.
     FilterEffectVector m_expression;
+    FilterEffectGeometryMap m_effectGeometryMap;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp (286465 => 286466)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp	2021-12-03 00:37:00 UTC (rev 286466)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Dirk Schulze <k...@webkit.org>
+ * Copyright (C) 2021 Apple Inc.  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
@@ -40,6 +41,25 @@
     addBuiltinEffects();
 }
 
+static OptionSet<FilterEffectGeometry::Flags> boundarySetFlagsForElement(SVGElement& element)
+{
+    OptionSet<FilterEffectGeometry::Flags> flags;
+
+    if (element.hasAttribute(SVGNames::xAttr))
+        flags.add(FilterEffectGeometry::Flags::HasX);
+
+    if (element.hasAttribute(SVGNames::yAttr))
+        flags.add(FilterEffectGeometry::Flags::HasY);
+
+    if (element.hasAttribute(SVGNames::widthAttr))
+        flags.add(FilterEffectGeometry::Flags::HasWidth);
+
+    if (element.hasAttribute(SVGNames::heightAttr))
+        flags.add(FilterEffectGeometry::Flags::HasHeight);
+
+    return flags;
+}
+
 #if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
 static ColorInterpolation colorInterpolationForElement(SVGElement& element)
 {
@@ -85,18 +105,19 @@
 
     for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
         effect = effectElement.build(*this);
-        if (!effect) {
-            clearEffects();
-            return nullptr;
+        if (!effect)
+            break;
+
+        if (auto flags = boundarySetFlagsForElement(effectElement)) {
+            auto effectBoundaries = SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&effectElement, m_primitiveUnits, m_targetBoundingBox);
+            m_effectGeometryMap.add(*effect, FilterEffectGeometry(effectBoundaries, flags));
         }
 
-        effectElement.setStandardAttributes(effect.get());
-        effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&effectElement, m_primitiveUnits, m_targetBoundingBox));
-
 #if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
         if (colorInterpolationForElement(effectElement) == ColorInterpolation::LinearRGB)
             effect->setOperatingColorSpace(DestinationColorSpace::LinearSRGB());
 #endif
+
         if (auto renderer = effectElement.renderer())
             appendEffectToEffectReferences(effect.copyRef(), renderer);
 
@@ -103,8 +124,10 @@
         add(effectElement.result(), effect);
     }
 
-    if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects)
+    if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects) {
+        clearEffects();
         return nullptr;
+    }
 
     return effect;
 }

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h (286465 => 286466)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2021-12-03 00:35:11 UTC (rev 286465)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2021-12-03 00:37:00 UTC (rev 286466)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008 Alex Mathews <possessedpenguin...@gmail.com>
  * Copyright (C) 2009 Dirk Schulze <k...@webkit.org>
+ * Copyright (C) 2021 Apple Inc.  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
@@ -69,6 +70,8 @@
     RefPtr<FilterEffect> buildFilterEffects(SVGFilterElement&);
     bool buildExpression(FilterEffectVector& _expression_) const;
 
+    FilterEffectGeometryMap takeEffectGeometryMap() { return WTFMove(m_effectGeometryMap); }
+
 private:
     inline void addBuiltinEffects()
     {
@@ -84,8 +87,10 @@
     HashMap<RenderObject*, FilterEffect*> m_effectRenderer;
 
     RefPtr<FilterEffect> m_lastEffect;
+
     FloatRect m_targetBoundingBox;
     SVGUnitTypes::SVGUnitType m_primitiveUnits { SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE };
+    FilterEffectGeometryMap m_effectGeometryMap;
 };
     
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to