Diff
Modified: trunk/Source/WebCore/Sources.txt (295516 => 295517)
--- trunk/Source/WebCore/Sources.txt 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/Sources.txt 2022-06-14 06:33:01 UTC (rev 295517)
@@ -2760,7 +2760,6 @@
svg/graphics/SVGImageCache.cpp
svg/graphics/SVGImageForContainer.cpp
svg/graphics/filters/SVGFilter.cpp
-svg/graphics/filters/SVGFilterBuilder.cpp
svg/properties/SVGAnimatedProperty.cpp
svg/properties/SVGAnimationAdditiveValueFunctionImpl.cpp
svg/properties/SVGAttributeAnimator.cpp
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (295516 => 295517)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2022-06-14 06:33:01 UTC (rev 295517)
@@ -239,7 +239,6 @@
081668D4125603BF006F25DE /* SVGTextChunkBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 081668D2125603BF006F25DE /* SVGTextChunkBuilder.h */; };
081668DA125603D5006F25DE /* SVGTextLayoutEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 081668D8125603D5006F25DE /* SVGTextLayoutEngine.h */; };
081AA8DA1111237E002AB06E /* SVGElementRareData.h in Headers */ = {isa = PBXBuildFile; fileRef = 081AA8D91111237E002AB06E /* SVGElementRareData.h */; };
- 081EBF3B0FD34F4100DA7559 /* SVGFilterBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 081EBF390FD34F4100DA7559 /* SVGFilterBuilder.h */; };
083DAEA70F01A7FB00342754 /* RenderTextControlMultiLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 083DAEA30F01A7FB00342754 /* RenderTextControlMultiLine.h */; };
083DAEA90F01A7FB00342754 /* RenderTextControlSingleLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 083DAEA50F01A7FB00342754 /* RenderTextControlSingleLine.h */; };
0844B01D1255B4E600B9CDD0 /* SVGBoundingBoxComputation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0844B01D1255E4E600B9CDD0 /* SVGBoundingBoxComputation.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -6252,8 +6251,6 @@
081668D7125603D5006F25DE /* SVGTextLayoutEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGTextLayoutEngine.cpp; sourceTree = "<group>"; };
081668D8125603D5006F25DE /* SVGTextLayoutEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGTextLayoutEngine.h; sourceTree = "<group>"; };
081AA8D91111237E002AB06E /* SVGElementRareData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGElementRareData.h; sourceTree = "<group>"; };
- 081EBF380FD34F4100DA7559 /* SVGFilterBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGFilterBuilder.cpp; sourceTree = "<group>"; };
- 081EBF390FD34F4100DA7559 /* SVGFilterBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGFilterBuilder.h; sourceTree = "<group>"; };
0834B00C1244E4E600B9CDD0 /* SVGBoundingBoxComputation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGBoundingBoxComputation.cpp; sourceTree = "<group>"; };
0834B00C1244E5A610B8AFD1 /* SVGContainerLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGContainerLayout.cpp; sourceTree = "<group>"; };
083DAEA20F01A7FB00342754 /* RenderTextControlMultiLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextControlMultiLine.cpp; sourceTree = "<group>"; };
@@ -29069,8 +29066,6 @@
children = (
845E72F90FD2623900A87D79 /* SVGFilter.cpp */,
845E72FA0FD2623900A87D79 /* SVGFilter.h */,
- 081EBF380FD34F4100DA7559 /* SVGFilterBuilder.cpp */,
- 081EBF390FD34F4100DA7559 /* SVGFilterBuilder.h */,
726CDE25275B489700A445B2 /* SVGFilterExpression.h */,
72F7A08027F171BF0008EEE8 /* SVGFilterGraph.h */,
);
@@ -37940,7 +37935,6 @@
B2227A060D00BF220071B782 /* SVGFETileElement.h in Headers */,
B2227A090D00BF220071B782 /* SVGFETurbulenceElement.h in Headers */,
845E72FC0FD2623900A87D79 /* SVGFilter.h in Headers */,
- 081EBF3B0FD34F4100DA7559 /* SVGFilterBuilder.h in Headers */,
B2227A0C0D00BF220071B782 /* SVGFilterElement.h in Headers */,
72A5D192275E8FFE0065833E /* SVGFilterExpression.h in Headers */,
B2227A0F0D00BF220071B782 /* SVGFilterPrimitiveStandardAttributes.h in Headers */,
Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (295516 => 295517)
--- trunk/Source/WebCore/rendering/CSSFilter.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -36,7 +36,6 @@
#include "ReferencedSVGResources.h"
#include "RenderElement.h"
#include "SVGFilter.h"
-#include "SVGFilterBuilder.h"
#include "SVGFilterElement.h"
#include "SourceGraphic.h"
@@ -253,7 +252,7 @@
if (!filterElement)
return { };
- return SVGFilterBuilder::calculateFilterOutsets(*filterElement, targetBoundingBox);
+ return SVGFilter::calculateOutsets(*filterElement, targetBoundingBox);
}
static RefPtr<SVGFilter> createReferenceFilter(CSSFilter& filter, const ReferenceFilterOperation& filterOperation, RenderElement& renderer, const FloatRect& targetBoundingBox, const GraphicsContext& destinationContext)
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (295516 => 295517)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -90,10 +90,9 @@
auto addResult = m_rendererFilterDataMap.set(&renderer, makeUnique<FilterData>());
auto filterData = addResult.iterator->value.get();
- FloatRect targetBoundingBox = renderer.objectBoundingBox();
-
- filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(&filterElement(), filterElement().filterUnits(), targetBoundingBox);
- if (filterData->boundaries.isEmpty()) {
+ auto targetBoundingBox = renderer.objectBoundingBox();
+ auto filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement>(&filterElement(), filterElement().filterUnits(), targetBoundingBox);
+ if (filterRegion.isEmpty()) {
m_rendererFilterDataMap.remove(&renderer);
return false;
}
@@ -109,17 +108,17 @@
FloatSize filterScale(absoluteTransform.xScale(), absoluteTransform.yScale());
// Determine absolute boundaries of the filter and the drawing region.
- filterData->drawingRegion = renderer.strokeBoundingBox();
- filterData->drawingRegion.intersect(filterData->boundaries);
+ filterData->sourceImageRect = renderer.strokeBoundingBox();
+ filterData->sourceImageRect.intersect(filterRegion);
// Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
- ImageBuffer::sizeNeedsClamping(filterData->drawingRegion.size(), filterScale);
+ ImageBuffer::sizeNeedsClamping(filterData->sourceImageRect.size(), filterScale);
// Set the rendering mode from the page's settings.
auto renderingMode = renderer.page().acceleratedFiltersEnabled() ? RenderingMode::Accelerated : RenderingMode::Unaccelerated;
// Create the SVGFilter object.
- filterData->filter = SVGFilter::create(filterElement(), renderingMode, filterScale, Filter::ClipOperation::Intersect, filterData->boundaries, targetBoundingBox, *context);
+ filterData->filter = SVGFilter::create(filterElement(), renderingMode, filterScale, Filter::ClipOperation::Intersect, filterRegion, targetBoundingBox, *context);
if (!filterData->filter) {
m_rendererFilterDataMap.remove(&renderer);
return false;
@@ -128,9 +127,9 @@
if (filterData->filter->clampFilterRegionIfNeeded())
filterScale = filterData->filter->filterScale();
- // If the drawingRegion is empty, we have something like <g filter=".."/>.
+ // If the sourceImageRect is empty, we have something like <g filter=".."/>.
// Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
- if (filterData->drawingRegion.isEmpty()) {
+ if (filterData->sourceImageRect.isEmpty()) {
ASSERT(m_rendererFilterDataMap.contains(&renderer));
filterData->savedContext = context;
return false;
@@ -142,20 +141,16 @@
auto colorSpace = DestinationColorSpace::SRGB();
#endif
- auto sourceGraphic = context->createScaledImageBuffer(filterData->drawingRegion, filterScale, colorSpace, filterData->filter->renderingMode());
- if (!sourceGraphic) {
+ filterData->sourceImage = context->createScaledImageBuffer(filterData->sourceImageRect, filterScale, colorSpace, filterData->filter->renderingMode());
+ if (!filterData->sourceImage) {
ASSERT(m_rendererFilterDataMap.contains(&renderer));
filterData->savedContext = context;
return false;
}
- auto& sourceGraphicContext = sourceGraphic->context();
-
- filterData->sourceGraphicBuffer = WTFMove(sourceGraphic);
filterData->savedContext = context;
+ context = &filterData->sourceImage->context();
- context = &sourceGraphicContext;
-
ASSERT(m_rendererFilterDataMap.contains(&renderer));
return true;
}
@@ -201,9 +196,9 @@
break;
}
- if (!filterData.boundaries.isEmpty()) {
+ if (filterData.filter) {
filterData.state = FilterData::Built;
- context->drawFilteredImageBuffer(filterData.sourceGraphicBuffer.get(), filterData.drawingRegion, *filterData.filter, filterData.results);
+ context->drawFilteredImageBuffer(filterData.sourceImage.get(), filterData.sourceImageRect, *filterData.filter, filterData.results);
}
LOG_WITH_STREAM(Filters, stream << "RenderSVGResourceFilter " << this << " postApplyResource done\n");
@@ -240,7 +235,7 @@
FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
{
FilterData* filterData = m_rendererFilterDataMap.get(object);
- return filterData ? filterData->drawingRegion : FloatRect();
+ return filterData ? filterData->sourceImageRect : FloatRect();
}
TextStream& operator<<(TextStream& ts, FilterData::FilterDataState state)
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h (295516 => 295517)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2022-06-14 06:33:01 UTC (rev 295517)
@@ -27,7 +27,6 @@
#include "ImageBuffer.h"
#include "RenderSVGResourceContainer.h"
#include "SVGFilter.h"
-#include "SVGFilterBuilder.h"
#include "SVGUnitTypes.h"
#include <wtf/IsoMalloc.h>
#include <wtf/RefPtr.h>
@@ -34,6 +33,7 @@
namespace WebCore {
+class GraphicsContext;
class SVGFilterElement;
struct FilterData {
@@ -45,17 +45,15 @@
FilterData() = default;
RefPtr<SVGFilter> filter;
- RefPtr<ImageBuffer> sourceGraphicBuffer;
+ FilterResults results;
+
+ RefPtr<ImageBuffer> sourceImage;
+ FloatRect sourceImageRect;
+
GraphicsContext* savedContext { nullptr };
- FloatRect boundaries;
- FloatRect drawingRegion;
- FloatSize scale;
FilterDataState state { PaintingSource };
- FilterResults results;
};
-class GraphicsContext;
-
class RenderSVGResourceFilter final : public RenderSVGResourceContainer {
WTF_MAKE_ISO_ALLOCATED(RenderSVGResourceFilter);
public:
Modified: trunk/Source/WebCore/svg/SVGElement.cpp (295516 => 295517)
--- trunk/Source/WebCore/svg/SVGElement.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/SVGElement.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -26,6 +26,8 @@
#include "config.h"
#include "SVGElement.h"
+#include "CSSComputedStyleDeclaration.h"
+#include "CSSPrimitiveValueMappings.h"
#include "CSSPropertyParser.h"
#include "Document.h"
#include "ElementChildIterator.h"
@@ -712,6 +714,20 @@
return m_svgRareData->overrideComputedStyle(*this, parentStyle);
}
+ColorInterpolation SVGElement::colorInterpolation() const
+{
+ if (auto renderer = this->renderer())
+ return renderer->style().svgStyle().colorInterpolationFilters();
+
+ // Try to determine the property value from the computed style.
+ if (auto value = ComputedStyleExtractor(const_cast<SVGElement*>(this)).propertyValue(CSSPropertyColorInterpolationFilters, DoNotUpdateLayout)) {
+ if (is<CSSPrimitiveValue>(value))
+ return downcast<CSSPrimitiveValue>(*value);
+ }
+
+ return ColorInterpolation::Auto;
+}
+
QualifiedName SVGElement::animatableAttributeForName(const AtomString& localName)
{
static NeverDestroyed animatableAttributes = [] {
Modified: trunk/Source/WebCore/svg/SVGElement.h (295516 => 295517)
--- trunk/Source/WebCore/svg/SVGElement.h 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/SVGElement.h 2022-06-14 06:33:01 UTC (rev 295517)
@@ -27,6 +27,7 @@
#include "SVGNames.h"
#include "SVGParsingError.h"
#include "SVGPropertyOwnerRegistry.h"
+#include "SVGRenderStyleDefs.h"
#include "StyledElement.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
@@ -149,6 +150,8 @@
void animatorWillBeDeleted(const QualifiedName&);
const RenderStyle* computedStyle(PseudoId = PseudoId::None) final;
+
+ ColorInterpolation colorInterpolation() const;
// These are needed for the RenderTree, animation and DOM.
AtomString className() const { return AtomString { m_className->currentValue() }; }
Modified: trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp (295516 => 295517)
--- trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -66,6 +66,22 @@
SVGElement::parseAttribute(name, value);
}
+OptionSet<FilterEffectGeometry::Flags> SVGFilterPrimitiveStandardAttributes::effectGeometryFlags() const
+{
+ OptionSet<FilterEffectGeometry::Flags> flags;
+
+ if (hasAttribute(SVGNames::xAttr))
+ flags.add(FilterEffectGeometry::Flags::HasX);
+ if (hasAttribute(SVGNames::yAttr))
+ flags.add(FilterEffectGeometry::Flags::HasY);
+ if (hasAttribute(SVGNames::widthAttr))
+ flags.add(FilterEffectGeometry::Flags::HasWidth);
+ if (hasAttribute(SVGNames::heightAttr))
+ flags.add(FilterEffectGeometry::Flags::HasHeight);
+
+ return flags;
+}
+
RefPtr<FilterEffect> SVGFilterPrimitiveStandardAttributes::filterEffect(const FilterEffectVector& inputs, const GraphicsContext& destinationContext)
{
if (!m_effect)
Modified: trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h (295516 => 295517)
--- trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h 2022-06-14 06:33:01 UTC (rev 295517)
@@ -21,6 +21,7 @@
#pragma once
+#include "FilterEffectGeometry.h"
#include "RenderSVGResourceFilter.h"
#include "RenderSVGResourceFilterPrimitive.h"
#include "SVGElement.h"
@@ -50,13 +51,15 @@
SVGAnimatedLength& heightAnimated() { return m_height; }
SVGAnimatedString& resultAnimated() { return m_result; }
- void primitiveAttributeChanged(const QualifiedName&);
- void markFilterEffectForRebuild();
+ OptionSet<FilterEffectGeometry::Flags> effectGeometryFlags() const;
virtual Vector<AtomString> filterEffectInputsNames() const { return { }; }
virtual IntOutsets outsets(const FloatRect&, SVGUnitTypes::SVGUnitType) const { return { }; }
RefPtr<FilterEffect> filterEffect(const FilterEffectVector&, const GraphicsContext& destinationContext);
+ void primitiveAttributeChanged(const QualifiedName&);
+ void markFilterEffectForRebuild();
+
static void invalidateFilterPrimitiveParent(SVGElement*);
protected:
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp (295516 => 295517)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -23,19 +23,24 @@
#include "config.h"
#include "SVGFilter.h"
+#include "ElementIterator.h"
#include "FilterResults.h"
#include "GeometryUtilities.h"
-#include "SVGFilterBuilder.h"
#include "SVGFilterElement.h"
+#include "SVGFilterGraph.h"
+#include "SVGFilterPrimitiveStandardAttributes.h"
#include "SourceGraphic.h"
namespace WebCore {
+static constexpr unsigned maxTotalNumberFilterEffects = 100;
+static constexpr unsigned maxCountChildNodes = 200;
+
RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, RenderingMode renderingMode, const FloatSize& filterScale, ClipOperation clipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, const GraphicsContext& destinationContext)
{
auto filter = adoptRef(*new SVGFilter(renderingMode, filterScale, clipOperation, filterRegion, targetBoundingBox, filterElement.primitiveUnits()));
- auto _expression_ = SVGFilterBuilder::buildFilterExpression(filterElement, filter, destinationContext);
+ auto _expression_ = buildExpression(filterElement, filter, destinationContext);
if (!_expression_)
return nullptr;
@@ -68,6 +73,100 @@
{
}
+static std::optional<std::tuple<SVGFilterEffectsGraph, FilterEffectGeometryMap>> buildFilterEffectsGraph(SVGFilterElement& filterElement, const SVGFilter& filter, const GraphicsContext& destinationContext)
+{
+ if (filterElement.countChildNodes() > maxCountChildNodes)
+ return std::nullopt;
+
+ SVGFilterEffectsGraph graph(SourceGraphic::create(), SourceAlpha::create());
+ FilterEffectGeometryMap effectGeometryMap;
+
+ for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
+ auto inputs = graph.getNamedNodes(effectElement.filterEffectInputsNames());
+ if (!inputs)
+ return std::nullopt;
+
+ auto effect = effectElement.filterEffect(*inputs, destinationContext);
+ if (!effect)
+ return std::nullopt;
+
+ if (auto flags = effectElement.effectGeometryFlags()) {
+ auto effectBoundaries = SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&effectElement, filter.primitiveUnits(), filter.targetBoundingBox());
+ effectGeometryMap.add(*effect, FilterEffectGeometry(effectBoundaries, flags));
+ }
+
+#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
+ if (effectElement.colorInterpolation() == ColorInterpolation::LinearRGB)
+ effect->setOperatingColorSpace(DestinationColorSpace::LinearSRGB());
+#endif
+
+ graph.addNamedNode(AtomString { effectElement.result() }, { *effect });
+ graph.setNodeInputs(*effect, WTFMove(*inputs));
+ }
+
+ return { { WTFMove(graph), WTFMove(effectGeometryMap) } };
+}
+
+std::optional<SVGFilterExpression> SVGFilter::buildExpression(SVGFilterElement& filterElement, const SVGFilter& filter, const GraphicsContext& destinationContext)
+{
+ auto result = buildFilterEffectsGraph(filterElement, filter, destinationContext);
+ if (!result)
+ return std::nullopt;
+
+ auto& graph = std::get<SVGFilterEffectsGraph>(*result);
+ auto& effectGeometryMap = std::get<FilterEffectGeometryMap>(*result);
+
+ auto effectGeometry = [&](FilterEffect& effect) -> std::optional<FilterEffectGeometry> {
+ auto it = effectGeometryMap.find(effect);
+ if (it != effectGeometryMap.end())
+ return it->value;
+ return std::nullopt;
+ };
+
+ SVGFilterExpression _expression_;
+ bool success = graph.visit([&](FilterEffect& effect, unsigned level) {
+ _expression_.append({ effect, effectGeometry(effect), level });
+ });
+
+ if (!success || _expression_.size() > maxTotalNumberFilterEffects)
+ return std::nullopt;
+
+ _expression_.reverse();
+ _expression_.shrinkToFit();
+ return _expression_;
+}
+
+static std::optional<SVGFilterPrimitivesGraph> buildFilterPrimitivesGraph(SVGFilterElement& filterElement)
+{
+ if (filterElement.countChildNodes() > maxCountChildNodes)
+ return std::nullopt;
+
+ SVGFilterPrimitivesGraph graph;
+
+ for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
+ // We should not be strict about not finding the input primitives here because SourceGraphic and SourceAlpha do not have primitives.
+ auto inputs = graph.getNamedNodes(effectElement.filterEffectInputsNames()).value_or(SVGFilterPrimitivesGraph::NodeVector());
+ graph.addNamedNode(AtomString { effectElement.result() }, { effectElement });
+ graph.setNodeInputs(effectElement, WTFMove(inputs));
+ }
+
+ return graph;
+}
+
+IntOutsets SVGFilter::calculateOutsets(SVGFilterElement& filterElement, const FloatRect& targetBoundingBox)
+{
+ auto graph = buildFilterPrimitivesGraph(filterElement);
+ if (!graph)
+ return { };
+
+ IntOutsets outsets;
+ bool result = graph->visit([&](SVGFilterPrimitiveStandardAttributes& primitive, unsigned) {
+ outsets += primitive.outsets(targetBoundingBox, filterElement.primitiveUnits());
+ });
+
+ return result ? outsets : IntOutsets();
+}
+
FloatSize SVGFilter::calculateResolvedSize(const FloatSize& size, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits)
{
return primitiveUnits == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX ? size * targetBoundingBox.size() : size;
Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h (295516 => 295517)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h 2022-06-14 06:33:01 UTC (rev 295517)
@@ -39,6 +39,8 @@
static RefPtr<SVGFilter> create(SVGFilterElement&, RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, const GraphicsContext& destinationContext);
WEBCORE_EXPORT static RefPtr<SVGFilter> create(const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits, SVGFilterExpression&&);
+ static IntOutsets calculateOutsets(SVGFilterElement&, const FloatRect& targetBoundingBox);
+
FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
SVGUnitTypes::SVGUnitType primitiveUnits() const { return m_primitiveUnits; }
@@ -56,6 +58,7 @@
SVGFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits);
SVGFilter(const FloatRect& targetBoundingBox, SVGUnitTypes::SVGUnitType primitiveUnits, SVGFilterExpression&&);
+ static std::optional<SVGFilterExpression> buildExpression(SVGFilterElement&, const SVGFilter&, const GraphicsContext& destinationContext);
void setExpression(SVGFilterExpression&& _expression_) { m_expression = WTFMove(_expression_); }
FloatSize resolvedSize(const FloatSize&) const final;
Deleted: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp (295516 => 295517)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp 2022-06-14 06:33:01 UTC (rev 295517)
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2009 Dirk Schulze <[email protected]>
- * Copyright (C) 2021-2022 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "SVGFilterBuilder.h"
-
-#include "ElementIterator.h"
-#include "SVGFilterElement.h"
-#include "SVGFilterGraph.h"
-#include "SVGFilterPrimitiveStandardAttributes.h"
-
-#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
-#include "CSSComputedStyleDeclaration.h"
-#include "CSSPrimitiveValueMappings.h"
-#endif
-
-namespace WebCore {
-
-static constexpr unsigned maxTotalNumberFilterEffects = 100;
-static constexpr unsigned maxCountChildNodes = 200;
-
-static OptionSet<FilterEffectGeometry::Flags> effectGeometryFlagsForElement(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)
-{
- if (auto renderer = element.renderer())
- return renderer->style().svgStyle().colorInterpolationFilters();
-
- // Try to determine the property value from the computed style.
- if (auto value = ComputedStyleExtractor(&element).propertyValue(CSSPropertyColorInterpolationFilters, DoNotUpdateLayout)) {
- if (is<CSSPrimitiveValue>(value))
- return downcast<CSSPrimitiveValue>(*value);
- }
-
- return ColorInterpolation::Auto;
-}
-#endif
-
-std::optional<SVGFilterExpression> SVGFilterBuilder::buildFilterExpression(SVGFilterElement& filterElement, const SVGFilter& filter, const GraphicsContext& destinationContext)
-{
- if (filterElement.countChildNodes() > maxCountChildNodes)
- return std::nullopt;
-
- SVGFilterEffectsGraph graph(SourceGraphic::create(), SourceAlpha::create());
- FilterEffectGeometryMap effectGeometryMap;
-
- for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
- auto inputs = graph.getNamedNodes(effectElement.filterEffectInputsNames());
- if (!inputs)
- return std::nullopt;
-
- auto effect = effectElement.filterEffect(*inputs, destinationContext);
- if (!effect)
- return std::nullopt;
-
- if (auto flags = effectGeometryFlagsForElement(effectElement)) {
- auto effectBoundaries = SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&effectElement, filter.primitiveUnits(), filter.targetBoundingBox());
- effectGeometryMap.add(*effect, FilterEffectGeometry(effectBoundaries, flags));
- }
-
-#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
- if (colorInterpolationForElement(effectElement) == ColorInterpolation::LinearRGB)
- effect->setOperatingColorSpace(DestinationColorSpace::LinearSRGB());
-#endif
-
- graph.addNamedNode(AtomString { effectElement.result() }, { *effect });
- graph.setNodeInputs(*effect, WTFMove(*inputs));
- }
-
- auto effectGeometry = [&](FilterEffect& effect) -> std::optional<FilterEffectGeometry> {
- auto it = effectGeometryMap.find(effect);
- if (it != effectGeometryMap.end())
- return it->value;
- return std::nullopt;
- };
-
- SVGFilterExpression _expression_;
- bool result = graph.visit([&](FilterEffect& effect, unsigned level) {
- _expression_.append({ effect, effectGeometry(effect), level });
- });
-
- if (!result || _expression_.size() > maxTotalNumberFilterEffects)
- return std::nullopt;
-
- _expression_.reverse();
- _expression_.shrinkToFit();
- return _expression_;
-}
-
-static std::optional<SVGFilterPrimitivesGraph> buildFilterPrimitivesGraph(SVGFilterElement& filterElement)
-{
- if (filterElement.countChildNodes() > maxCountChildNodes)
- return std::nullopt;
-
- SVGFilterPrimitivesGraph graph;
-
- for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
- // We should not be strict about not finding the input primitives here because SourceGraphic and SourceAlpha do not have primitives.
- auto inputs = graph.getNamedNodes(effectElement.filterEffectInputsNames()).value_or(SVGFilterPrimitivesGraph::NodeVector());
- graph.addNamedNode(AtomString { effectElement.result() }, { effectElement });
- graph.setNodeInputs(effectElement, WTFMove(inputs));
- }
-
- return graph;
-}
-
-IntOutsets SVGFilterBuilder::calculateFilterOutsets(SVGFilterElement& filterElement, const FloatRect& targetBoundingBox)
-{
- auto graph = buildFilterPrimitivesGraph(filterElement);
- if (!graph)
- return { };
-
- IntOutsets outsets;
- bool result = graph->visit([&](SVGFilterPrimitiveStandardAttributes& primitive, unsigned) {
- outsets += primitive.outsets(targetBoundingBox, filterElement.primitiveUnits());
- });
-
- return result ? outsets : IntOutsets();
-}
-
-} // namespace WebCore
Deleted: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h (295516 => 295517)
--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h 2022-06-14 06:30:59 UTC (rev 295516)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h 2022-06-14 06:33:01 UTC (rev 295517)
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2008 Alex Mathews <[email protected]>
- * Copyright (C) 2009 Dirk Schulze <[email protected]>
- * Copyright (C) 2021-2022 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#pragma once
-
-#include "SVGFilterExpression.h"
-#include "SVGUnitTypes.h"
-
-namespace WebCore {
-
-class FilterEffect;
-class GraphicsContext;
-class RenderObject;
-class SVGFilter;
-class SVGFilterElement;
-
-class SVGFilterBuilder {
-public:
- static std::optional<SVGFilterExpression> buildFilterExpression(SVGFilterElement&, const SVGFilter&, const GraphicsContext& destinationContext);
- static IntOutsets calculateFilterOutsets(SVGFilterElement&, const FloatRect& targetBoundingBox);
-};
-
-} // namespace WebCore