Skip to content
Permalink
Browse files
[GPU Process] [Filters] Simplify the dynamic update of the SVG filter…
… elements

https://bugs.webkit.org/show_bug.cgi?id=232842
rdar://85426197

Reviewed by Simon Fraser.

Consider this SVG as an example:

<svg>
    <filter id="blur">
        <feGaussianBlur stdDeviation="5"/>
    </filter>
    <circle ... filter="url(#blur)"/>
    <rect ... filter="url(#blur)"/>
</svg>

The renderers of the <circle> and the <rect> elements ask the renderer of the
<filter> element, i.e. RenderSVGResourceFilter to applyResource(). In this
function a new SVGFilter is created for each target renderer. A new entry
{ target_renderer, FilterData } is added to
RenderSVGResourceFilter::m_rendererFilterDataMap.

While building the SVGFilter, a new FilterEffect is created for every target
renderer and an entry { primitive_renderer, effect } is added to
SVGFilterBuilder::m_effectRenderer.

Suppose 'stdDeviation' of <feGaussianBlur> has been changed, this is the
current workflow:

    SVGFEGaussianBlurElement::svgAttributeChanged() will call
    SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged() which
    will call RenderSVGResourceFilterPrimitive::primitiveAttributeChanged().
    The last one will call RenderSVGResourceFilter::primitiveAttributeChanged()
    and pass itself as an argument.

    RenderSVGResourceFilter::primitiveAttributeChanged() will loop through
    all the entries in m_rendererFilterDataMap and get the FilterData. And
    then it gets the effect given the key primitive renderer from
    FilterData::SVGFilterBuilder::m_effectRenderer. Having this effect, its
    setFilterEffectAttribute() will be called.

This workflow is cumbersome since it was mainly done this way because the result
FilterImage was stored with the FilterEffect. But since the  result FilterImage
was moved out of the FilterEffect, we do not need to create a new FilterEffect
for every target renderer. The same FilterEffect can be shared among all the
target renderers.

This is the new workflow for dynamically updating the FilterEffect attributes:

    No need to create a separate FilterEffect for every SVGFilter (or target
    renderer). A shared FilterEffect can be used instead. This will be
    SVGFilterPrimitiveStandardAttributes::m_effect.

    SVGFEGaussianBlurElement::svgAttributeChanged() will call
    SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged() which
    will call SVGFEGaussianBlurElement::setFilterEffectAttribute() if m_effect
    is not null. setFilterEffectAttribute() will return true if it needs to
    be repainted. RenderSVGResourceFilterPrimitive::markFilterEffectForRepaint()
    will be called then.

    RenderSVGResourceFilterPrimitive::markFilterForInvalidation() will call
    RenderSVGResourceFilter::markFilterForRepaint() if effect is not null which
    will clear the result FilterImage of this effect and all other FilterImages
    which takes the result FilterImage of this effect as an input.

    If svgAttributeChanged() finds out it needs to rebuild the entire SVGFilter,
    it will call SVGFilterPrimitiveStandardAttributes::markFilterEffectForRebuild()
    which will call RenderSVGResourceFilterPrimitive::markFilterEffectForRebuild()
    and sets SVGFilterPrimitiveStandardAttributes::m_effect to nullptr.
    RenderSVGResourceFilterPrimitive::markFilterEffectForRebuild() will call
    RenderSVGResourceFilter::markFilterForRebuild() which will clear
    RenderSVGResourceFilter::m_rendererFilterDataMap. This will force rebuilding
    the SVGFilter for all renderers.

* Source/WebCore/platform/graphics/filters/FEDropShadow.cpp:
(WebCore::FEDropShadow::setStdDeviationX):
(WebCore::FEDropShadow::setStdDeviationY):
(WebCore::FEDropShadow::setDx):
(WebCore::FEDropShadow::setDy):
(WebCore::FEDropShadow::setShadowColor):
(WebCore::FEDropShadow::setShadowOpacity):
* Source/WebCore/platform/graphics/filters/FEDropShadow.h:
(WebCore::FEDropShadow::setStdDeviationX): Deleted.
(WebCore::FEDropShadow::setStdDeviationY): Deleted.
(WebCore::FEDropShadow::setDx): Deleted.
(WebCore::FEDropShadow::setDy): Deleted.
(WebCore::FEDropShadow::setShadowColor): Deleted.
(WebCore::FEDropShadow::setShadowOpacity): Deleted.
* Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp:
(WebCore::FEGaussianBlur::setStdDeviationX):
(WebCore::FEGaussianBlur::setStdDeviationY):
(WebCore::FEGaussianBlur::setEdgeMode):
* Source/WebCore/platform/graphics/filters/FEGaussianBlur.h:
* Source/WebCore/platform/graphics/filters/FEOffset.cpp:
(WebCore::FEOffset::setDx):
(WebCore::FEOffset::setDy):
* Source/WebCore/platform/graphics/filters/FEOffset.h:
* Source/WebCore/rendering/CSSFilter.cpp:
(WebCore::createReferenceFilter):
* Source/WebCore/rendering/svg/RenderSVGResourceContainer.h:
* Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::applyResource):
(WebCore::RenderSVGResourceFilter::markFilterForRepaint):
(WebCore::RenderSVGResourceFilter::markFilterForRebuild):
(WebCore::RenderSVGResourceFilter::primitiveAttributeChanged): Deleted.
* Source/WebCore/rendering/svg/RenderSVGResourceFilter.h:
* Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp:
(WebCore::RenderSVGResourceFilterPrimitive::styleDidChange):
(WebCore::RenderSVGResourceFilterPrimitive::markFilterEffectForRepaint):
(WebCore::RenderSVGResourceFilterPrimitive::markFilterEffectForRebuild):
* Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.h:
* Source/WebCore/rendering/svg/SVGRenderTreeAsText.cpp:
(WebCore::writeSVGResourceContainer):
* Source/WebCore/svg/SVGFEBlendElement.cpp:
(WebCore::SVGFEBlendElement::setFilterEffectAttribute):
(WebCore::SVGFEBlendElement::createFilterEffect const):
(WebCore::SVGFEBlendElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEBlendElement.h:
* Source/WebCore/svg/SVGFEColorMatrixElement.cpp:
(WebCore::SVGFEColorMatrixElement::isInvalidValuesLength const):
(WebCore::SVGFEColorMatrixElement::setFilterEffectAttribute):
(WebCore::SVGFEColorMatrixElement::svgAttributeChanged):
(WebCore::SVGFEColorMatrixElement::createFilterEffect const):
(WebCore::SVGFEColorMatrixElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEColorMatrixElement.h:
* Source/WebCore/svg/SVGFEComponentTransferElement.cpp:
(WebCore::SVGFEComponentTransferElement::svgAttributeChanged):
(WebCore::SVGFEComponentTransferElement::createFilterEffect const):
(WebCore::SVGFEComponentTransferElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEComponentTransferElement.h:
* Source/WebCore/svg/SVGFECompositeElement.cpp:
(WebCore::SVGFECompositeElement::setFilterEffectAttribute):
(WebCore::SVGFECompositeElement::svgAttributeChanged):
(WebCore::SVGFECompositeElement::createFilterEffect const):
(WebCore::SVGFECompositeElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFECompositeElement.h:
* Source/WebCore/svg/SVGFEConvolveMatrixElement.cpp:
(WebCore::SVGFEConvolveMatrixElement::setFilterEffectAttribute):
(WebCore::SVGFEConvolveMatrixElement::svgAttributeChanged):
(WebCore::SVGFEConvolveMatrixElement::createFilterEffect const):
(WebCore::SVGFEConvolveMatrixElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEConvolveMatrixElement.h:
* Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp:
(WebCore::SVGFEDiffuseLightingElement::setFilterEffectAttribute):
(WebCore::SVGFEDiffuseLightingElement::svgAttributeChanged):
(WebCore::SVGFEDiffuseLightingElement::createFilterEffect const):
(WebCore::SVGFEDiffuseLightingElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEDiffuseLightingElement.h:
* Source/WebCore/svg/SVGFEDisplacementMapElement.cpp:
(WebCore::SVGFEDisplacementMapElement::setFilterEffectAttribute):
(WebCore::SVGFEDisplacementMapElement::svgAttributeChanged):
(WebCore::SVGFEDisplacementMapElement::createFilterEffect const):
(WebCore::SVGFEDisplacementMapElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEDisplacementMapElement.h:
* Source/WebCore/svg/SVGFEDropShadowElement.cpp:
(WebCore::SVGFEDropShadowElement::svgAttributeChanged):
(WebCore::SVGFEDropShadowElement::setFilterEffectAttribute):
(WebCore::SVGFEDropShadowElement::createFilterEffect const):
(WebCore::SVGFEDropShadowElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEDropShadowElement.h:
* Source/WebCore/svg/SVGFEFloodElement.cpp:
(WebCore::SVGFEFloodElement::setFilterEffectAttribute):
(WebCore::SVGFEFloodElement::createFilterEffect const):
(WebCore::SVGFEFloodElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEFloodElement.h:
* Source/WebCore/svg/SVGFEGaussianBlurElement.cpp:
(WebCore::SVGFEGaussianBlurElement::svgAttributeChanged):
(WebCore::SVGFEGaussianBlurElement::setFilterEffectAttribute):
(WebCore::SVGFEGaussianBlurElement::createFilterEffect const):
(WebCore::SVGFEGaussianBlurElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEGaussianBlurElement.h:
* Source/WebCore/svg/SVGFEImageElement.cpp:
(WebCore::SVGFEImageElement::svgAttributeChanged):
(WebCore::SVGFEImageElement::createFilterEffect const):
(WebCore::SVGFEImageElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEImageElement.h:
* Source/WebCore/svg/SVGFEMergeElement.cpp:
(WebCore::SVGFEMergeElement::childrenChanged):
(WebCore::SVGFEMergeElement::createFilterEffect const):
(WebCore::SVGFEMergeElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEMergeElement.h:
* Source/WebCore/svg/SVGFEMorphologyElement.cpp:
(WebCore::SVGFEMorphologyElement::setFilterEffectAttribute):
(WebCore::SVGFEMorphologyElement::svgAttributeChanged):
(WebCore::SVGFEMorphologyElement::createFilterEffect const):
(WebCore::SVGFEMorphologyElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEMorphologyElement.h:
* Source/WebCore/svg/SVGFEOffsetElement.cpp:
(WebCore::SVGFEOffsetElement::svgAttributeChanged):
(WebCore::SVGFEOffsetElement::setFilterEffectAttribute):
(WebCore::SVGFEOffsetElement::createFilterEffect const):
(WebCore::SVGFEOffsetElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFEOffsetElement.h:
* Source/WebCore/svg/SVGFESpecularLightingElement.cpp:
(WebCore::SVGFESpecularLightingElement::setFilterEffectAttribute):
(WebCore::SVGFESpecularLightingElement::createFilterEffect const):
(WebCore::SVGFESpecularLightingElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFESpecularLightingElement.h:
* Source/WebCore/svg/SVGFETileElement.cpp:
(WebCore::SVGFETileElement::createFilterEffect const):
(WebCore::SVGFETileElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFETileElement.h:
* Source/WebCore/svg/SVGFETurbulenceElement.cpp:
(WebCore::SVGFETurbulenceElement::setFilterEffectAttribute):
(WebCore::SVGFETurbulenceElement::createFilterEffect const):
(WebCore::SVGFETurbulenceElement::filterEffect const): Deleted.
* Source/WebCore/svg/SVGFETurbulenceElement.h:
* Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.cpp:
(WebCore::SVGFilterPrimitiveStandardAttributes::filterEffect):
(WebCore::SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged):
(WebCore::SVGFilterPrimitiveStandardAttributes::markFilterEffectForRebuild):
(WebCore::SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute): Deleted.
* Source/WebCore/svg/SVGFilterPrimitiveStandardAttributes.h:
(WebCore::SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute):
(WebCore::SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged): Deleted.
* Source/WebCore/svg/graphics/filters/SVGFilter.cpp:
(WebCore::SVGFilter::create):
* Source/WebCore/svg/graphics/filters/SVGFilter.h:
* Source/WebCore/svg/graphics/filters/SVGFilterBuilder.cpp:
(WebCore::SVGFilterBuilder::buildFilterExpression):
* Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h:
(WebCore::SVGFilterBuilder::effectByRenderer): Deleted.

Canonical link: https://commits.webkit.org/251503@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@295498 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
shallawa committed Jun 13, 2022
1 parent 6143537 commit d60c93a5b945e64be1b5f2a6b27f44b58a342478
Show file tree
Hide file tree
Showing 53 changed files with 454 additions and 255 deletions.
@@ -45,6 +45,54 @@ FEDropShadow::FEDropShadow(float stdX, float stdY, float dx, float dy, const Col
{
}

bool FEDropShadow::setStdDeviationX(float stdX)
{
if (m_stdX == stdX)
return false;
m_stdX = stdX;
return true;
}

bool FEDropShadow::setStdDeviationY(float stdY)
{
if (m_stdY == stdY)
return false;
m_stdY = stdY;
return true;
}

bool FEDropShadow::setDx(float dx)
{
if (m_dx == dx)
return false;
m_dx = dx;
return true;
}

bool FEDropShadow::setDy(float dy)
{
if (m_dy == dy)
return false;
m_dy = dy;
return true;
}

bool FEDropShadow::setShadowColor(const Color& shadowColor)
{
if (m_shadowColor == shadowColor)
return false;
m_shadowColor = shadowColor;
return true;
}

bool FEDropShadow::setShadowOpacity(float shadowOpacity)
{
if (m_shadowOpacity == shadowOpacity)
return false;
m_shadowOpacity = shadowOpacity;
return true;
}

FloatRect FEDropShadow::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
{
auto imageRect = inputs[0]->imageRect();
@@ -30,22 +30,22 @@ class FEDropShadow : public FilterEffect {
WEBCORE_EXPORT static Ref<FEDropShadow> create(float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity);

float stdDeviationX() const { return m_stdX; }
void setStdDeviationX(float stdX) { m_stdX = stdX; }
bool setStdDeviationX(float);

float stdDeviationY() const { return m_stdY; }
void setStdDeviationY(float stdY) { m_stdY = stdY; }
bool setStdDeviationY(float);

float dx() const { return m_dx; }
void setDx(float dx) { m_dx = dx; }
bool setDx(float);

float dy() const { return m_dy; }
void setDy(float dy) { m_dy = dy; }
bool setDy(float);

const Color& shadowColor() const { return m_shadowColor; }
void setShadowColor(const Color& shadowColor) { m_shadowColor = shadowColor; }
bool setShadowColor(const Color&);

float shadowOpacity() const { return m_shadowOpacity; }
void setShadowOpacity(float shadowOpacity) { m_shadowOpacity = shadowOpacity; }
bool setShadowOpacity(float);

static IntOutsets calculateOutsets(const FloatSize& offset, const FloatSize& stdDeviation);

@@ -45,19 +45,28 @@ FEGaussianBlur::FEGaussianBlur(float x, float y, EdgeModeType edgeMode)
{
}

void FEGaussianBlur::setStdDeviationX(float x)
bool FEGaussianBlur::setStdDeviationX(float stdX)
{
m_stdX = x;
if (m_stdX == stdX)
return false;
m_stdX = stdX;
return true;
}

void FEGaussianBlur::setStdDeviationY(float y)
bool FEGaussianBlur::setStdDeviationY(float stdY)
{
m_stdY = y;
if (m_stdY == stdY)
return false;
m_stdY = stdY;
return true;
}

void FEGaussianBlur::setEdgeMode(EdgeModeType edgeMode)
bool FEGaussianBlur::setEdgeMode(EdgeModeType edgeMode)
{
if (m_edgeMode == edgeMode)
return false;
m_edgeMode = edgeMode;
return true;
}

static inline float gaussianKernelFactor()
@@ -32,13 +32,13 @@ class FEGaussianBlur : public FilterEffect {
WEBCORE_EXPORT static Ref<FEGaussianBlur> create(float x, float y, EdgeModeType);

float stdDeviationX() const { return m_stdX; }
void setStdDeviationX(float);
bool setStdDeviationX(float);

float stdDeviationY() const { return m_stdY; }
void setStdDeviationY(float);
bool setStdDeviationY(float);

EdgeModeType edgeMode() const { return m_edgeMode; }
void setEdgeMode(EdgeModeType);
bool setEdgeMode(EdgeModeType);

static IntSize calculateKernelSize(const Filter&, FloatSize stdDeviation);
static IntSize calculateUnscaledKernelSize(FloatSize stdDeviation);
@@ -43,14 +43,20 @@ FEOffset::FEOffset(float dx, float dy)
{
}

void FEOffset::setDx(float dx)
bool FEOffset::setDx(float dx)
{
if (m_dx == dx)
return false;
m_dx = dx;
return true;
}

void FEOffset::setDy(float dy)
bool FEOffset::setDy(float dy)
{
if (m_dy == dy)
return false;
m_dy = dy;
return true;
}

FloatRect FEOffset::calculateImageRect(const Filter& filter, const FilterImageVector& inputs, const FloatRect& primitiveSubregion) const
@@ -31,10 +31,10 @@ class FEOffset : public FilterEffect {
WEBCORE_EXPORT static Ref<FEOffset> create(float dx, float dy);

float dx() const { return m_dx; }
void setDx(float);
bool setDx(float);

float dy() const { return m_dy; }
void setDy(float);
bool setDy(float);

static IntOutsets calculateOutsets(const FloatSize& offset);

@@ -264,8 +264,7 @@ static RefPtr<SVGFilter> createReferenceFilter(CSSFilter& filter, const Referenc

auto filterRegion = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits(), targetBoundingBox);

SVGFilterBuilder builder;
return SVGFilter::create(*filterElement, builder, filter.renderingMode(), filter.filterScale(), filter.clipOperation(), filterRegion, targetBoundingBox, destinationContext);
return SVGFilter::create(*filterElement, filter.renderingMode(), filter.filterScale(), filter.clipOperation(), filterRegion, targetBoundingBox, destinationContext);
}

bool CSSFilter::buildFilterFunctions(RenderElement& renderer, const FilterOperations& operations, const FloatRect& targetBoundingBox, const GraphicsContext& destinationContext)
@@ -45,6 +45,7 @@ class RenderSVGResourceContainer : public RenderSVGHiddenContainer,
void markAllClientsForRepaint();
void addClientRenderLayer(RenderLayer*);
void removeClientRenderLayer(RenderLayer*);
void markAllClientLayersForInvalidation();

protected:
RenderSVGResourceContainer(SVGElement&, RenderStyle&&);
@@ -60,7 +61,6 @@ class RenderSVGResourceContainer : public RenderSVGHiddenContainer,
virtual bool selfNeedsClientInvalidation() const { return everHadLayout() && selfNeedsLayout(); }

void markAllClientsForInvalidation(InvalidationMode);
void markAllClientLayersForInvalidation();
void markClientForInvalidation(RenderObject&, InvalidationMode);

private:
@@ -25,24 +25,14 @@
#include "config.h"
#include "RenderSVGResourceFilter.h"

#include "ElementChildIterator.h"
#include "FilterEffect.h"
#include "FloatPoint.h"
#include "Frame.h"
#include "GraphicsContext.h"
#include "Image.h"
#include "ImageData.h"
#include "IntRect.h"
#include "Logging.h"
#include "RenderSVGResourceFilterInlines.h"
#include "RenderSVGResourceFilterPrimitive.h"
#include "RenderView.h"
#include "SVGElementTypeHelpers.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
#include "SVGNames.h"
#include "SVGRenderingContext.h"
#include "Settings.h"
#include "SourceGraphic.h"
#include <wtf/IsoMallocInlines.h>
#include <wtf/text/TextStream.h>

@@ -129,8 +119,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
auto renderingMode = renderer.page().acceleratedFiltersEnabled() ? RenderingMode::Accelerated : RenderingMode::Unaccelerated;

// Create the SVGFilter object.
filterData->builder = makeUnique<SVGFilterBuilder>();
filterData->filter = SVGFilter::create(filterElement(), *filterData->builder, renderingMode, filterScale, Filter::ClipOperation::Intersect, filterData->boundaries, targetBoundingBox, *context);
filterData->filter = SVGFilter::create(filterElement(), renderingMode, filterScale, Filter::ClipOperation::Intersect, filterData->boundaries, targetBoundingBox, *context);
if (!filterData->filter) {
m_rendererFilterDataMap.remove(&renderer);
return false;
@@ -225,31 +214,27 @@ FloatRect RenderSVGResourceFilter::resourceBoundingBox(const RenderObject& objec
return SVGLengthContext::resolveRectangle<SVGFilterElement>(&filterElement(), filterElement().filterUnits(), object.objectBoundingBox());
}

void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute)
void RenderSVGResourceFilter::markFilterForRepaint(FilterEffect& effect)
{
SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node());

LOG(Filters, "RenderSVGResourceFilter %p primitiveAttributeChanged renderer %p", this, object);
LOG(Filters, "RenderSVGResourceFilter %p markFilterForRepaint effect %p", this, &effect);

for (const auto& objectFilterDataPair : m_rendererFilterDataMap) {
const auto& filterData = objectFilterDataPair.value;
if (filterData->state != FilterData::Built)
continue;

SVGFilterBuilder* builder = filterData->builder.get();
FilterEffect* effect = builder->effectByRenderer(object);
if (!effect)
continue;
// Since all effects shares the same attribute value, all
// or none of them will be changed.
if (!primitve->setFilterEffectAttribute(effect, attribute))
return;
filterData->results.clearEffectResult(*effect);

// Repaint the image on the screen.
markClientForInvalidation(*objectFilterDataPair.key, RepaintInvalidation);

filterData->results.clearEffectResult(effect);
}
markAllClientLayersForInvalidation();
}

void RenderSVGResourceFilter::markFilterForRebuild()
{
LOG(Filters, "RenderSVGResourceFilter %p markFilterForRebuild", this);

removeAllClientsFromCache();
}

FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
@@ -45,7 +45,6 @@ struct FilterData {
FilterData() = default;

RefPtr<SVGFilter> filter;
std::unique_ptr<SVGFilterBuilder> builder;
RefPtr<ImageBuffer> sourceGraphicBuffer;
GraphicsContext* savedContext { nullptr };
FloatRect boundaries;
@@ -73,12 +72,11 @@ class RenderSVGResourceFilter final : public RenderSVGResourceContainer {

FloatRect resourceBoundingBox(const RenderObject&) override;

std::unique_ptr<SVGFilterBuilder> buildPrimitives(SVGFilter&) const;

inline SVGUnitTypes::SVGUnitType filterUnits() const;
inline SVGUnitTypes::SVGUnitType primitiveUnits() const;

void primitiveAttributeChanged(RenderObject*, const QualifiedName&);
void markFilterForRepaint(FilterEffect&);
void markFilterForRebuild();

RenderSVGResourceType resourceType() const override { return FilterResourceType; }

@@ -2,6 +2,7 @@
* Copyright (C) 2010 University of Szeged
* Copyright (C) 2010 Zoltan Herczeg
* Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
* Copyright (C) 2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +31,7 @@

#include "SVGElementTypeHelpers.h"
#include "SVGFEDiffuseLightingElement.h"
#include "SVGFEDropShadowElement.h"
#include "SVGFEFloodElement.h"
#include "SVGFESpecularLightingElement.h"
#include "SVGFilterPrimitiveStandardAttributes.h"
@@ -54,23 +56,45 @@ void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, cons
{
RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);

auto* filter = parent();
if (!filter)
return;

if (diff == StyleDifference::Equal || !oldStyle)
return;

const SVGRenderStyle& newStyle = style().svgStyle();
if (is<SVGFEFloodElement>(filterPrimitiveElement())) {
if (is<SVGFEFloodElement>(filterPrimitiveElement()) || is<SVGFEDropShadowElement>(filterPrimitiveElement())) {
if (newStyle.floodColor() != oldStyle->svgStyle().floodColor())
downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
filterPrimitiveElement().primitiveAttributeChanged(SVGNames::flood_colorAttr);
if (newStyle.floodOpacity() != oldStyle->svgStyle().floodOpacity())
downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
filterPrimitiveElement().primitiveAttributeChanged(SVGNames::flood_opacityAttr);
} else if (is<SVGFEDiffuseLightingElement>(filterPrimitiveElement()) || is<SVGFESpecularLightingElement>(filterPrimitiveElement())) {
if (newStyle.lightingColor() != oldStyle->svgStyle().lightingColor())
downcast<RenderSVGResourceFilter>(*filter).primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
filterPrimitiveElement().primitiveAttributeChanged(SVGNames::lighting_colorAttr);
}
}

void RenderSVGResourceFilterPrimitive::markFilterEffectForRepaint(FilterEffect* effect)
{
auto parent = this->parent();
if (!is<RenderSVGResourceFilter>(parent))
return;

auto& filterRenderer = downcast<RenderSVGResourceFilter>(*parent);

if (effect)
filterRenderer.markFilterForRepaint(*effect);

filterRenderer.markAllClientLayersForInvalidation();
}

void RenderSVGResourceFilterPrimitive::markFilterEffectForRebuild()
{
auto parent = this->parent();
if (!is<RenderSVGResourceFilter>(parent))
return;

auto& filterRenderer = downcast<RenderSVGResourceFilter>(*parent);

filterRenderer.markFilterForRebuild();
filterRenderer.markAllClientLayersForInvalidation();
}

} // namespace WebCore
@@ -43,13 +43,9 @@ class RenderSVGResourceFilterPrimitive final : public RenderSVGHiddenContainer {

ASCIILiteral renderName() const override { return "RenderSVGResourceFilterPrimitive"_s; }

inline void primitiveAttributeChanged(const QualifiedName& attribute)
{
RenderObject* filter = parent();
if (!filter || !filter->isSVGResourceFilter())
return;
static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, attribute);
}
void markFilterEffectForRepaint(FilterEffect*);
void markFilterEffectForRebuild();

private:
bool isSVGResourceFilterPrimitive() const override { return true; }
void element() const = delete;
@@ -477,8 +477,7 @@ void writeSVGResourceContainer(TextStream& ts, const RenderSVGResourceContainer&
// Creating a placeholder filter which is passed to the builder.
FloatRect dummyRect;
FloatSize dummyScale(1, 1);
SVGFilterBuilder builder;
auto dummyFilter = SVGFilter::create(filter.filterElement(), builder, RenderingMode::Unaccelerated, dummyScale, Filter::ClipOperation::Intersect, dummyRect, dummyRect, NullGraphicsContext());
auto dummyFilter = SVGFilter::create(filter.filterElement(), RenderingMode::Unaccelerated, dummyScale, Filter::ClipOperation::Intersect, dummyRect, dummyRect, NullGraphicsContext());
if (dummyFilter) {
TextStream::IndentScope indentScope(ts);
dummyFilter->externalRepresentation(ts, FilterRepresentation::TestOutput);

0 comments on commit d60c93a

Please sign in to comment.