<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[286765] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/286765">286765</a></dd>
<dt>Author</dt> <dd>said@apple.com</dd>
<dt>Date</dt> <dd>2021-12-08 22:39:26 -0800 (Wed, 08 Dec 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
https://bugs.webkit.org/show_bug.cgi?id=233973
rdar://86248999

Reviewed by Cameron McCormack.

This is a step towards removing the dependency on the input effects. This
step is required to make encoding/decoding the FilterEffect just be
sending or receiving its primitive data.

In this patch:

-- The sourceImage and sourceImageRect arguments to Filter::apply() are
   used to create a FilterImage. This will be the input to the SourceGraphic.

-- The members m_sourceImage and m_sourceImageRect of Filter are removed.

-- CSSFilter::apply() loops through its functions and uses the result
   of every function as the input to the next one. The initial input is
   the sourceImage. And the result of the last function is the returned
   FilterImage.

-- SVGFilter::apply() loops through its expression. It uses a stack of
   FilterImageVector to keep track of the inputs while applying each
   FilterEffect. Every FilterEffect is asked to takeInputs() from this
   stack. The result of applying the FilterEffect is pushed on this stack.
   The stack should have a single FilterImage when finishing the loop.
   This item is the result of applying the Filter.

-- FilterEffect::transformInputsColorSpace() was added to transform the
   input FilterImageVector to the operating color space of FilterEffect.
   It is overridden by FEDisplacementMap which does not transform the
   color space of the first input FilterImage.

-- FilterEffect::correctPremultipliedInputs() was added to correct the
   premultiplied pixels of the inputs FilterImageVector. We do not need
   to do this correction if the FilterEffect we apply is arithmetic
   composite filter. Otherwise we need to correct the FilterImage of any
   arithmetic composite filter in the FilterImageVector.

-- No need for totalNumberFilterEffects(). This count is the size of the
   SVGFilter expression.

* platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
(WebCore::SourceGraphicCoreImageApplier::apply const):
* platform/graphics/filters/FEBlend.h:
* platform/graphics/filters/FEComposite.h:
* platform/graphics/filters/FEDisplacementMap.cpp:
(WebCore::FEDisplacementMap::calculateImageRect const):
(WebCore::FEDisplacementMap::transformInputsColorSpace const):
(WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
* platform/graphics/filters/FEDisplacementMap.h:
* platform/graphics/filters/FEFlood.h:
* platform/graphics/filters/FEMerge.h:
* platform/graphics/filters/FETurbulence.h:
* platform/graphics/filters/Filter.cpp:
(WebCore::Filter::apply):
* platform/graphics/filters/Filter.h:
(WebCore::Filter::sourceImageRect const): Deleted.
(WebCore::Filter::setSourceImageRect): Deleted.
(WebCore::Filter::sourceImage const): Deleted.
(WebCore::Filter::setSourceImage): Deleted.
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::takeImageInputs const):
(WebCore::FilterEffect::calculateImageRect const):
(WebCore::FilterEffect::transformInputsColorSpace const):
(WebCore::FilterEffect::correctPremultipliedInputs const):
(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::inputEffect const):
(WebCore::FilterEffect::inputFilterImages const): Deleted.
(WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::filterImage const):
(WebCore::FilterEffect::numberOfEffectInputs const):
(WebCore::FilterEffect::numberOfImageInputs const):
(WebCore::FilterEffect::resultIsValidPremultiplied const):
(WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
(WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
(WebCore::FilterEffect::transformResultColorSpace): Deleted.
* platform/graphics/filters/FilterFunction.h:
(WebCore::FilterFunction::apply):
* platform/graphics/filters/FilterImage.cpp:
(WebCore::FilterImage::create):
(WebCore::FilterImage::FilterImage):
(WebCore::FilterImage::correctPremultipliedPixelBuffer):
* platform/graphics/filters/FilterImage.h:
* platform/graphics/filters/SourceAlpha.cpp:
(WebCore::SourceAlpha::calculateImageRect const): Deleted.
* platform/graphics/filters/SourceAlpha.h:
* platform/graphics/filters/SourceGraphic.cpp:
(WebCore::SourceGraphic::calculateImageRect const): Deleted.
* platform/graphics/filters/SourceGraphic.h:
* platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
(WebCore::SourceGraphicSoftwareApplier::apply const):
* rendering/CSSFilter.cpp:
(WebCore::CSSFilter::apply):
* rendering/CSSFilter.h:
* svg/graphics/filters/SVGFEImage.h:
* svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::apply):
* svg/graphics/filters/SVGFilter.h:
* svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::SVGFilterBuilder::buildFilterEffects):
(WebCore::SVGFilterBuilder::buildExpression const):
(WebCore::collectEffects): Deleted.
(WebCore::totalNumberFilterEffects): Deleted.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicscoreimageSourceGraphicCoreImageAppliermm">trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEBlendh">trunk/Source/WebCore/platform/graphics/filters/FEBlend.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFECompositeh">trunk/Source/WebCore/platform/graphics/filters/FEComposite.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEDisplacementMapcpp">trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEDisplacementMaph">trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEFloodh">trunk/Source/WebCore/platform/graphics/filters/FEFlood.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFEMergeh">trunk/Source/WebCore/platform/graphics/filters/FEMerge.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFETurbulenceh">trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFiltercpp">trunk/Source/WebCore/platform/graphics/filters/Filter.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterh">trunk/Source/WebCore/platform/graphics/filters/Filter.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterEffectcpp">trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterEffecth">trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterFunctionh">trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterImagecpp">trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersFilterImageh">trunk/Source/WebCore/platform/graphics/filters/FilterImage.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersSourceAlphacpp">trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersSourceAlphah">trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersSourceGraphiccpp">trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfiltersSourceGraphich">trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgraphicsfilterssoftwareSourceGraphicSoftwareAppliercpp">trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingCSSFiltercpp">trunk/Source/WebCore/rendering/CSSFilter.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingCSSFilterh">trunk/Source/WebCore/rendering/CSSFilter.h</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsfiltersSVGFEImageh">trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsfiltersSVGFiltercpp">trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsfiltersSVGFilterh">trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h</a></li>
<li><a href="#trunkSourceWebCoresvggraphicsfiltersSVGFilterBuildercpp">trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/ChangeLog      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -1,3 +1,113 @@
</span><ins>+2021-12-08  Said Abou-Hallawa  <said@apple.com>
+
+        [GPU Process] [Filters] Make Filter::apply() and FilterEffect:apply() take FilterImageVector for the inputs
+        https://bugs.webkit.org/show_bug.cgi?id=233973
+        rdar://86248999
+
+        Reviewed by Cameron McCormack.
+
+        This is a step towards removing the dependency on the input effects. This 
+        step is required to make encoding/decoding the FilterEffect just be
+        sending or receiving its primitive data.
+
+        In this patch:
+
+        -- The sourceImage and sourceImageRect arguments to Filter::apply() are
+           used to create a FilterImage. This will be the input to the SourceGraphic.
+
+        -- The members m_sourceImage and m_sourceImageRect of Filter are removed.
+
+        -- CSSFilter::apply() loops through its functions and uses the result
+           of every function as the input to the next one. The initial input is
+           the sourceImage. And the result of the last function is the returned
+           FilterImage.
+
+        -- SVGFilter::apply() loops through its expression. It uses a stack of
+           FilterImageVector to keep track of the inputs while applying each
+           FilterEffect. Every FilterEffect is asked to takeInputs() from this 
+           stack. The result of applying the FilterEffect is pushed on this stack.
+           The stack should have a single FilterImage when finishing the loop.
+           This item is the result of applying the Filter.
+
+        -- FilterEffect::transformInputsColorSpace() was added to transform the
+           input FilterImageVector to the operating color space of FilterEffect.
+           It is overridden by FEDisplacementMap which does not transform the
+           color space of the first input FilterImage.
+
+        -- FilterEffect::correctPremultipliedInputs() was added to correct the
+           premultiplied pixels of the inputs FilterImageVector. We do not need
+           to do this correction if the FilterEffect we apply is arithmetic
+           composite filter. Otherwise we need to correct the FilterImage of any
+           arithmetic composite filter in the FilterImageVector.
+
+        -- No need for totalNumberFilterEffects(). This count is the size of the
+           SVGFilter expression.
+
+        * platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm:
+        (WebCore::SourceGraphicCoreImageApplier::apply const):
+        * platform/graphics/filters/FEBlend.h:
+        * platform/graphics/filters/FEComposite.h:
+        * platform/graphics/filters/FEDisplacementMap.cpp:
+        (WebCore::FEDisplacementMap::calculateImageRect const):
+        (WebCore::FEDisplacementMap::transformInputsColorSpace const):
+        (WebCore::FEDisplacementMap::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FEDisplacementMap.h:
+        * platform/graphics/filters/FEFlood.h:
+        * platform/graphics/filters/FEMerge.h:
+        * platform/graphics/filters/FETurbulence.h:
+        * platform/graphics/filters/Filter.cpp:
+        (WebCore::Filter::apply):
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::sourceImageRect const): Deleted.
+        (WebCore::Filter::setSourceImageRect): Deleted.
+        (WebCore::Filter::sourceImage const): Deleted.
+        (WebCore::Filter::setSourceImage): Deleted.
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::takeImageInputs const):
+        (WebCore::FilterEffect::calculateImageRect const):
+        (WebCore::FilterEffect::transformInputsColorSpace const):
+        (WebCore::FilterEffect::correctPremultipliedInputs const):
+        (WebCore::FilterEffect::apply):
+        (WebCore::FilterEffect::inputEffect const):
+        (WebCore::FilterEffect::inputFilterImages const): Deleted.
+        (WebCore::FilterEffect::correctPremultipliedResultIfNeeded): Deleted.
+        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::filterImage const):
+        (WebCore::FilterEffect::numberOfEffectInputs const):
+        (WebCore::FilterEffect::numberOfImageInputs const):
+        (WebCore::FilterEffect::resultIsValidPremultiplied const):
+        (WebCore::FilterEffect::mayProduceInvalidPremultipliedPixels const): Deleted.
+        (WebCore::FilterEffect::correctFilterResultIfNeeded): Deleted.
+        (WebCore::FilterEffect::transformResultColorSpace): Deleted.
+        * platform/graphics/filters/FilterFunction.h:
+        (WebCore::FilterFunction::apply):
+        * platform/graphics/filters/FilterImage.cpp:
+        (WebCore::FilterImage::create):
+        (WebCore::FilterImage::FilterImage):
+        (WebCore::FilterImage::correctPremultipliedPixelBuffer):
+        * platform/graphics/filters/FilterImage.h:
+        * platform/graphics/filters/SourceAlpha.cpp:
+        (WebCore::SourceAlpha::calculateImageRect const): Deleted.
+        * platform/graphics/filters/SourceAlpha.h:
+        * platform/graphics/filters/SourceGraphic.cpp:
+        (WebCore::SourceGraphic::calculateImageRect const): Deleted.
+        * platform/graphics/filters/SourceGraphic.h:
+        * platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp:
+        (WebCore::SourceGraphicSoftwareApplier::apply const):
+        * rendering/CSSFilter.cpp:
+        (WebCore::CSSFilter::apply):
+        * rendering/CSSFilter.h:
+        * svg/graphics/filters/SVGFEImage.h:
+        * svg/graphics/filters/SVGFilter.cpp:
+        (WebCore::SVGFilter::apply):
+        * svg/graphics/filters/SVGFilter.h:
+        * svg/graphics/filters/SVGFilterBuilder.cpp:
+        (WebCore::SVGFilterBuilder::buildFilterEffects):
+        (WebCore::SVGFilterBuilder::buildExpression const):
+        (WebCore::collectEffects): Deleted.
+        (WebCore::totalNumberFilterEffects): Deleted.
+
</ins><span class="cx"> 2021-12-08  Patrick Griffis  <pgriffis@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         CSP: Skip whitespace at beginning of policy header
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicscoreimageSourceGraphicCoreImageAppliermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm        2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/coreimage/SourceGraphicCoreImageApplier.mm   2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -28,15 +28,16 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(CORE_IMAGE)
</span><span class="cx"> 
</span><del>-#import "Filter.h"
</del><span class="cx"> #import "FilterImage.h"
</span><span class="cx"> #import "PlatformImageBuffer.h"
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-bool SourceGraphicCoreImageApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
</del><ins>+bool SourceGraphicCoreImageApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
</ins><span class="cx"> {
</span><del>-    auto sourceImage = filter.sourceImage();
</del><ins>+    auto& input = inputs[0].get();
+
+    auto sourceImage = input.imageBuffer();
</ins><span class="cx">     if (!sourceImage)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEBlendh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEBlend.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEBlend.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEBlend.h    2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -41,6 +41,8 @@
</span><span class="cx"> private:
</span><span class="cx">     FEBlend(BlendMode);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return 2; }
+    
</ins><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span><span class="cx"> 
</span><span class="cx">     void platformApplyNEON(unsigned char* srcPixelArrayA, unsigned char* srcPixelArrayB, unsigned char* dstPixelArray,
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFECompositeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEComposite.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEComposite.h     2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEComposite.h        2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -63,9 +63,11 @@
</span><span class="cx"> private:
</span><span class="cx">     FEComposite(const CompositeOperationType&, float k1, float k2, float k3, float k4);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return 2; }
+
</ins><span class="cx">     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
</span><span class="cx"> 
</span><del>-    bool mayProduceInvalidPremultipliedPixels() const override { return m_type == FECOMPOSITE_OPERATOR_ARITHMETIC; }
</del><ins>+    bool resultIsValidPremultiplied() const override { return m_type != FECOMPOSITE_OPERATOR_ARITHMETIC; }
</ins><span class="cx"> 
</span><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEDisplacementMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp     2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.cpp        2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -68,6 +68,11 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
+{
+    return filter.maxEffectRect(primitiveSubregion);
+}
+
</ins><span class="cx"> const DestinationColorSpace& FEDisplacementMap::resultColorSpace(const FilterImageVector& inputs) const
</span><span class="cx"> {
</span><span class="cx">     // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
</span><span class="lines">@@ -77,18 +82,13 @@
</span><span class="cx">     return inputs[0]->colorSpace();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)
</del><ins>+void FEDisplacementMap::transformInputsColorSpace(const FilterImageVector& inputs) const
</ins><span class="cx"> {
</span><span class="cx">     // Do not transform the first primitive input, as per the spec.
</span><del>-    if (index)
-        in->transformResultColorSpace(operatingColorSpace());
</del><ins>+    ASSERT(inputs.size() == 2);
+    inputs[1]->transformToColorSpace(operatingColorSpace());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FloatRect FEDisplacementMap::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect& primitiveSubregion) const
-{
-    return filter.maxEffectRect(primitiveSubregion);
-}
-
</del><span class="cx"> std::unique_ptr<FilterEffectApplier> FEDisplacementMap::createApplier(const Filter&) const
</span><span class="cx"> {
</span><span class="cx">     return FilterEffectApplier::create<FEDisplacementMapSoftwareApplier>(*this);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEDisplacementMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h       2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEDisplacementMap.h  2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -54,11 +54,13 @@
</span><span class="cx"> private:
</span><span class="cx">     FEDisplacementMap(ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float);
</span><span class="cx"> 
</span><del>-    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
-    void transformResultColorSpace(FilterEffect*, const int) override;
</del><ins>+    unsigned numberOfEffectInputs() const override { return 2; }
</ins><span class="cx"> 
</span><span class="cx">     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
</span><span class="cx"> 
</span><ins>+    const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const override;
+    void transformInputsColorSpace(const FilterImageVector& inputs) const override;
+
</ins><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span><span class="cx"> 
</span><span class="cx">     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEFloodh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEFlood.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEFlood.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEFlood.h    2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -49,6 +49,8 @@
</span><span class="cx"> private:
</span><span class="cx">     FEFlood(const Color& floodColor, float floodOpacity);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return 0; }
+
</ins><span class="cx">     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFEMergeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FEMerge.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FEMerge.h 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FEMerge.h    2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> public:
</span><span class="cx">     WEBCORE_EXPORT static Ref<FEMerge> create(unsigned numberOfEffectInputs);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return m_numberOfEffectInputs; }
+
</ins><span class="cx">     template<class Encoder> void encode(Encoder&) const;
</span><span class="cx">     template<class Decoder> static std::optional<Ref<FEMerge>> decode(Decoder&);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFETurbulenceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h    2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h       2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -63,6 +63,8 @@
</span><span class="cx"> private:
</span><span class="cx">     FETurbulence(TurbulenceType, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return 0; }
+
</ins><span class="cx">     FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFiltercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/Filter.cpp        2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.cpp   2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -83,13 +83,20 @@
</span><span class="cx"> 
</span><span class="cx"> RefPtr<FilterImage> Filter::apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect)
</span><span class="cx"> {
</span><del>-    setSourceImage(sourceImage);
-    setSourceImageRect(sourceImageRect);
</del><ins>+    RefPtr<FilterImage> input;
</ins><span class="cx"> 
</span><del>-    auto result = apply();
</del><ins>+    if (sourceImage) {
+        auto absoluteSourceImageRect = enclosingIntRect(scaledByFilterScale(sourceImageRect));
+        input = FilterImage::create(m_filterRegion, sourceImageRect, absoluteSourceImageRect, Ref { *sourceImage });
+        if (!input)
+            return nullptr;
+    }
+
+    auto result = apply(input.get());
</ins><span class="cx">     if (!result)
</span><del>-        return { };
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><ins>+    result->correctPremultipliedPixelBuffer();
</ins><span class="cx">     result->transformToColorSpace(DestinationColorSpace::SRGB());
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/Filter.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/Filter.h  2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/Filter.h     2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -44,15 +44,9 @@
</span><span class="cx">     FloatSize filterScale() const { return m_filterScale; }
</span><span class="cx">     void setFilterScale(const FloatSize& filterScale) { m_filterScale = filterScale; }
</span><span class="cx"> 
</span><del>-    FloatRect sourceImageRect() const { return m_sourceImageRect; }
-    void setSourceImageRect(const FloatRect& sourceImageRect) { m_sourceImageRect = sourceImageRect; }
-
</del><span class="cx">     FloatRect filterRegion() const { return m_filterRegion; }
</span><span class="cx">     void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
</span><span class="cx"> 
</span><del>-    ImageBuffer* sourceImage() const { return m_sourceImage.get(); }
-    void setSourceImage(RefPtr<ImageBuffer>&& sourceImage) { m_sourceImage = WTFMove(sourceImage); }
-
</del><span class="cx">     ClipOperation clipOperation() const { return m_clipOperation; }
</span><span class="cx">     void setClipOperation(ClipOperation clipOperation) { m_clipOperation = clipOperation; }
</span><span class="cx"> 
</span><span class="lines">@@ -68,8 +62,8 @@
</span><span class="cx">     virtual RefPtr<FilterEffect> lastEffect() const = 0;
</span><span class="cx"> 
</span><span class="cx">     bool clampFilterRegionIfNeeded();
</span><del>-    
-    virtual RefPtr<FilterImage> apply() = 0;
</del><ins>+
+    virtual RefPtr<FilterImage> apply(FilterImage* sourceImage) = 0;
</ins><span class="cx">     WEBCORE_EXPORT RefPtr<FilterImage> apply(ImageBuffer* sourceImage, const FloatRect& sourceImageRect);
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -81,10 +75,6 @@
</span><span class="cx">     FloatSize m_filterScale;
</span><span class="cx">     ClipOperation m_clipOperation;
</span><span class="cx">     FloatRect m_filterRegion;
</span><del>-
-    // FIXME: these should not be members of Filter. They should be passed to Filter::apply().
-    FloatRect m_sourceImageRect;
-    RefPtr<ImageBuffer> m_sourceImage;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterEffectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp  2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp     2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -33,12 +33,20 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
</del><ins>+FilterImageVector FilterEffect::takeImageInputs(FilterImageVector& stack) const
</ins><span class="cx"> {
</span><del>-    FloatRect imageRect;
-    for (auto& input : inputs)
-        imageRect.unite(input->imageRect());
-    return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
</del><ins>+    unsigned inputsSize = numberOfImageInputs();
+    ASSERT(stack.size() >= inputsSize);
+    if (!inputsSize)
+        return { };
+
+    Vector<Ref<FilterImage>> inputs;
+    inputs.reserveInitialCapacity(inputsSize);
+
+    for (; inputsSize; --inputsSize)
+        inputs.uncheckedAppend(stack.takeLast());
+
+    return inputs;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> FloatRect FilterEffect::calculatePrimitiveSubregion(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry) const
</span><span class="lines">@@ -68,51 +76,60 @@
</span><span class="cx">     return primitiveSubregion;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FilterEffect* FilterEffect::inputEffect(unsigned number) const
</del><ins>+FloatRect FilterEffect::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
</ins><span class="cx"> {
</span><del>-    ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
-    return m_inputEffects.at(number).get();
</del><ins>+    FloatRect imageRect;
+    for (auto& input : inputs)
+        imageRect.unite(input->imageRect());
+    return filter.clipToMaxEffectRect(imageRect, primitiveSubregion);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool FilterEffect::apply(const Filter& filter, const std::optional<FilterEffectGeometry>& geometry)
</del><ins>+void FilterEffect::transformInputsColorSpace(const FilterImageVector& inputs) const
</ins><span class="cx"> {
</span><del>-    if (hasResult())
-        return true;
</del><ins>+    for (auto& input : inputs)
+        input->transformToColorSpace(operatingColorSpace());
+}
</ins><span class="cx"> 
</span><del>-    unsigned size = m_inputEffects.size();
-    for (unsigned i = 0; i < size; ++i) {
-        FilterEffect* in = m_inputEffects.at(i).get();
</del><ins>+void FilterEffect::correctPremultipliedInputs(const FilterImageVector& inputs) const
+{
+    // Correct any invalid pixels, if necessary, in the result of a filter operation.
+    // This method is used to ensure valid pixel values on filter inputs and the final result.
+    // Only the arithmetic composite filter ever needs to perform correction.
+    for (auto& input : inputs)
+        input->correctPremultipliedPixelBuffer();
+}
</ins><span class="cx"> 
</span><del>-        // Convert input results to the current effect's color space.
-        ASSERT(in->hasResult());
-        transformResultColorSpace(in, i);
-    }
</del><ins>+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, FilterImage& input)
+{
+    return apply(filter, FilterImageVector { Ref { input } });
+}
</ins><span class="cx"> 
</span><del>-    if (!mayProduceInvalidPremultipliedPixels()) {
-        for (auto& in : m_inputEffects)
-            in->correctPremultipliedResultIfNeeded();
-    }
</del><ins>+RefPtr<FilterImage> FilterEffect::apply(const Filter& filter, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& geometry)
+{
+    ASSERT(inputs.size() == numberOfImageInputs());
</ins><span class="cx"> 
</span><del>-    auto inputFilterImages = this->inputFilterImages();
</del><ins>+    if (m_filterImage)
+        return m_filterImage;
</ins><span class="cx"> 
</span><del>-    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputFilterImages, geometry);
-    auto imageRect = calculateImageRect(filter, inputFilterImages, primitiveSubregion);
</del><ins>+    auto primitiveSubregion = calculatePrimitiveSubregion(filter, inputs, geometry);
+    auto imageRect = calculateImageRect(filter, inputs, primitiveSubregion);
</ins><span class="cx">     auto absoluteImageRect = enclosingIntRect(filter.scaledByFilterScale(imageRect));
</span><span class="cx"> 
</span><span class="cx">     if (absoluteImageRect.isEmpty() || ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()))
</span><del>-        return false;
</del><ins>+        return nullptr;
</ins><span class="cx">     
</span><del>-    auto isAlphaImage = resultIsAlphaImage(inputFilterImages);
-    auto imageColorSpace = resultColorSpace(inputFilterImages);
</del><ins>+    auto isAlphaImage = resultIsAlphaImage(inputs);
+    auto isValidPremultiplied = resultIsValidPremultiplied();
+    auto imageColorSpace = resultColorSpace(inputs);
</ins><span class="cx"> 
</span><del>-    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, filter.renderingMode(), imageColorSpace);
-    if (!m_filterImage)
-        return false;
-
</del><span class="cx">     auto applier = createApplier(filter);
</span><span class="cx">     if (!applier)
</span><del>-        return false;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><ins>+    m_filterImage = FilterImage::create(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, filter.renderingMode(), imageColorSpace);
+    if (!m_filterImage)
+        return nullptr;
+
</ins><span class="cx">     LOG_WITH_STREAM(Filters, stream
</span><span class="cx">         << "FilterEffect " << filterName() << " " << this << " apply():"
</span><span class="cx">         << "\n  filterPrimitiveSubregion " << primitiveSubregion
</span><span class="lines">@@ -120,9 +137,22 @@
</span><span class="cx">         << "\n  maxEffectRect " << filter.maxEffectRect(primitiveSubregion)
</span><span class="cx">         << "\n  filter scale " << filter.filterScale());
</span><span class="cx"> 
</span><del>-    return applier->apply(filter, inputFilterImages, *m_filterImage);
</del><ins>+    transformInputsColorSpace(inputs);
+    if (isValidPremultiplied)
+        correctPremultipliedInputs(inputs);
+
+    if (!applier->apply(filter, inputs, *m_filterImage))
+        m_filterImage = nullptr;
+
+    return m_filterImage;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FilterEffect* FilterEffect::inputEffect(unsigned number) const
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(number < m_inputEffects.size());
+    return m_inputEffects.at(number).get();
+}
+
</ins><span class="cx"> void FilterEffect::clearResult()
</span><span class="cx"> {
</span><span class="cx">     m_filterImage = nullptr;
</span><span class="lines">@@ -137,30 +167,6 @@
</span><span class="cx">         effect->clearResultsRecursive();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FilterImageVector FilterEffect::inputFilterImages() const
-{
-    FilterImageVector filterImages;
-
-    for (auto& inputEffect : m_inputEffects)
-        filterImages.append(*inputEffect->filterImage());
-
-    return filterImages;
-}
-
-void FilterEffect::correctPremultipliedResultIfNeeded()
-{
-    if (!hasResult() || !mayProduceInvalidPremultipliedPixels())
-        return;
-    m_filterImage->correctPremultipliedPixelBuffer();
-}
-
-void FilterEffect::transformResultColorSpace(const DestinationColorSpace& destinationColorSpace)
-{
-    if (!hasResult())
-        return;
-    m_filterImage->transformToColorSpace(destinationColorSpace);
-}
-
</del><span class="cx"> TextStream& FilterEffect::externalRepresentation(TextStream& ts, FilterRepresentation representation) const
</span><span class="cx"> {
</span><span class="cx">     // FIXME: We should dump the subRegions of the filter primitives here later. This isn't
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterEffecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h    2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h       2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -40,21 +40,21 @@
</span><span class="cx"> class FilterEffectGeometry;
</span><span class="cx"> 
</span><span class="cx"> class FilterEffect : public FilterFunction {
</span><ins>+    using FilterFunction::apply;
+
</ins><span class="cx"> public:
</span><span class="cx">     void clearResult() override;
</span><span class="cx">     void clearResultsRecursive();
</span><span class="cx">     bool hasResult() const { return m_filterImage; }
</span><span class="cx"> 
</span><del>-    FilterImage* filterImage() const { return m_filterImage.get(); }
</del><ins>+    RefPtr<FilterImage> filterImage() const { return m_filterImage; }
+    FilterImageVector takeImageInputs(FilterImageVector& stack) const;
</ins><span class="cx"> 
</span><span class="cx">     FilterEffectVector& inputEffects() { return m_inputEffects; }
</span><span class="cx">     FilterEffect* inputEffect(unsigned) const;
</span><del>-    unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
</del><span class="cx"> 
</span><del>-    void transformResultColorSpace(const DestinationColorSpace&);
</del><ins>+    RefPtr<FilterImage> apply(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>& = std::nullopt);
</ins><span class="cx"> 
</span><del>-    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) override;
-
</del><span class="cx">     const DestinationColorSpace& operatingColorSpace() const { return m_operatingColorSpace; }
</span><span class="cx">     virtual void setOperatingColorSpace(const DestinationColorSpace& colorSpace) { m_operatingColorSpace = colorSpace; }
</span><span class="cx"> 
</span><span class="lines">@@ -63,29 +63,28 @@
</span><span class="cx"> protected:
</span><span class="cx">     using FilterFunction::FilterFunction;
</span><span class="cx"> 
</span><del>-    virtual bool mayProduceInvalidPremultipliedPixels() const { return false; }
</del><ins>+    virtual unsigned numberOfEffectInputs() const { return 1; }
+    unsigned numberOfImageInputs() const { return filterType() == FilterEffect::Type::SourceGraphic ? 1 : numberOfEffectInputs(); }
</ins><span class="cx"> 
</span><del>-    void correctPremultipliedResultIfNeeded();
</del><ins>+    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector& inputs, const std::optional<FilterEffectGeometry>&) const;
</ins><span class="cx"> 
</span><del>-    // Correct any invalid pixels, if necessary, in the result of a filter operation.
-    // This method is used to ensure valid pixel values on filter inputs and the final result.
-    // Only the arithmetic composite filter ever needs to perform correction.
-    virtual void correctFilterResultIfNeeded() { }
-
-    virtual void transformResultColorSpace(FilterEffect* in, const int) { in->transformResultColorSpace(m_operatingColorSpace); }
-
-    FilterImageVector inputFilterImages() const;
-    
-    FloatRect calculatePrimitiveSubregion(const Filter&, const FilterImageVector&, const std::optional<FilterEffectGeometry>&) const;
-
</del><span class="cx">     virtual FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const;
</span><span class="cx"> 
</span><span class="cx">     // Solid black image with different alpha values.
</span><span class="cx">     virtual bool resultIsAlphaImage(const FilterImageVector&) const { return false; }
</span><ins>+
+    virtual bool resultIsValidPremultiplied() const { return true; }
+
</ins><span class="cx">     virtual const DestinationColorSpace& resultColorSpace(const FilterImageVector&) const { return m_operatingColorSpace; }
</span><span class="cx"> 
</span><ins>+    virtual void transformInputsColorSpace(const FilterImageVector& inputs) const;
+    
+    void correctPremultipliedInputs(const FilterImageVector& inputs) const;
+
</ins><span class="cx">     virtual std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const = 0;
</span><span class="cx"> 
</span><ins>+    RefPtr<FilterImage> apply(const Filter&, FilterImage& input) override;
+
</ins><span class="cx">     FilterEffectVector m_inputEffects;
</span><span class="cx"> 
</span><span class="cx">     RefPtr<FilterImage> m_filterImage;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterFunctionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h  2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h     2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -26,6 +26,8 @@
</span><span class="cx"> #pragma once
</span><span class="cx"> 
</span><span class="cx"> #include "FilterEffectGeometry.h"
</span><ins>+#include "FilterImage.h"
+#include "FilterImageVector.h"
</ins><span class="cx"> #include "FloatRect.h"
</span><span class="cx"> #include "IntRectExtent.h"
</span><span class="cx"> #include <wtf/RefCounted.h>
</span><span class="lines">@@ -94,7 +96,7 @@
</span><span class="cx">     virtual bool supportsCoreImageRendering() const { return false; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    virtual bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) { return false; }
</del><ins>+    virtual RefPtr<FilterImage> apply(const Filter&, FilterImage&) { return nullptr; }
</ins><span class="cx">     virtual IntOutsets outsets() const { return { }; }
</span><span class="cx">     virtual void clearResult() { }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterImagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.cpp      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -38,22 +38,38 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
</del><ins>+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!ImageBuffer::sizeNeedsClamping(absoluteImageRect.size()));
</span><del>-    return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, renderingMode, colorSpace));
</del><ins>+    return adoptRef(new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, isAlphaImage, isValidPremultiplied, renderingMode, colorSpace));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
</del><ins>+RefPtr<FilterImage> FilterImage::create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+{
+    return adoptRef(*new FilterImage(primitiveSubregion, imageRect, absoluteImageRect, WTFMove(imageBuffer)));
+}
+
+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode renderingMode, const DestinationColorSpace& colorSpace)
</ins><span class="cx">     : m_primitiveSubregion(primitiveSubregion)
</span><span class="cx">     , m_imageRect(imageRect)
</span><span class="cx">     , m_absoluteImageRect(absoluteImageRect)
</span><span class="cx">     , m_isAlphaImage(isAlphaImage)
</span><ins>+    , m_isValidPremultiplied(isValidPremultiplied)
</ins><span class="cx">     , m_renderingMode(renderingMode)
</span><span class="cx">     , m_colorSpace(colorSpace)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FilterImage::FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&& imageBuffer)
+    : m_primitiveSubregion(primitiveSubregion)
+    , m_imageRect(imageRect)
+    , m_absoluteImageRect(absoluteImageRect)
+    , m_renderingMode(imageBuffer->renderingMode())
+    , m_colorSpace(imageBuffer->colorSpace())
+    , m_imageBuffer(WTFMove(imageBuffer))
+{
+}
+
</ins><span class="cx"> FloatRect FilterImage::maxEffectRect(const Filter& filter) const
</span><span class="cx"> {
</span><span class="cx">     return filter.maxEffectRect(m_primitiveSubregion);
</span><span class="lines">@@ -281,7 +297,7 @@
</span><span class="cx"> void FilterImage::correctPremultipliedPixelBuffer()
</span><span class="cx"> {
</span><span class="cx">     // Must operate on pre-multiplied results; other formats cannot have invalid pixels.
</span><del>-    if (!m_premultipliedPixelBuffer)
</del><ins>+    if (!m_premultipliedPixelBuffer || m_isValidPremultiplied)
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     Uint8ClampedArray& imageArray = m_premultipliedPixelBuffer->data();
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersFilterImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/FilterImage.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/FilterImage.h     2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterImage.h        2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -45,7 +45,8 @@
</span><span class="cx"> 
</span><span class="cx"> class FilterImage : public RefCounted<FilterImage> {
</span><span class="cx"> public:
</span><del>-    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
</del><ins>+    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+    static RefPtr<FilterImage> create(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
</ins><span class="cx"> 
</span><span class="cx">     // The return values are in filter coordinates.
</span><span class="cx">     FloatRect primitiveSubregion() const { return m_primitiveSubregion; }
</span><span class="lines">@@ -76,7 +77,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, RenderingMode, const DestinationColorSpace&);
</del><ins>+    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, bool isAlphaImage, bool isValidPremultiplied, RenderingMode, const DestinationColorSpace&);
+    FilterImage(const FloatRect& primitiveSubregion, const FloatRect& imageRect, const IntRect& absoluteImageRect, Ref<ImageBuffer>&&);
</ins><span class="cx"> 
</span><span class="cx">     std::optional<PixelBuffer>& pixelBufferSlot(AlphaPremultiplication);
</span><span class="cx"> 
</span><span class="lines">@@ -93,6 +95,7 @@
</span><span class="cx">     IntRect m_absoluteImageRect;
</span><span class="cx"> 
</span><span class="cx">     bool m_isAlphaImage { false };
</span><ins>+    bool m_isValidPremultiplied { true };
</ins><span class="cx">     RenderingMode m_renderingMode;
</span><span class="cx">     DestinationColorSpace m_colorSpace;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersSourceAlphacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.cpp      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -48,11 +48,6 @@
</span><span class="cx">     inputEffects().append(&sourceEffect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FloatRect SourceAlpha::calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect&) const
-{
-    return inputs[0]->imageRect();
-}
-
</del><span class="cx"> std::unique_ptr<FilterEffectApplier> SourceAlpha::createApplier(const Filter&) const
</span><span class="cx"> {
</span><span class="cx">     return FilterEffectApplier::create<SourceAlphaSoftwareApplier>(*this);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersSourceAlphah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h     2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceAlpha.h        2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -35,8 +35,6 @@
</span><span class="cx">     SourceAlpha();
</span><span class="cx">     explicit SourceAlpha(FilterEffect&);
</span><span class="cx"> 
</span><del>-    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
-
</del><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span><span class="cx"> 
</span><span class="cx">     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const override;
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersSourceGraphiccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.cpp    2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -41,11 +41,6 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FloatRect SourceGraphic::calculateImageRect(const Filter& filter, const FilterImageVector&, const FloatRect&) const
-{
-    return filter.sourceImageRect();
-}
-
</del><span class="cx"> std::unique_ptr<FilterEffectApplier> SourceGraphic::createApplier(const Filter& filter) const
</span><span class="cx"> {
</span><span class="cx"> #if USE(CORE_IMAGE)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfiltersSourceGraphich"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/SourceGraphic.h      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -38,7 +38,7 @@
</span><span class="cx">     bool supportsCoreImageRendering() const override { return true; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    FloatRect calculateImageRect(const Filter&, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const override;
</del><ins>+    unsigned numberOfEffectInputs() const override { return 0; }
</ins><span class="cx"> 
</span><span class="cx">     std::unique_ptr<FilterEffectApplier> createApplier(const Filter&) const override;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgraphicsfilterssoftwareSourceGraphicSoftwareAppliercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp 2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/platform/graphics/filters/software/SourceGraphicSoftwareApplier.cpp    2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -21,17 +21,17 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "SourceGraphicSoftwareApplier.h"
</span><span class="cx"> 
</span><del>-#include "Filter.h"
</del><span class="cx"> #include "GraphicsContext.h"
</span><span class="cx"> #include "ImageBuffer.h"
</span><del>-#include "SourceGraphic.h"
</del><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><del>-bool SourceGraphicSoftwareApplier::apply(const Filter& filter, const FilterImageVector&, FilterImage& result) const
</del><ins>+bool SourceGraphicSoftwareApplier::apply(const Filter&, const FilterImageVector& inputs, FilterImage& result) const
</ins><span class="cx"> {
</span><ins>+    auto& input = inputs[0].get();
+
</ins><span class="cx">     auto resultImage = result.imageBuffer();
</span><del>-    auto sourceImage = filter.sourceImage();
</del><ins>+    auto sourceImage = input.imageBuffer();
</ins><span class="cx">     if (!resultImage || !sourceImage)
</span><span class="cx">         return false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingCSSFiltercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/CSSFilter.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/CSSFilter.cpp     2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.cpp        2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -368,15 +368,20 @@
</span><span class="cx">         function->clearResult();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<FilterImage> CSSFilter::apply()
</del><ins>+RefPtr<FilterImage> CSSFilter::apply(FilterImage* sourceImage)
</ins><span class="cx"> {
</span><ins>+    if (!sourceImage)
+        return nullptr;
+    
+    RefPtr<FilterImage> result = sourceImage;
+
</ins><span class="cx">     for (auto& function : m_functions) {
</span><del>-        if (function->isSVGFilter())
-            downcast<SVGFilter>(function.ptr())->setSourceImageRect(sourceImageRect());
-        if (!function->apply(*this))
</del><ins>+        result = function->apply(*this, *result);
+        if (!result)
</ins><span class="cx">             return nullptr;
</span><span class="cx">     }
</span><del>-    return lastEffect()->filterImage();
</del><ins>+
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void CSSFilter::setFilterRegion(const FloatRect& filterRegion)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingCSSFilterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/CSSFilter.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/CSSFilter.h       2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/rendering/CSSFilter.h  2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx">     IntOutsets outsets() const final;
</span><span class="cx"> 
</span><span class="cx">     void clearIntermediateResults();
</span><del>-    RefPtr<FilterImage> apply() final;
</del><ins>+    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     CSSFilter(RenderingMode, const FloatSize& filterScale, ClipOperation, bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin);
</span></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsfiltersSVGFEImageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFEImage.h      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -47,6 +47,8 @@
</span><span class="cx"> private:
</span><span class="cx">     FEImage(SourceImage&&, const FloatRect& sourceImageRect, const SVGPreserveAspectRatioValue&);
</span><span class="cx"> 
</span><ins>+    unsigned numberOfEffectInputs() const override { return 0; }
+
</ins><span class="cx">     // FEImage results are always in DestinationColorSpace::SRGB()
</span><span class="cx">     void setOperatingColorSpace(const DestinationColorSpace&) override { }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsfiltersSVGFiltercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp  2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp     2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -117,20 +117,51 @@
</span><span class="cx">     return m_expression.last().effect.ptr();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SVGFilter::apply(const Filter& filter, const std::optional<FilterEffectGeometry>&)
</del><ins>+RefPtr<FilterImage> SVGFilter::apply(const Filter&, FilterImage& sourceImage)
</ins><span class="cx"> {
</span><del>-    setSourceImage({ filter.sourceImage() });
-    return apply();
</del><ins>+    return apply(&sourceImage);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-RefPtr<FilterImage> SVGFilter::apply()
</del><ins>+RefPtr<FilterImage> SVGFilter::apply(FilterImage* sourceImage)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_expression.isEmpty());
</span><ins>+
+    FilterImageVector stack;
+
</ins><span class="cx">     for (auto& term : m_expression) {
</span><del>-        if (!term.effect->apply(*this, term.geometry))
</del><ins>+        auto& effect = term.effect;
+        auto geometry = term.geometry;
+
+        if (effect->filterType() == FilterEffect::Type::SourceGraphic) {
+            if (auto result = effect->filterImage()) {
+                stack.append(result.releaseNonNull());
+                continue;
+            }
+
+            if (!sourceImage)
+                return nullptr;
+
+            // Add sourceImage as an input to the SourceGraphic.
+            stack.append(Ref { *sourceImage });
+        }
+
+        // Need to remove the inputs here in case the effect already has a result.
+        auto inputs = effect->takeImageInputs(stack);
+
+        if (auto result = effect->filterImage()) {
+            stack.append(result.releaseNonNull());
+            continue;
+        }
+
+        auto result = term.effect->apply(*this, inputs, geometry);
+        if (!result)
</ins><span class="cx">             return nullptr;
</span><ins>+
+        stack.append(result.releaseNonNull());
</ins><span class="cx">     }
</span><del>-    return lastEffect()->filterImage();
</del><ins>+    
+    ASSERT(stack.size() == 1);
+    return stack.takeLast();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> IntOutsets SVGFilter::outsets() const
</span></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsfiltersSVGFilterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h    2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h       2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx">     
</span><span class="cx">     RefPtr<FilterEffect> lastEffect() const final;
</span><span class="cx"> 
</span><del>-    RefPtr<FilterImage> apply() final;
</del><ins>+    RefPtr<FilterImage> apply(FilterImage* sourceImage) final;
</ins><span class="cx"> 
</span><span class="cx">     WTF::TextStream& externalRepresentation(WTF::TextStream&, FilterRepresentation) const final;
</span><span class="cx"> 
</span><span class="lines">@@ -63,7 +63,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     FloatSize resolvedSize(const FloatSize&) const final;
</span><span class="cx"> 
</span><del>-    bool apply(const Filter&, const std::optional<FilterEffectGeometry>& = std::nullopt) final;
</del><ins>+    RefPtr<FilterImage> apply(const Filter&, FilterImage& sourceImage) final;
</ins><span class="cx">     IntOutsets outsets() const final;
</span><span class="cx">     void clearResult() final;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoresvggraphicsfiltersSVGFilterBuildercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp (286764 => 286765)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp   2021-12-09 06:37:26 UTC (rev 286764)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp      2021-12-09 06:39:26 UTC (rev 286765)
</span><span class="lines">@@ -34,6 +34,9 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><ins>+static constexpr unsigned maxTotalNumberFilterEffects = 100;
+static constexpr unsigned maxCountChildNodes = 200;
+
</ins><span class="cx"> void SVGFilterBuilder::setupBuiltinEffects(Ref<FilterEffect> sourceGraphic)
</span><span class="cx"> {
</span><span class="cx">     m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphic.ptr());
</span><span class="lines">@@ -76,28 +79,8 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-static unsigned collectEffects(const FilterEffect* effect, HashSet<const FilterEffect*>& allEffects)
-{
-    allEffects.add(effect);
-    unsigned size = effect->numberOfEffectInputs();
-    for (unsigned i = 0; i < size; ++i) {
-        FilterEffect* in = effect->inputEffect(i);
-        collectEffects(in, allEffects);
-    }
-    return allEffects.size();
-}
-
-static unsigned totalNumberFilterEffects(const FilterEffect& lastEffect)
-{
-    HashSet<const FilterEffect*> allEffects;
-    return collectEffects(&lastEffect, allEffects);
-}
-
</del><span class="cx"> RefPtr<FilterEffect> SVGFilterBuilder::buildFilterEffects(SVGFilterElement& filterElement)
</span><span class="cx"> {
</span><del>-    static constexpr unsigned maxCountChildNodes = 200;
-    static constexpr unsigned maxTotalNumberFilterEffects = 100;
-
</del><span class="cx">     if (filterElement.countChildNodes() > maxCountChildNodes)
</span><span class="cx">         return nullptr;
</span><span class="cx"> 
</span><span class="lines">@@ -124,10 +107,8 @@
</span><span class="cx">         add(effectElement.result(), effect);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects) {
</del><ins>+    if (!effect)
</ins><span class="cx">         clearEffects();
</span><del>-        return nullptr;
-    }
</del><span class="cx"> 
</span><span class="cx">     return effect;
</span><span class="cx"> }
</span><span class="lines">@@ -240,6 +221,9 @@
</span><span class="cx">     if (!buildEffectExpression(m_lastEffect, stack, 0, expression))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (expression.size() > maxTotalNumberFilterEffects)
+        return false;
+
</ins><span class="cx">     expression.reverse();
</span><span class="cx">     expression.shrinkToFit();
</span><span class="cx">     return true;
</span></span></pre>
</div>
</div>

</body>
</html>