⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 285618 in webkit


Ignore:
Timestamp:
Nov 10, 2021, 8:31:07 PM (5 years ago)
Author:
Said Abou-Hallawa
Message:

[GPU Process] Make CSSFilter be a composite of FilterFunctions
https://bugs.webkit.org/show_bug.cgi?id=232469
rdar://85047148

Reviewed by Simon Fraser.

Source/WebCore:

In this patch, the CSS reference filter is built as an SVGFilter and it
is kept as a FilterFunction in the CSSFilter functions' list. The Filter
associated with the FilterEffects of the referenced filter will be an
SVGFilter instead of the root CSSFilter. This will allow having color
spacing for the referenced filters different from the color spacing of
CSSFilter.

Also this patch makes a single function for building the primitives of
the SVGFilter instead of having two functions.

To allow operating through the SVGFilter as a FilterFunction owned by
CSSFilter, the SVGFilter will have a pointer to its lastEffect.

  • css/CSSFilterImageValue.cpp:

(WebCore::CSSFilterImageValue::image):

  • platform/graphics/filters/Filter.h:
  • platform/graphics/filters/FilterEffect.cpp:

(WebCore::collectEffects): Deleted.
(WebCore::FilterEffect::totalNumberOfEffectInputs const): Deleted.

  • platform/graphics/filters/FilterEffect.h:

(WebCore::FilterEffect::numberOfEffectInputs const):
(WebCore::FilterEffect::setMaxEffectRect):
(WebCore::FilterEffect::outsets const): Deleted.

  • platform/graphics/filters/FilterFunction.h:

(WebCore::FilterFunction::outsets const):
(WebCore::FilterFunction::clearResult):

  • rendering/CSSFilter.cpp:

(WebCore::CSSFilter::create):
(WebCore::CSSFilter::CSSFilter):
(WebCore::m_hasFilterThatShouldBeRestrictedBySecurityOrigin):
(WebCore::createBlurEffect):
(WebCore::createBrightnessEffect):
(WebCore::createContrastEffect):
(WebCore::createDropShadowEffect):
(WebCore::createGrayScaleEffect):
(WebCore::createHueRotateEffect):
(WebCore::createInvertEffect):
(WebCore::createOpacityEffect):
(WebCore::createSaturateEffect):
(WebCore::createSepiaEffect):
(WebCore::createSVGFilter):
(WebCore::setupLastEffectProperties):
(WebCore::CSSFilter::buildFilterFunctions):
(WebCore::CSSFilter::inputContext):
(WebCore::CSSFilter::allocateBackingStoreIfNeeded):
(WebCore::CSSFilter::lastEffect):
(WebCore::CSSFilter::determineFilterPrimitiveSubregion):
(WebCore::CSSFilter::clearIntermediateResults):
(WebCore::CSSFilter::apply):
(WebCore::CSSFilter::output):
(WebCore::CSSFilter::setSourceImageRect):
(WebCore::CSSFilter::outputRect):
(WebCore::CSSFilter::outsets const):
(WebCore::m_sourceGraphic): Deleted.
(WebCore::CSSFilter::buildReferenceFilter): Deleted.
(WebCore::CSSFilter::build): Deleted.
(WebCore::CSSFilter::output const): Deleted.
(WebCore::CSSFilter::setMaxEffectRects): Deleted.
(WebCore::CSSFilter::outputRect const): Deleted.

  • rendering/CSSFilter.h:
  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::setupFilters):

  • rendering/RenderLayerFilters.cpp:

(WebCore::RenderLayerFilters::buildFilter):
(WebCore::RenderLayerFilters::beginFilterEffect):
(WebCore::RenderLayerFilters::applyFilterEffect):

  • rendering/RenderLayerFilters.h:
  • rendering/svg/RenderSVGResourceFilter.cpp:

(WebCore::RenderSVGResourceFilter::applyResource):
(WebCore::RenderSVGResourceFilter::buildPrimitives const): Deleted.

  • rendering/svg/SVGRenderTreeAsText.cpp:

(WebCore::writeSVGResourceContainer):

  • svg/graphics/filters/SVGFilter.cpp:

(WebCore::SVGFilter::create):
(WebCore::SVGFilter::outsets const):
(WebCore::SVGFilter::clearResult):

  • svg/graphics/filters/SVGFilter.h:
  • svg/graphics/filters/SVGFilterBuilder.cpp:

(WebCore::SVGFilterBuilder::setupBuiltinEffects):
(WebCore::colorInterpolationForElement):
(WebCore::collectEffects):
(WebCore::totalNumberFilterEffects):
(WebCore::SVGFilterBuilder::buildFilterEffects):
(WebCore::SVGFilterBuilder::SVGFilterBuilder): Deleted.

  • svg/graphics/filters/SVGFilterBuilder.h:

LayoutTests:

Unskip filter hidpi layout tests.

Location:
trunk
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r285615 r285618  
     12021-11-10  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] Make CSSFilter be a composite of FilterFunctions
     4        https://bugs.webkit.org/show_bug.cgi?id=232469
     5        rdar://85047148
     6
     7        Reviewed by Simon Fraser.
     8
     9        Unskip filter hidpi layout tests.
     10
     11        * TestExpectations:
     12
    1132021-11-10  Tim Nguyen  <ntim@apple.com>
    214
  • trunk/LayoutTests/TestExpectations

    r285615 r285618  
    51745174
    51755175# These filter related failures should be fixed once webkit.org/b/232705 is resolved
    5176 webkit.org/b/232705 compositing/filters/drop-shadow.html [ Skip ]
    5177 webkit.org/b/232705 compositing/filters/simple-image-with-svg-filter.html [ Skip ]
    5178 webkit.org/b/232705 css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html [ Skip ]
    5179 webkit.org/b/232705 css3/filters/color-interpolation-filters.html [ Skip ]
    5180 webkit.org/b/232705 css3/filters/css-opacity-with-drop-shadow.html [ Skip ]
    5181 webkit.org/b/232705 css3/filters/drop-shadow.html [ Skip ]
    5182 webkit.org/b/232705 css3/filters/effect-brightness-square.html [ Skip ]
    5183 webkit.org/b/232705 css3/filters/effect-contrast-square.html [ Skip ]
    5184 webkit.org/b/232705 css3/filters/effect-grayscale-square.html [ Skip ]
    5185 webkit.org/b/232705 css3/filters/effect-hue-rotate-square.html [ Skip ]
    5186 webkit.org/b/232705 css3/filters/effect-invert-square.html [ Skip ]
    5187 webkit.org/b/232705 css3/filters/effect-reference-local-url-with-base.html [ Skip ]
    5188 webkit.org/b/232705 css3/filters/effect-saturate-square.html [ Skip ]
    5189 webkit.org/b/232705 css3/filters/effect-sepia-square.html [ Skip ]
    5190 webkit.org/b/232705 css3/filters/filter-is-on-subpixel-position.html [ Skip ]
    5191 webkit.org/b/232705 css3/filters/filter-on-overflow-hidden.html [ Skip ]
    5192 webkit.org/b/232705 css3/filters/filters-on-svg-root.html [ Skip ]
    5193 webkit.org/b/232705 css3/filters/hidpi-feConvolveMatrix.html [ Skip ]
    5194 webkit.org/b/232705 css3/filters/hidpi-filter-is-on-subpixel-position.html [ Skip ]
    5195 webkit.org/b/232705 css3/filters/invalidate-sourceAlpha.html [ Skip ]
    5196 webkit.org/b/232705 css3/filters/null-effect-check.html [ Skip ]
    5197 webkit.org/b/232705 css3/filters/reference-filter-set-filter-regions.html [ Skip ]
    5198 webkit.org/b/232705 css3/masking/clip-path-filter.html [ Skip ]
     5176webkit.org/b/232705 compositing/filters/sw-nested-shadow-overlaps-hw-nested-shadow.html [ Skip ]
     5177webkit.org/b/232705 compositing/filters/sw-shadow-overlaps-hw-layer.html [ Skip ]
     5178webkit.org/b/232705 compositing/filters/sw-shadow-overlaps-hw-shadow.html [ Skip ]
     5179webkit.org/b/232705 css3/filters/effect-reference-delete.html [ Skip ]
     5180webkit.org/b/232705 css3/filters/svg-blur-filter-clipped.html [ Skip ]
     5181webkit.org/b/232705 fast/filter-image/background-filter-image.html [ Skip ]
     5182webkit.org/b/232705 fast/filter-image/filter-image-blur.html [ Skip ]
     5183webkit.org/b/232705 fast/filter-image/filter-image-svg.html [ Skip ]
    51995184webkit.org/b/232705 fast/filter-image/filter-image.html [ Skip ]
    5200 webkit.org/b/232705 fast/gradients/conic-gradient-alpha.html [ Skip ]
    5201 webkit.org/b/232705 fast/gradients/conic-gradient-extended-stops.html [ Skip ]
    5202 webkit.org/b/232705 fast/gradients/conic-gradient.html [ Skip ]
    5203 webkit.org/b/232705 fast/hidpi/filters-and-image-buffer-resolution.html [ Skip ]
    5204 webkit.org/b/232705 fast/hidpi/filters-blur.html [ Skip ]
    5205 webkit.org/b/232705 fast/hidpi/filters-component-transfer.html [ Skip ]
    5206 webkit.org/b/232705 fast/hidpi/filters-hue-rotate.html [ Skip ]
    5207 webkit.org/b/232705 fast/hidpi/filters-invert.html [ Skip ]
    5208 webkit.org/b/232705 fast/hidpi/filters-morphology.html [ Skip ]
    5209 webkit.org/b/232705 fast/hidpi/filters-multiple.html [ Skip ]
    5210 webkit.org/b/232705 fast/hidpi/filters-reference.html [ Skip ]
    5211 webkit.org/b/232705 fast/hidpi/filters-shadow.html [ Skip ]
    5212 webkit.org/b/232705 fast/hidpi/filters-turbulence.html [ Skip ]
    5213 webkit.org/b/232705 fast/multicol/filter-in-columns.html [ Skip ]
    5214 webkit.org/b/232705 http/tests/css/filters-on-iframes.html [ Skip ]
    5215 webkit.org/b/232705 imported/blink/css3/filters/effect-reference-add-hw.html [ Skip ]
    5216 webkit.org/b/232705 imported/blink/css3/filters/effect-reference-on-transparent-element.html [ Skip ]
    5217 webkit.org/b/232705 imported/blink/css3/filters/effect-reference-source-alpha-hw.html [ Skip ]
    52185185webkit.org/b/232705 imported/blink/svg/filters/filter-huge-clamping.svg [ Skip ]
    5219 webkit.org/b/232705 imported/mozilla/svg/svg-effects-area-unzoomed.xhtml [ Skip ]
    5220 webkit.org/b/232705 imported/mozilla/svg/svg-effects-area-zoomed-in.xhtml [ Skip ]
    5221 webkit.org/b/232705 imported/mozilla/svg/svg-effects-area-zoomed-out.xhtml [ Skip ]
    5222 webkit.org/b/232705 imported/w3c/web-platform-tests/css/css-overflow/overflow-scroll-resize-visibility-hidden.html [ Skip ]
    5223 webkit.org/b/232705 svg/custom/feColorMatrix-values-leading-spaces.html [ Skip ]
     5186webkit.org/b/232705 imported/mozilla/svg/dynamic-filter-contents-01a.svg [ Skip ]
     5187webkit.org/b/232705 imported/mozilla/svg/filters/feComposite-2.svg [ Skip ]
     5188webkit.org/b/232705 imported/mozilla/svg/filters/feSpecularLighting-1.svg [ Skip ]
    52245189webkit.org/b/232705 svg/custom/resources-css-scaled.html [ Skip ]
     5190webkit.org/b/232705 svg/filters/feLighting-clipped.svg [ Skip ]
    52255191webkit.org/b/232705 svg/filters/big-sized-off-viewport-filter.svg [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r285617 r285618  
     12021-11-10  Said Abou-Hallawa  <said@apple.com>
     2
     3        [GPU Process] Make CSSFilter be a composite of FilterFunctions
     4        https://bugs.webkit.org/show_bug.cgi?id=232469
     5        rdar://85047148
     6
     7        Reviewed by Simon Fraser.
     8
     9        In this patch, the CSS reference filter is built as an SVGFilter and it
     10        is kept as a FilterFunction in the CSSFilter functions' list. The Filter
     11        associated with the FilterEffects of the referenced filter will be an
     12        SVGFilter instead of the root CSSFilter. This will allow having color
     13        spacing for the referenced filters different from the color spacing of
     14        CSSFilter.
     15
     16        Also this patch makes a single function for building the primitives of
     17        the SVGFilter instead of having two functions.
     18
     19        To allow operating through the SVGFilter as a FilterFunction owned by
     20        CSSFilter, the SVGFilter will have a pointer to its lastEffect.
     21
     22        * css/CSSFilterImageValue.cpp:
     23        (WebCore::CSSFilterImageValue::image):
     24        * platform/graphics/filters/Filter.h:
     25        * platform/graphics/filters/FilterEffect.cpp:
     26        (WebCore::collectEffects): Deleted.
     27        (WebCore::FilterEffect::totalNumberOfEffectInputs const): Deleted.
     28        * platform/graphics/filters/FilterEffect.h:
     29        (WebCore::FilterEffect::numberOfEffectInputs const):
     30        (WebCore::FilterEffect::setMaxEffectRect):
     31        (WebCore::FilterEffect::outsets const): Deleted.
     32        * platform/graphics/filters/FilterFunction.h:
     33        (WebCore::FilterFunction::outsets const):
     34        (WebCore::FilterFunction::clearResult):
     35        * rendering/CSSFilter.cpp:
     36        (WebCore::CSSFilter::create):
     37        (WebCore::CSSFilter::CSSFilter):
     38        (WebCore::m_hasFilterThatShouldBeRestrictedBySecurityOrigin):
     39        (WebCore::createBlurEffect):
     40        (WebCore::createBrightnessEffect):
     41        (WebCore::createContrastEffect):
     42        (WebCore::createDropShadowEffect):
     43        (WebCore::createGrayScaleEffect):
     44        (WebCore::createHueRotateEffect):
     45        (WebCore::createInvertEffect):
     46        (WebCore::createOpacityEffect):
     47        (WebCore::createSaturateEffect):
     48        (WebCore::createSepiaEffect):
     49        (WebCore::createSVGFilter):
     50        (WebCore::setupLastEffectProperties):
     51        (WebCore::CSSFilter::buildFilterFunctions):
     52        (WebCore::CSSFilter::inputContext):
     53        (WebCore::CSSFilter::allocateBackingStoreIfNeeded):
     54        (WebCore::CSSFilter::lastEffect):
     55        (WebCore::CSSFilter::determineFilterPrimitiveSubregion):
     56        (WebCore::CSSFilter::clearIntermediateResults):
     57        (WebCore::CSSFilter::apply):
     58        (WebCore::CSSFilter::output):
     59        (WebCore::CSSFilter::setSourceImageRect):
     60        (WebCore::CSSFilter::outputRect):
     61        (WebCore::CSSFilter::outsets const):
     62        (WebCore::m_sourceGraphic): Deleted.
     63        (WebCore::CSSFilter::buildReferenceFilter): Deleted.
     64        (WebCore::CSSFilter::build): Deleted.
     65        (WebCore::CSSFilter::output const): Deleted.
     66        (WebCore::CSSFilter::setMaxEffectRects): Deleted.
     67        (WebCore::CSSFilter::outputRect const): Deleted.
     68        * rendering/CSSFilter.h:
     69        * rendering/RenderLayer.cpp:
     70        (WebCore::RenderLayer::setupFilters):
     71        * rendering/RenderLayerFilters.cpp:
     72        (WebCore::RenderLayerFilters::buildFilter):
     73        (WebCore::RenderLayerFilters::beginFilterEffect):
     74        (WebCore::RenderLayerFilters::applyFilterEffect):
     75        * rendering/RenderLayerFilters.h:
     76        * rendering/svg/RenderSVGResourceFilter.cpp:
     77        (WebCore::RenderSVGResourceFilter::applyResource):
     78        (WebCore::RenderSVGResourceFilter::buildPrimitives const): Deleted.
     79        * rendering/svg/SVGRenderTreeAsText.cpp:
     80        (WebCore::writeSVGResourceContainer):
     81        * svg/graphics/filters/SVGFilter.cpp:
     82        (WebCore::SVGFilter::create):
     83        (WebCore::SVGFilter::outsets const):
     84        (WebCore::SVGFilter::clearResult):
     85        * svg/graphics/filters/SVGFilter.h:
     86        * svg/graphics/filters/SVGFilterBuilder.cpp:
     87        (WebCore::SVGFilterBuilder::setupBuiltinEffects):
     88        (WebCore::colorInterpolationForElement):
     89        (WebCore::collectEffects):
     90        (WebCore::totalNumberFilterEffects):
     91        (WebCore::SVGFilterBuilder::buildFilterEffects):
     92        (WebCore::SVGFilterBuilder::SVGFilterBuilder): Deleted.
     93        * svg/graphics/filters/SVGFilterBuilder.h:
     94
    1952021-11-10  J Pascoe  <j_pascoe@apple.com>
    296
  • trunk/Source/WebCore/css/CSSFilterImageValue.cpp

    r285597 r285618  
    117117    // Transform Image into ImageBuffer.
    118118    // FIXME (149424): This buffer should not be unconditionally unaccelerated.
    119     auto texture = ImageBuffer::create(size, RenderingMode::Unaccelerated, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
    120     if (!texture)
     119    auto renderingMode = RenderingMode::Unaccelerated;
     120    auto sourceImage = ImageBuffer::create(size, renderingMode, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8);
     121    if (!sourceImage)
    121122        return &Image::nullImage();
    122123
    123     auto imageRect = FloatRect { { }, size };
    124     texture->context().drawImage(*image, imageRect);
     124    auto sourceImageRect = FloatRect { { }, size };
     125    sourceImage->context().drawImage(*image, sourceImageRect);
    125126
    126     auto cssFilter = CSSFilter::create();
    127     cssFilter->setSourceImage(WTFMove(texture));
    128     cssFilter->setSourceImageRect(imageRect);
    129     if (!cssFilter->build(renderer, m_filterOperations, FilterConsumer::FilterFunction))
     127    auto cssFilter = CSSFilter::create(m_filterOperations, renderingMode);
     128
     129    cssFilter->setSourceImageRect(sourceImageRect);
     130    if (!cssFilter->buildFilterFunctions(renderer, m_filterOperations, FilterConsumer::FilterFunction))
    130131        return &Image::nullImage();
     132
     133    cssFilter->setSourceImage(WTFMove(sourceImage));
    131134    cssFilter->apply();
    132135
  • trunk/Source/WebCore/platform/graphics/filters/Filter.h

    r285597 r285618  
    2222#pragma once
    2323
    24 #include "AffineTransform.h"
    2524#include "FilterFunction.h"
    2625#include "FloatRect.h"
    2726#include "GraphicsTypes.h"
    2827#include "ImageBuffer.h"
     28#include "RenderingMode.h"
    2929
    3030namespace WebCore {
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp

    r285597 r285618  
    144144}
    145145
    146 static unsigned collectEffects(const FilterEffect*effect, HashSet<const FilterEffect*>& allEffects)
    147 {
    148     allEffects.add(effect);
    149     unsigned size = effect->numberOfEffectInputs();
    150     for (unsigned i = 0; i < size; ++i) {
    151         FilterEffect* in = effect->inputEffect(i);
    152         collectEffects(in, allEffects);
    153     }
    154     return allEffects.size();
    155 }
    156 
    157 unsigned FilterEffect::totalNumberOfEffectInputs() const
    158 {
    159     HashSet<const FilterEffect*> allEffects;
    160     return collectEffects(this, allEffects);
    161 }
    162 
    163146void FilterEffect::apply()
    164147{
  • trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h

    r285543 r285618  
    4949class FilterEffect : public FilterFunction {
    5050public:
    51     void clearResult();
     51    void clearResult() override;
    5252    void clearResultsRecursive();
    5353
     
    6060    FilterEffect* inputEffect(unsigned) const;
    6161    unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
    62     unsigned totalNumberOfEffectInputs() const;
    6362   
    6463    inline bool hasResult() const
     
    8483
    8584    FloatRect maxEffectRect() const { return m_maxEffectRect; }
    86     void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; } 
     85    void setMaxEffectRect(const FloatRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; }
    8786
    8887    void apply();
     
    9493
    9594    virtual void determineAbsolutePaintRect();
    96 
    97     virtual IntOutsets outsets() const { return IntOutsets(); }
    9895
    9996    enum class RepresentationType { TestOutput, Debugging };
  • trunk/Source/WebCore/platform/graphics/filters/FilterFunction.h

    r285543 r285618  
    2626#pragma once
    2727
     28#include "FloatRect.h"
     29#include "IntRectExtent.h"
    2830#include <wtf/RefCounted.h>
    2931#include <wtf/text/AtomString.h>
     
    8183    AtomString filterName() const { return filterName(m_filterType); }
    8284
     85    virtual IntOutsets outsets() const { return { }; }
     86    virtual void clearResult() { }
     87
    8388private:
    8489    Type m_filterType;
  • trunk/Source/WebCore/rendering/CSSFilter.cpp

    r285597 r285618  
    2828#include "CSSFilter.h"
    2929
    30 #include "CachedSVGDocument.h"
    31 #include "CachedSVGDocumentReference.h"
    32 #include "ElementIterator.h"
    3330#include "FEColorMatrix.h"
    3431#include "FEComponentTransfer.h"
     
    3936#include "Logging.h"
    4037#include "ReferencedSVGResources.h"
    41 #include "RenderLayer.h"
    42 #include "SVGElement.h"
     38#include "SVGFilter.h"
    4339#include "SVGFilterBuilder.h"
    4440#include "SVGFilterElement.h"
    45 #include "SVGFilterPrimitiveStandardAttributes.h"
    46 #include "SourceAlpha.h"
    4741#include "SourceGraphic.h"
    48 #include <algorithm>
    49 #include <wtf/MathExtras.h>
    5042
    5143#if USE(DIRECT2D)
     
    5547namespace WebCore {
    5648
    57 Ref<CSSFilter> CSSFilter::create(float scaleFactor)
    58 {
    59     return adoptRef(*new CSSFilter(scaleFactor));
    60 }
    61 
    62 CSSFilter::CSSFilter(float scaleFactor)
     49RefPtr<CSSFilter> CSSFilter::create(const FilterOperations& operations, RenderingMode renderingMode, float scaleFactor)
     50{
     51    bool hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
     52    bool hasFilterThatShouldBeRestrictedBySecurityOrigin = operations.hasFilterThatShouldBeRestrictedBySecurityOrigin();
     53
     54    auto filter = adoptRef(*new CSSFilter(hasFilterThatMovesPixels, hasFilterThatShouldBeRestrictedBySecurityOrigin, scaleFactor));
     55
     56    filter->setRenderingMode(renderingMode);
     57    return filter;
     58}
     59
     60CSSFilter::CSSFilter(bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin, float scaleFactor)
    6361    : Filter(Filter::Type::CSSFilter, FloatSize { scaleFactor, scaleFactor })
    64     , m_sourceGraphic(SourceGraphic::create(*this))
    65 {
    66 }
    67 
    68 GraphicsContext* CSSFilter::inputContext()
    69 {
    70     return sourceImage() ? &sourceImage()->context() : nullptr;
    71 }
    72 
    73 RefPtr<FilterEffect> CSSFilter::buildReferenceFilter(RenderElement& renderer, FilterEffect& previousEffect, ReferenceFilterOperation& filterOperation)
    74 {
    75     auto* filterElement = renderer.ensureReferencedSVGResources().referencedFilterElement(renderer.document(), filterOperation);
     62    , m_hasFilterThatMovesPixels(hasFilterThatMovesPixels)
     63    , m_hasFilterThatShouldBeRestrictedBySecurityOrigin(hasFilterThatShouldBeRestrictedBySecurityOrigin)
     64{
     65}
     66
     67static RefPtr<FilterEffect> createBlurEffect(CSSFilter& filter, const BlurFilterOperation& blurOperation, FilterConsumer consumer)
     68{
     69    float stdDeviation = floatValueForLength(blurOperation.stdDeviation(), 0);
     70    return FEGaussianBlur::create(filter, stdDeviation, stdDeviation, consumer == FilterConsumer::FilterProperty ? EDGEMODE_NONE : EDGEMODE_DUPLICATE);
     71}
     72
     73static RefPtr<FilterEffect> createBrightnessEffect(CSSFilter& filter, const BasicComponentTransferFilterOperation& componentTransferOperation)
     74{
     75    ComponentTransferFunction transferFunction;
     76    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
     77    transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation.amount());
     78    transferFunction.intercept = 0;
     79
     80    ComponentTransferFunction nullFunction;
     81    return FEComponentTransfer::create(filter, transferFunction, transferFunction, transferFunction, nullFunction);
     82}
     83
     84static RefPtr<FilterEffect> createContrastEffect(CSSFilter& filter, const BasicComponentTransferFilterOperation& componentTransferOperation)
     85{
     86    ComponentTransferFunction transferFunction;
     87    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
     88    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
     89    transferFunction.slope = amount;
     90    transferFunction.intercept = -0.5 * amount + 0.5;
     91
     92    ComponentTransferFunction nullFunction;
     93    return FEComponentTransfer::create(filter, transferFunction, transferFunction, transferFunction, nullFunction);
     94}
     95
     96static RefPtr<FilterEffect> createDropShadowEffect(CSSFilter& filter, const DropShadowFilterOperation& dropShadowOperation)
     97{
     98    float std = dropShadowOperation.stdDeviation();
     99    return FEDropShadow::create(filter, std, std, dropShadowOperation.x(), dropShadowOperation.y(), dropShadowOperation.color(), 1);
     100}
     101
     102static RefPtr<FilterEffect> createGrayScaleEffect(CSSFilter& filter, const BasicColorMatrixFilterOperation& colorMatrixOperation)
     103{
     104    double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);
     105
     106    // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
     107    // for information on parameters.
     108
     109    Vector<float> inputParameters {
     110        narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount),
     111        narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
     112        narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
     113        0,
     114        0,
     115
     116        narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
     117        narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount),
     118        narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
     119        0,
     120        0,
     121
     122        narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
     123        narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
     124        narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount),
     125        0,
     126        0,
     127
     128        0,
     129        0,
     130        0,
     131        1,
     132        0,
     133    };
     134
     135    return FEColorMatrix::create(filter, FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
     136}
     137
     138static RefPtr<FilterEffect> createHueRotateEffect(CSSFilter& filter, const BasicColorMatrixFilterOperation& colorMatrixOperation)
     139{
     140    Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
     141    return FEColorMatrix::create(filter, FECOLORMATRIX_TYPE_HUEROTATE, WTFMove(inputParameters));
     142}
     143
     144static RefPtr<FilterEffect> createInvertEffect(CSSFilter& filter, const BasicComponentTransferFilterOperation& componentTransferOperation)
     145{
     146    ComponentTransferFunction transferFunction;
     147    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
     148    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
     149    transferFunction.slope = 1 - 2 * amount;
     150    transferFunction.intercept = amount;
     151
     152    ComponentTransferFunction nullFunction;
     153    return FEComponentTransfer::create(filter, transferFunction, transferFunction, transferFunction, nullFunction);
     154}
     155
     156static RefPtr<FilterEffect> createOpacityEffect(CSSFilter& filter, const BasicComponentTransferFilterOperation& componentTransferOperation)
     157{
     158    ComponentTransferFunction transferFunction;
     159    transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
     160    float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
     161    transferFunction.slope = amount;
     162    transferFunction.intercept = 0;
     163
     164    ComponentTransferFunction nullFunction;
     165    return FEComponentTransfer::create(filter, nullFunction, nullFunction, nullFunction, transferFunction);
     166}
     167
     168static RefPtr<FilterEffect> createSaturateEffect(CSSFilter& filter, const BasicColorMatrixFilterOperation& colorMatrixOperation)
     169{
     170    Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
     171    return FEColorMatrix::create(filter, FECOLORMATRIX_TYPE_SATURATE, WTFMove(inputParameters));
     172}
     173
     174static RefPtr<FilterEffect> createSepiaEffect(CSSFilter& filter, const BasicColorMatrixFilterOperation& colorMatrixOperation)
     175{
     176    double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);
     177
     178    // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
     179    // for information on parameters.
     180
     181    Vector<float> inputParameters {
     182        narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount),
     183        narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount),
     184        narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount),
     185        0,
     186        0,
     187
     188        narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount),
     189        narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount),
     190        narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount),
     191        0,
     192        0,
     193
     194        narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount),
     195        narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount),
     196        narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount),
     197        0,
     198        0,
     199
     200        0,
     201        0,
     202        0,
     203        1,
     204        0,
     205    };
     206
     207    return FEColorMatrix::create(filter, FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
     208}
     209
     210static RefPtr<SVGFilter> createSVGFilter(CSSFilter& filter, const ReferenceFilterOperation& filterOperation, RenderElement& renderer, FilterEffect& previousEffect)
     211{
     212    auto& referencedSVGResources = renderer.ensureReferencedSVGResources();
     213    auto* filterElement = referencedSVGResources.referencedFilterElement(renderer.document(), filterOperation);
     214
    76215    if (!filterElement) {
    77         LOG_WITH_STREAM(Filters, stream << "CSSFilter " << this << " buildReferenceFilter: failed to find filter renderer, adding pending resource " << filterOperation.fragment());
     216        LOG_WITH_STREAM(Filters, stream << " buildReferenceFilter: failed to find filter renderer, adding pending resource " << filterOperation.fragment());
    78217        // Although we did not find the referenced filter, it might exist later in the document.
    79218        // FIXME: This skips anonymous RenderObjects. <https://webkit.org/b/131085>
    80219        // FIXME: Unclear if this does anything.
    81         if (auto* element = renderer.element())
    82             renderer.document().accessSVGExtensions().addPendingResource(filterOperation.fragment(), *element);
    83220        return nullptr;
    84221    }
    85222
    86     auto builder = makeUnique<SVGFilterBuilder>(&previousEffect);
    87 
    88     RefPtr<FilterEffect> effect;
    89     Vector<Ref<FilterEffect>> referenceEffects;
    90 
    91     for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(*filterElement)) {
    92         effect = effectElement.build(builder.get(), *this);
    93         if (!effect) {
    94             LOG_WITH_STREAM(Filters, stream << "CSSFilter " << this << " buildReferenceFilter: failed to build effect from " << effectElement);
    95             return nullptr;
    96         }
    97 
    98         effectElement.setStandardAttributes(effect.get());
    99         if (effectElement.renderer()) {
    100 #if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
    101             effect->setOperatingColorSpace(effectElement.renderer()->style().svgStyle().colorInterpolationFilters() == ColorInterpolation::LinearRGB ? DestinationColorSpace::LinearSRGB() : DestinationColorSpace::SRGB());
    102 #else
    103             effect->setOperatingColorSpace(DestinationColorSpace::SRGB());
    104 #endif
    105         }
    106         builder->add(effectElement.result(), effect);
    107         referenceEffects.append(*effect);
    108     }
     223    SVGFilterBuilder builder;
     224    return SVGFilter::create(*filterElement, builder, filter.filterScale(), filter.sourceImageRect(), filter.filterRegion(), previousEffect);
     225}
     226
     227static void setupLastEffectProperties(FilterEffect& effect, FilterConsumer consumer)
     228{
     229    // Unlike SVG Filters and CSSFilterImages, filter functions on the filter
     230    // property applied here should not clip to their primitive subregions.
     231    effect.setClipsToBounds(consumer == FilterConsumer::FilterFunction);
     232    effect.setOperatingColorSpace(DestinationColorSpace::SRGB());
     233}
     234
     235bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperations& operations, FilterConsumer consumer)
     236{
     237    m_functions.clear();
     238    m_outsets = { };
     239
     240    RefPtr<FilterEffect> previousEffect = SourceGraphic::create(*this);
     241    m_functions.append({ *previousEffect });
     242
     243    RefPtr<SVGFilter> filter;
    109244   
    110     m_effects.appendVector(WTFMove(referenceEffects));
    111     return effect;
    112 }
    113 
    114 bool CSSFilter::build(RenderElement& renderer, const FilterOperations& operations, FilterConsumer consumer)
    115 {
    116     m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
    117     m_hasFilterThatShouldBeRestrictedBySecurityOrigin = operations.hasFilterThatShouldBeRestrictedBySecurityOrigin();
    118 
    119     m_effects.clear();
    120     m_outsets = { };
    121 
    122     RefPtr<FilterEffect> previousEffect = m_sourceGraphic.ptr();
    123245    for (auto& operation : operations.operations()) {
    124246        RefPtr<FilterEffect> effect;
    125         auto& filterOperation = *operation;
    126         switch (filterOperation.type()) {
    127         case FilterOperation::REFERENCE: {
    128             auto& referenceOperation = downcast<ReferenceFilterOperation>(filterOperation);
    129             effect = buildReferenceFilter(renderer, *previousEffect, referenceOperation);
    130             break;
    131         }
    132         case FilterOperation::GRAYSCALE: {
    133             auto& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation);
    134             double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);
    135 
    136             // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
    137             // for information on parameters.
    138 
    139             Vector<float> inputParameters {
    140                 narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount),
    141                 narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
    142                 narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
    143                 0,
    144                 0,
    145 
    146                 narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
    147                 narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount),
    148                 narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount),
    149                 0,
    150                 0,
    151 
    152                 narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount),
    153                 narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount),
    154                 narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount),
    155                 0,
    156                 0,
    157 
    158                 0,
    159                 0,
    160                 0,
    161                 1,
    162                 0,
    163             };
    164 
    165             effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
    166             break;
    167         }
    168         case FilterOperation::SEPIA: {
    169             auto& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation);
    170             double oneMinusAmount = clampTo(1 - colorMatrixOperation.amount(), 0.0, 1.0);
    171 
    172             // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
    173             // for information on parameters.
    174 
    175             Vector<float> inputParameters {
    176                 narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount),
    177                 narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount),
    178                 narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount),
    179                 0,
    180                 0,
    181 
    182                 narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount),
    183                 narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount),
    184                 narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount),
    185                 0,
    186                 0,
    187 
    188                 narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount),
    189                 narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount),
    190                 narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount),
    191                 0,
    192                 0,
    193 
    194                 0,
    195                 0,
    196                 0,
    197                 1,
    198                 0,
    199             };
    200 
    201             effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_MATRIX, WTFMove(inputParameters));
    202             break;
    203         }
    204         case FilterOperation::SATURATE: {
    205             auto& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation);
    206             Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
    207             effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_SATURATE, WTFMove(inputParameters));
    208             break;
    209         }
    210         case FilterOperation::HUE_ROTATE: {
    211             auto& colorMatrixOperation = downcast<BasicColorMatrixFilterOperation>(filterOperation);
    212             Vector<float> inputParameters { narrowPrecisionToFloat(colorMatrixOperation.amount()) };
    213             effect = FEColorMatrix::create(*this, FECOLORMATRIX_TYPE_HUEROTATE, WTFMove(inputParameters));
    214             break;
    215         }
    216         case FilterOperation::INVERT: {
    217             auto& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation);
    218             ComponentTransferFunction transferFunction;
    219             transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    220             float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    221             transferFunction.slope = 1 - 2 * amount;
    222             transferFunction.intercept = amount;
    223 
    224             ComponentTransferFunction nullFunction;
    225             effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction);
    226             break;
    227         }
     247
     248        switch (operation->type()) {
    228249        case FilterOperation::APPLE_INVERT_LIGHTNESS:
    229250            ASSERT_NOT_REACHED(); // APPLE_INVERT_LIGHTNESS is only used in -apple-color-filter.
    230251            break;
    231         case FilterOperation::OPACITY: {
    232             auto& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation);
    233             ComponentTransferFunction transferFunction;
    234             transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    235             float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    236             transferFunction.slope = amount;
    237             transferFunction.intercept = 0;
    238 
    239             ComponentTransferFunction nullFunction;
    240             effect = FEComponentTransfer::create(*this, nullFunction, nullFunction, nullFunction, transferFunction);
     252
     253        case FilterOperation::BLUR:
     254            effect = createBlurEffect(*this, downcast<BlurFilterOperation>(*operation), consumer);
     255            break;
     256
     257        case FilterOperation::BRIGHTNESS:
     258            effect = createBrightnessEffect(*this, downcast<BasicComponentTransferFilterOperation>(*operation));
     259            break;
     260
     261        case FilterOperation::CONTRAST:
     262            effect = createContrastEffect(*this, downcast<BasicComponentTransferFilterOperation>(*operation));
     263            break;
     264
     265        case FilterOperation::DROP_SHADOW:
     266            effect = createDropShadowEffect(*this, downcast<DropShadowFilterOperation>(*operation));
     267            break;
     268
     269        case FilterOperation::GRAYSCALE:
     270            effect = createGrayScaleEffect(*this, downcast<BasicColorMatrixFilterOperation>(*operation));
     271            break;
     272
     273        case FilterOperation::HUE_ROTATE:
     274            effect = createHueRotateEffect(*this, downcast<BasicColorMatrixFilterOperation>(*operation));
     275            break;
     276
     277        case FilterOperation::INVERT:
     278            effect = createInvertEffect(*this, downcast<BasicComponentTransferFilterOperation>(*operation));
     279            break;
     280
     281        case FilterOperation::OPACITY:
     282            effect = createOpacityEffect(*this, downcast<BasicComponentTransferFilterOperation>(*operation));
     283            break;
     284
     285        case FilterOperation::SATURATE:
     286            effect = createSaturateEffect(*this, downcast<BasicColorMatrixFilterOperation>(*operation));
     287            break;
     288
     289        case FilterOperation::SEPIA:
     290            effect = createSepiaEffect(*this, downcast<BasicColorMatrixFilterOperation>(*operation));
     291            break;
     292
     293        case FilterOperation::REFERENCE:
     294            filter = createSVGFilter(*this, downcast<ReferenceFilterOperation>(*operation), renderer, *previousEffect);
     295            effect = nullptr;
     296            break;
     297
     298        default:
    241299            break;
    242300        }
    243         case FilterOperation::BRIGHTNESS: {
    244             auto& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation);
    245             ComponentTransferFunction transferFunction;
    246             transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    247             transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation.amount());
    248             transferFunction.intercept = 0;
    249 
    250             ComponentTransferFunction nullFunction;
    251             effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction);
    252             break;
     301
     302        if (filter) {
     303            effect = filter->lastEffect();
     304            setupLastEffectProperties(*effect, consumer);
     305            m_functions.append(filter.releaseNonNull());
     306            previousEffect = WTFMove(effect);
     307            continue;
    253308        }
    254         case FilterOperation::CONTRAST: {
    255             auto& componentTransferOperation = downcast<BasicComponentTransferFilterOperation>(filterOperation);
    256             ComponentTransferFunction transferFunction;
    257             transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
    258             float amount = narrowPrecisionToFloat(componentTransferOperation.amount());
    259             transferFunction.slope = amount;
    260             transferFunction.intercept = -0.5 * amount + 0.5;
    261            
    262             ComponentTransferFunction nullFunction;
    263             effect = FEComponentTransfer::create(*this, transferFunction, transferFunction, transferFunction, nullFunction);
    264             break;
    265         }
    266         case FilterOperation::BLUR: {
    267             auto& blurOperation = downcast<BlurFilterOperation>(filterOperation);
    268             float stdDeviation = floatValueForLength(blurOperation.stdDeviation(), 0);
    269             effect = FEGaussianBlur::create(*this, stdDeviation, stdDeviation, consumer == FilterConsumer::FilterProperty ? EDGEMODE_NONE : EDGEMODE_DUPLICATE);
    270             break;
    271         }
    272         case FilterOperation::DROP_SHADOW: {
    273             auto& dropShadowOperation = downcast<DropShadowFilterOperation>(filterOperation);
    274             effect = FEDropShadow::create(*this, dropShadowOperation.stdDeviation(), dropShadowOperation.stdDeviation(),
    275                 dropShadowOperation.x(), dropShadowOperation.y(), dropShadowOperation.color(), 1);
    276             break;
    277         }
    278         default:
    279             break;
    280         }
    281309
    282310        if (effect) {
    283             // Unlike SVG Filters and CSSFilterImages, filter functions on the filter
    284             // property applied here should not clip to their primitive subregions.
    285             effect->setClipsToBounds(consumer == FilterConsumer::FilterFunction);
    286             effect->setOperatingColorSpace(DestinationColorSpace::SRGB());
    287            
    288             if (filterOperation.type() != FilterOperation::REFERENCE) {
    289                 effect->inputEffects() = { WTFMove(previousEffect) };
    290                 m_effects.append(*effect);
    291             }
     311            setupLastEffectProperties(*effect, consumer);
     312            effect->inputEffects() = { WTFMove(previousEffect) };
     313            m_functions.append({ *effect });
    292314            previousEffect = WTFMove(effect);
    293315        }
     
    295317
    296318    // If we didn't make any effects, tell our caller we are not valid.
    297     if (m_effects.isEmpty())
     319    if (m_functions.isEmpty())
    298320        return false;
    299321
    300     m_effects.shrinkToFit();
    301 
    302     setMaxEffectRects(sourceImageRect());
     322    m_functions.shrinkToFit();
     323
    303324#if USE(CORE_IMAGE)
    304325    if (!m_filterRenderer)
    305         m_filterRenderer = FilterEffectRenderer::tryCreate(renderer.settings().coreImageAcceleratedFilterRenderEnabled(), m_effects.last().get());
     326        m_filterRenderer = FilterEffectRenderer::tryCreate(renderer.settings().coreImageAcceleratedFilterRenderEnabled(), *lastEffect());
    306327#endif
    307328    return true;
     329}
     330
     331GraphicsContext* CSSFilter::inputContext()
     332{
     333    return sourceImage() ? &sourceImage()->context() : nullptr;
    308334}
    309335
     
    338364        setSourceImage(ImageBuffer::create(logicalSize, mode, 1, DestinationColorSpace::SRGB(), PixelFormat::BGRA8));
    339365#endif
    340     }
     366        if (auto context = inputContext())
     367            context->scale(filterScale());
     368    }
     369
    341370    m_graphicsBufferAttached = true;
    342371}
    343372
     373RefPtr<FilterEffect> CSSFilter::lastEffect()
     374{
     375    if (m_functions.isEmpty())
     376        return nullptr;
     377
     378    auto& function = m_functions.last();
     379    if (function->isSVGFilter())
     380        return downcast<SVGFilter>(function.ptr())->lastEffect();
     381
     382    return downcast<FilterEffect>(function.ptr());
     383}
     384
    344385void CSSFilter::determineFilterPrimitiveSubregion()
    345386{
    346     auto& lastEffect = m_effects.last().get();
    347     lastEffect.determineFilterPrimitiveSubregion();
    348     FloatRect subRegion = lastEffect.maxEffectRect();
     387    auto effect = lastEffect();
     388    effect->determineFilterPrimitiveSubregion();
     389    FloatRect subRegion = effect->maxEffectRect();
    349390    // At least one FilterEffect has a too big image size, recalculate the effect sizes with new scale factors.
    350391    FloatSize filterScale { 1, 1 };
    351392    if (ImageBuffer::sizeNeedsClamping(subRegion.size(), filterScale)) {
    352393        setFilterScale(filterScale);
    353         lastEffect.determineFilterPrimitiveSubregion();
     394        effect->determineFilterPrimitiveSubregion();
    354395    }
    355396}
     
    357398void CSSFilter::clearIntermediateResults()
    358399{
    359     m_sourceGraphic->clearResult();
    360     for (auto& effect : m_effects)
    361         effect->clearResult();
     400    for (auto& function : m_functions)
     401        function->clearResult();
    362402}
    363403
    364404void CSSFilter::apply()
    365405{
    366     auto& effect = m_effects.last().get();
     406    auto effect = lastEffect();
    367407    if (m_filterRenderer) {
    368         m_filterRenderer->applyEffects(effect);
     408        m_filterRenderer->applyEffects(*effect);
    369409        if (m_filterRenderer->hasResult()) {
    370             effect.transformResultColorSpace(DestinationColorSpace::SRGB());
     410            effect->transformResultColorSpace(DestinationColorSpace::SRGB());
    371411            return;
    372412        }
    373413    }
    374     effect.apply();
    375     effect.transformResultColorSpace(DestinationColorSpace::SRGB());
     414    effect->apply();
     415    effect->transformResultColorSpace(DestinationColorSpace::SRGB());
    376416}
    377417
     
    386426}
    387427
    388 ImageBuffer* CSSFilter::output() const
     428ImageBuffer* CSSFilter::output()
    389429{
    390430    if (m_filterRenderer && m_filterRenderer->hasResult())
    391431        return m_filterRenderer->output();
    392432   
    393     return m_effects.last()->imageBufferResult();
     433    return lastEffect()->imageBufferResult();
    394434}
    395435
    396436void CSSFilter::setSourceImageRect(const FloatRect& sourceImageRect)
    397437{
     438    auto scaledSourceImageRect = sourceImageRect;
     439    scaledSourceImageRect.scale(filterScale());
     440
    398441    Filter::setFilterRegion(sourceImageRect);
    399     Filter::setSourceImageRect(sourceImageRect);
    400     setMaxEffectRects(sourceImageRect);
     442    Filter::setSourceImageRect(scaledSourceImageRect);
     443
     444    for (auto& function : m_functions) {
     445        if (function->isSVGFilter()) {
     446            downcast<SVGFilter>(function.ptr())->setFilterRegion(sourceImageRect);
     447            downcast<SVGFilter>(function.ptr())->setSourceImageRect(scaledSourceImageRect);
     448        }
     449    }
     450
    401451    m_graphicsBufferAttached = false;
    402452}
    403453
    404 void CSSFilter::setMaxEffectRects(const FloatRect& effectRect)
    405 {
    406     for (auto& effect : m_effects)
    407         effect->setMaxEffectRect(effectRect);
    408 }
    409 
    410 IntRect CSSFilter::outputRect() const
    411 {
    412     auto& lastEffect = m_effects.last().get();
    413    
    414     if (lastEffect.hasResult() || (m_filterRenderer && m_filterRenderer->hasResult()))
    415         return lastEffect.requestedRegionOfInputPixelBuffer(IntRect { filterRegion() });
    416    
     454IntRect CSSFilter::outputRect()
     455{
     456    auto effect = lastEffect();
     457
     458    if (effect->hasResult() || (m_filterRenderer && m_filterRenderer->hasResult()))
     459        return effect->requestedRegionOfInputPixelBuffer(IntRect { filterRegion() });
     460
    417461    return { };
    418462}
     
    426470        return m_outsets;
    427471
    428     for (auto& effect : m_effects)
    429         m_outsets += effect->outsets();
     472    for (auto& function : m_functions)
     473        m_outsets += function->outsets();
    430474    return m_outsets;
    431475}
  • trunk/Source/WebCore/rendering/CSSFilter.h

    r285597 r285618  
    4545class CSSFilter final : public Filter {
    4646    WTF_MAKE_FAST_ALLOCATED;
    47     friend class RenderLayerFilters;
    4847public:
    49     static Ref<CSSFilter> create(float scaleFactor = 1);
    50 
    51     ImageBuffer* output() const;
     48    static RefPtr<CSSFilter> create(const FilterOperations&, RenderingMode, float scaleFactor = 1);
    5249
    5350    void setSourceImageRect(const FloatRect&);
    54     bool build(RenderElement&, const FilterOperations&, FilterConsumer);
    55     void clearIntermediateResults();
    56     void apply();
     51    bool buildFilterFunctions(RenderElement&, const FilterOperations&, FilterConsumer);
     52    void determineFilterPrimitiveSubregion();
    5753
    5854    bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
    5955    bool hasFilterThatShouldBeRestrictedBySecurityOrigin() const { return m_hasFilterThatShouldBeRestrictedBySecurityOrigin; }
    6056
    61     void determineFilterPrimitiveSubregion();
    62     IntOutsets outsets() const;
     57    RefPtr<FilterEffect> lastEffect();
     58    GraphicsContext* inputContext();
     59    IntOutsets outsets() const override;
    6360
    64 private:
    65     CSSFilter(float scaleFactor);
     61    void clearIntermediateResults();
     62    void apply();
    6663
    67     RefPtr<FilterEffect> buildReferenceFilter(RenderElement&, FilterEffect& previousEffect, ReferenceFilterOperation&);
    68 
    69     void setMaxEffectRects(const FloatRect&);
    70 
    71     GraphicsContext* inputContext();
     64    ImageBuffer* output();
    7265
    7366    bool updateBackingStoreRect(const FloatRect& filterRect);
    7467    void allocateBackingStoreIfNeeded(const GraphicsContext&);
    7568
    76     IntRect outputRect() const;
     69    IntRect outputRect();
    7770
    7871    LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
    7972
    80     Vector<Ref<FilterEffect>> m_effects;
    81     Ref<SourceGraphic> m_sourceGraphic;
    82 
    83     mutable IntOutsets m_outsets;
     73private:
     74    CSSFilter(bool hasFilterThatMovesPixels, bool hasFilterThatShouldBeRestrictedBySecurityOrigin, float scaleFactor);
    8475
    8576    bool m_graphicsBufferAttached { false };
    8677    bool m_hasFilterThatMovesPixels { false };
    8778    bool m_hasFilterThatShouldBeRestrictedBySecurityOrigin { false };
    88    
     79
     80    Vector<Ref<FilterFunction>> m_functions;
     81
     82    mutable IntOutsets m_outsets;
     83
    8984    std::unique_ptr<FilterEffectRenderer> m_filterRenderer;
    9085};
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r285583 r285618  
    32433243    auto rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, offsetFromRoot, { });
    32443244
    3245     GraphicsContext* filterContext = paintingFilters->beginFilterEffect(destinationContext, enclosingIntRect(rootRelativeBounds), enclosingIntRect(paintingInfo.paintDirtyRect), enclosingIntRect(filterRepaintRect));
     3245    GraphicsContext* filterContext = paintingFilters->beginFilterEffect(destinationContext, renderer(), enclosingIntRect(rootRelativeBounds), enclosingIntRect(paintingInfo.paintDirtyRect), enclosingIntRect(filterRepaintRect));
    32463246    if (!filterContext)
    32473247        return nullptr;
  • trunk/Source/WebCore/rendering/RenderLayerFilters.cpp

    r285597 r285618  
    119119void RenderLayerFilters::buildFilter(RenderElement& renderer, float scaleFactor, RenderingMode renderingMode)
    120120{
    121     // FIXME: this rebuilds the entire effects chain even if the filter style didn't change.
    122     m_filter = CSSFilter::create(scaleFactor);
    123     m_filter->setRenderingMode(renderingMode);
    124 
    125121    // If the filter fails to build, remove it from the layer. It will still attempt to
    126122    // go through regular processing (e.g. compositing), but never apply anything.
    127     if (!m_filter->build(renderer, renderer.style().filter(), FilterConsumer::FilterProperty))
    128         m_filter = nullptr;
    129 }
    130 
    131 GraphicsContext* RenderLayerFilters::beginFilterEffect(GraphicsContext& destinationContext, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
     123    // FIXME: this rebuilds the entire effects chain even if the filter style didn't change.
     124    m_filter = CSSFilter::create(renderer.style().filter(), renderingMode, scaleFactor);
     125}
     126
     127GraphicsContext* RenderLayerFilters::beginFilterEffect(GraphicsContext& destinationContext, RenderElement& renderer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
    132128{
    133129    if (!m_filter)
     
    140136
    141137    bool hasUpdatedBackingStore = filter.updateBackingStoreRect(filterSourceRect);
     138
     139    // FIXME: this call should be moved to CSSFilter::create() when FilterEffect does not store its geometry.
     140    if (hasUpdatedBackingStore || !m_filter->lastEffect()) {
     141        // If the filter fails to build, remove it from the layer. It will still attempt to
     142        // go through regular processing (e.g. compositing), but never apply anything.
     143        if (!m_filter->buildFilterFunctions(renderer, renderer.style().filter(), FilterConsumer::FilterProperty))
     144            return nullptr;
     145    }
     146   
    142147    if (!filter.hasFilterThatMovesPixels())
    143148        m_repaintRect = dirtyRect;
     
    185190    destRect.move(m_paintOffset.x(), m_paintOffset.y());
    186191
    187     if (auto* outputBuffer = filter.output())
     192    if (auto* outputBuffer = filter.output()) {
     193        destinationContext.scale({ 1 / filter.filterScale().width(), 1 / filter.filterScale().height() });
    188194        destinationContext.drawImageBuffer(*outputBuffer, snapRectToDevicePixels(destRect, m_layer.renderer().document().deviceScaleFactor()));
     195        destinationContext.scale(filter.filterScale());
     196    }
    189197
    190198    filter.clearIntermediateResults();
  • trunk/Source/WebCore/rendering/RenderLayerFilters.h

    r261597 r285618  
    6464    LayoutRect repaintRect() const { return m_repaintRect; }
    6565
    66     GraphicsContext* beginFilterEffect(GraphicsContext& destinationContext, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
     66    GraphicsContext* beginFilterEffect(GraphicsContext& destinationContext, RenderElement&, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
    6767    void applyFilterEffect(GraphicsContext& destinationContext);
    6868
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp

    r285597 r285618  
    8383}
    8484
    85 std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter& filter) const
    86 {
    87     static const unsigned maxCountChildNodes = 200;
    88     if (filterElement().countChildNodes() > maxCountChildNodes)
    89         return nullptr;
    90 
    91     FloatRect targetBoundingBox = filter.targetBoundingBox();
    92 
    93     // Add effects to the builder
    94     auto builder = makeUnique<SVGFilterBuilder>(SourceGraphic::create(filter));
    95     builder->setPrimitiveUnits(filterElement().primitiveUnits());
    96     builder->setTargetBoundingBox(targetBoundingBox);
    97    
    98     for (auto& element : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement())) {
    99         auto effect = element.build(builder.get(), filter);
    100         if (!effect) {
    101             builder->clearEffects();
    102             return nullptr;
    103         }
    104         builder->appendEffectToEffectReferences(effect.copyRef(), element.renderer());
    105         element.setStandardAttributes(effect.get());
    106         effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&element, filterElement().primitiveUnits(), targetBoundingBox));
    107         if (element.renderer()) {
    108 #if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
    109             effect->setOperatingColorSpace(element.renderer()->style().svgStyle().colorInterpolationFilters() == ColorInterpolation::LinearRGB ? DestinationColorSpace::LinearSRGB() : DestinationColorSpace::SRGB());
    110 #else
    111             effect->setOperatingColorSpace(DestinationColorSpace::SRGB());
    112 #endif
    113         }
    114         builder->add(element.result(), WTFMove(effect));
    115     }
    116     return builder;
    117 }
    118 
    11985bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, OptionSet<RenderSVGResourceMode> resourceMode)
    12086{
     
    156122
    157123    // Create the SVGFilter object.
    158     bool primitiveBoundingBoxMode = filterElement().primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
    159     filterData->filter = SVGFilter::create(filterScale, absoluteDrawingRegion, filterData->boundaries, targetBoundingBox, primitiveBoundingBoxMode);
    160 
    161     // Create all relevant filter primitives.
    162     filterData->builder = buildPrimitives(*filterData->filter);
    163     if (!filterData->builder)
    164         return false;
    165 
    166     static const unsigned maxTotalOfEffectInputs = 100;
    167     FilterEffect* lastEffect = filterData->builder->lastEffect();
    168     if (!lastEffect || lastEffect->totalNumberOfEffectInputs() > maxTotalOfEffectInputs)
    169         return false;
     124    filterData->builder = makeUnique<SVGFilterBuilder>();
     125    filterData->filter = SVGFilter::create(filterElement(), *filterData->builder, filterScale, absoluteDrawingRegion, filterData->boundaries, targetBoundingBox);
     126    if (!filterData->filter)
     127        return false;
     128
     129    auto lastEffect = filterData->builder->lastEffect();
     130    ASSERT(lastEffect);
    170131
    171132    LOG_WITH_STREAM(Filters, stream << "RenderSVGResourceFilter::applyResource\n" << *filterData->builder->lastEffect());
  • trunk/Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp

    r285597 r285618  
    434434        FloatRect dummyRect;
    435435        FloatSize dummyScale(1, 1);
    436         auto dummyFilter = SVGFilter::create(dummyScale, dummyRect, dummyRect, dummyRect, true);
    437         if (auto builder = filter.buildPrimitives(dummyFilter.get())) {
     436        SVGFilterBuilder builder;
     437        auto dummyFilter = SVGFilter::create(filter.filterElement(), builder, dummyScale, dummyRect, dummyRect, dummyRect);
     438        if (dummyFilter) {
    438439            TextStream::IndentScope indentScope(ts);
    439440
    440             if (FilterEffect* lastEffect = builder->lastEffect())
     441            if (auto lastEffect = dummyFilter->lastEffect())
    441442                lastEffect->externalRepresentation(ts);
    442443        }
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilter.cpp

    r285597 r285618  
    2323#include "SVGFilter.h"
    2424
     25#include "SVGFilterBuilder.h"
     26#include "SVGFilterElement.h"
     27#include "SourceGraphic.h"
     28
    2529namespace WebCore {
     30
     31RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, FilterEffect& previousEffect)
     32{
     33    return create(filterElement, builder, filterScale, sourceImageRect, filterRegion, filterRegion, &previousEffect);
     34}
     35
     36RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox)
     37{
     38    return create(filterElement, builder, filterScale, sourceImageRect, filterRegion, targetBoundingBox, nullptr);
     39}
     40
     41RefPtr<SVGFilter> SVGFilter::create(SVGFilterElement& filterElement, SVGFilterBuilder& builder, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, FilterEffect* previousEffect)
     42{
     43    bool primitiveBoundingBoxMode = filterElement.primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
     44
     45    auto filter = adoptRef(*new SVGFilter(filterScale, sourceImageRect, filterRegion, targetBoundingBox, primitiveBoundingBoxMode));
     46
     47    if (!previousEffect)
     48        builder.setupBuiltinEffects(SourceGraphic::create(filter));
     49    else
     50        builder.setupBuiltinEffects({ *previousEffect });
     51
     52    builder.setTargetBoundingBox(targetBoundingBox);
     53    builder.setPrimitiveUnits(filterElement.primitiveUnits());
     54
     55    auto lastEffect = builder.buildFilterEffects(filter, filterElement);
     56    if (!lastEffect)
     57        return nullptr;
     58
     59    filter->setLastEffect(WTFMove(lastEffect));
     60    return filter;
     61}
    2662
    2763SVGFilter::SVGFilter(const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, bool effectBBoxMode)
     
    4076}
    4177
    42 Ref<SVGFilter> SVGFilter::create(const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, bool effectBBoxMode)
     78IntOutsets SVGFilter::outsets() const
    4379{
    44     return adoptRef(*new SVGFilter(filterScale, sourceImageRect, filterRegion, targetBoundingBox, effectBBoxMode));
     80    return m_lastEffect->outsets();
     81}
     82
     83void SVGFilter::clearResult()
     84{
     85    m_lastEffect->clearResultsRecursive();
    4586}
    4687
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilter.h

    r285597 r285618  
    2828namespace WebCore {
    2929
     30class SVGFilterBuilder;
     31class SVGFilterElement;
     32
    3033class SVGFilter final : public Filter {
    3134public:
    32     static Ref<SVGFilter> create(const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode);
     35    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, FilterEffect& previousEffect);
     36    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox);
     37    static RefPtr<SVGFilter> create(SVGFilterElement&, SVGFilterBuilder&, const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& filterRegion, const FloatRect& targetBoundingBox, FilterEffect* previousEffect);
    3338
    3439    FloatSize scaledByFilterScale(FloatSize) const final;
     
    3641    FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
    3742
     43    RefPtr<FilterEffect> lastEffect() { return m_lastEffect; }
     44    void setLastEffect(RefPtr<FilterEffect>&& lastEffect) { m_lastEffect = WTFMove(lastEffect); }
     45
    3846private:
    3947    SVGFilter(const FloatSize& filterScale, const FloatRect& sourceImageRect, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode);
    4048
     49    IntOutsets outsets() const override;
     50    void clearResult() override;
     51
    4152    FloatRect m_targetBoundingBox;
    4253    bool m_effectBBoxMode;
     54
     55    RefPtr<FilterEffect> m_lastEffect;
    4356};
    4457
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp

    r285543 r285618  
    2121#include "SVGFilterBuilder.h"
    2222
    23 #include "FilterEffect.h"
     23#include "ElementIterator.h"
    2424#include "ImageBuffer.h"
     25#include "SVGFilterElement.h"
     26#include "SVGFilterPrimitiveStandardAttributes.h"
    2527#include "SourceAlpha.h"
    2628#include "SourceGraphic.h"
    2729#include <wtf/text/StringConcatenateNumbers.h>
    2830
     31#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
     32#include "CSSComputedStyleDeclaration.h"
     33#include "CSSPrimitiveValueMappings.h"
     34#endif
     35
    2936namespace WebCore {
    3037
    31 SVGFilterBuilder::SVGFilterBuilder(RefPtr<FilterEffect> sourceGraphic)
     38void SVGFilterBuilder::setupBuiltinEffects(Ref<FilterEffect> sourceGraphic)
    3239{
    33     m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphic);
    34     m_builtinEffects.add(SourceAlpha::effectName(), SourceAlpha::create(*sourceGraphic));
     40    m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphic.ptr());
     41    m_builtinEffects.add(SourceAlpha::effectName(), SourceAlpha::create(sourceGraphic));
    3542    addBuiltinEffects();
     43}
     44
     45#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
     46static ColorInterpolation colorInterpolationForElement(SVGElement& element)
     47{
     48    if (auto renderer = element.renderer())
     49        return renderer->style().svgStyle().colorInterpolationFilters();
     50
     51    // Try to determine the property value from the computed style.
     52    if (auto value = ComputedStyleExtractor(&element).propertyValue(CSSPropertyColorInterpolationFilters)) {
     53        if (is<CSSPrimitiveValue>(value))
     54            return downcast<CSSPrimitiveValue>(*value);
     55    }
     56
     57    return ColorInterpolation::Auto;
     58}
     59#endif
     60
     61static unsigned collectEffects(const FilterEffect* effect, HashSet<const FilterEffect*>& allEffects)
     62{
     63    allEffects.add(effect);
     64    unsigned size = effect->numberOfEffectInputs();
     65    for (unsigned i = 0; i < size; ++i) {
     66        FilterEffect* in = effect->inputEffect(i);
     67        collectEffects(in, allEffects);
     68    }
     69    return allEffects.size();
     70}
     71
     72static unsigned totalNumberFilterEffects(const FilterEffect& lastEffect)
     73{
     74    HashSet<const FilterEffect*> allEffects;
     75    return collectEffects(&lastEffect, allEffects);
     76}
     77
     78RefPtr<FilterEffect> SVGFilterBuilder::buildFilterEffects(Filter& filter, SVGFilterElement& filterElement)
     79{
     80    static constexpr unsigned maxCountChildNodes = 200;
     81    static constexpr unsigned maxTotalNumberFilterEffects = 100;
     82
     83    if (filterElement.countChildNodes() > maxCountChildNodes)
     84        return nullptr;
     85
     86    RefPtr<FilterEffect> effect;
     87
     88    for (auto& effectElement : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement)) {
     89        effect = effectElement.build(this, filter);
     90        if (!effect) {
     91            clearEffects();
     92            return nullptr;
     93        }
     94
     95        effectElement.setStandardAttributes(effect.get());
     96        effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(&effectElement, m_primitiveUnits, m_targetBoundingBox));
     97
     98#if ENABLE(DESTINATION_COLOR_SPACE_LINEAR_SRGB)
     99        if (colorInterpolationForElement(effectElement) == ColorInterpolation::LinearRGB)
     100            effect->setOperatingColorSpace(DestinationColorSpace::LinearSRGB());
     101#endif
     102        if (auto renderer = effectElement.renderer())
     103            appendEffectToEffectReferences(effect.copyRef(), renderer);
     104
     105        add(effectElement.result(), effect);
     106    }
     107
     108    if (!effect || totalNumberFilterEffects(*effect) > maxTotalNumberFilterEffects)
     109        return nullptr;
     110
     111    return effect;
    36112}
    37113
  • trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h

    r248762 r285618  
    3838    typedef HashSet<FilterEffect*> FilterEffectSet;
    3939
    40     SVGFilterBuilder(RefPtr<FilterEffect> sourceGraphic);
     40    SVGFilterBuilder() = default;
    4141
    4242    void setTargetBoundingBox(const FloatRect& r) { m_targetBoundingBox = r; }
     
    6666    void clearResultsRecursive(FilterEffect*);
    6767
     68    void setupBuiltinEffects(Ref<FilterEffect> sourceGraphic);
     69    RefPtr<FilterEffect> buildFilterEffects(Filter&, SVGFilterElement&);
     70
    6871private:
    6972    inline void addBuiltinEffects()
Note: See TracChangeset for help on using the changeset viewer.