Commit d24c3eae authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Refactor <filter> invalidation to use the DOM structure

This changes the path used for invalidation of filter effects (SVGFE*)
from the layout tree to the DOM tree. This is done to allow invalidation
to work when the filter is not part of the layout tree. That change
will be done in a follow-up.

Also add casting helpers for SVGFilterPrimitiveStandardAttributes and
use it where applicable.

Bug: 773811
Change-Id: I275534e59eb285c0cab805f6c09d00b1f725e4f4
Reviewed-on: https://chromium-review.googlesource.com/719837Reviewed-by: default avatarStephen Chenney <schenney@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Commit-Queue: Philip Rogers <pdr@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#509478}
parent 08beed78
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
{ {
"object": "LayoutSVGRect rect", "object": "LayoutSVGRect rect",
"rect": [0, 0, 110, 110], "rect": [0, 0, 110, 110],
"reason": "style change" "reason": "full"
} }
] ]
} }
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
"objectPaintInvalidations": [ "objectPaintInvalidations": [
{ {
"object": "LayoutSVGRect rect", "object": "LayoutSVGRect rect",
"reason": "style change" "reason": "full"
} }
] ]
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
{ {
"object": "LayoutSVGRect rect", "object": "LayoutSVGRect rect",
"rect": [0, 0, 110, 110], "rect": [0, 0, 110, 110],
"reason": "style change" "reason": "full"
} }
] ]
} }
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
}, },
{ {
"object": "LayoutSVGRect rect", "object": "LayoutSVGRect rect",
"reason": "style change" "reason": "full"
} }
] ]
} }
......
...@@ -119,10 +119,9 @@ SVGUnitTypes::SVGUnitType LayoutSVGResourceFilter::PrimitiveUnits() const { ...@@ -119,10 +119,9 @@ SVGUnitTypes::SVGUnitType LayoutSVGResourceFilter::PrimitiveUnits() const {
} }
void LayoutSVGResourceFilter::PrimitiveAttributeChanged( void LayoutSVGResourceFilter::PrimitiveAttributeChanged(
LayoutObject* object, SVGFilterPrimitiveStandardAttributes& primitive,
const QualifiedName& attribute) { const QualifiedName& attribute) {
SVGFilterPrimitiveStandardAttributes* primitive = LayoutObject* object = primitive.GetLayoutObject();
static_cast<SVGFilterPrimitiveStandardAttributes*>(object->GetNode());
for (auto& filter : filter_) { for (auto& filter : filter_) {
FilterData* filter_data = filter.value.Get(); FilterData* filter_data = filter.value.Get();
...@@ -135,7 +134,7 @@ void LayoutSVGResourceFilter::PrimitiveAttributeChanged( ...@@ -135,7 +134,7 @@ void LayoutSVGResourceFilter::PrimitiveAttributeChanged(
continue; continue;
// Since all effects shares the same attribute value, all // Since all effects shares the same attribute value, all
// or none of them will be changed. // or none of them will be changed.
if (!primitive->SetFilterEffectAttribute(effect, attribute)) if (!primitive.SetFilterEffectAttribute(effect, attribute))
return; return;
node_map->InvalidateDependentEffects(effect); node_map->InvalidateDependentEffects(effect);
......
...@@ -32,6 +32,7 @@ namespace blink { ...@@ -32,6 +32,7 @@ namespace blink {
class FilterEffect; class FilterEffect;
class SVGFilterElement; class SVGFilterElement;
class SVGFilterGraphNodeMap; class SVGFilterGraphNodeMap;
class SVGFilterPrimitiveStandardAttributes;
class FilterData final : public GarbageCollected<FilterData> { class FilterData final : public GarbageCollected<FilterData> {
public: public:
...@@ -87,7 +88,8 @@ class LayoutSVGResourceFilter final : public LayoutSVGResourceContainer { ...@@ -87,7 +88,8 @@ class LayoutSVGResourceFilter final : public LayoutSVGResourceContainer {
SVGUnitTypes::SVGUnitType FilterUnits() const; SVGUnitTypes::SVGUnitType FilterUnits() const;
SVGUnitTypes::SVGUnitType PrimitiveUnits() const; SVGUnitTypes::SVGUnitType PrimitiveUnits() const;
void PrimitiveAttributeChanged(LayoutObject*, const QualifiedName&); void PrimitiveAttributeChanged(SVGFilterPrimitiveStandardAttributes&,
const QualifiedName&);
static const LayoutSVGResourceType kResourceType = kFilterResourceType; static const LayoutSVGResourceType kResourceType = kFilterResourceType;
LayoutSVGResourceType ResourceType() const override { return kResourceType; } LayoutSVGResourceType ResourceType() const override { return kResourceType; }
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include "core/layout/svg/LayoutSVGResourceFilterPrimitive.h" #include "core/layout/svg/LayoutSVGResourceFilterPrimitive.h"
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
namespace blink { namespace blink {
void LayoutSVGResourceFilterPrimitive::StyleDidChange( void LayoutSVGResourceFilterPrimitive::StyleDidChange(
...@@ -34,32 +36,27 @@ void LayoutSVGResourceFilterPrimitive::StyleDidChange( ...@@ -34,32 +36,27 @@ void LayoutSVGResourceFilterPrimitive::StyleDidChange(
const ComputedStyle* old_style) { const ComputedStyle* old_style) {
LayoutSVGHiddenContainer::StyleDidChange(diff, old_style); LayoutSVGHiddenContainer::StyleDidChange(diff, old_style);
LayoutObject* filter = Parent();
if (!filter)
return;
DCHECK(filter->IsSVGResourceFilter());
if (!old_style) if (!old_style)
return; return;
const SVGComputedStyle& new_style = this->StyleRef().SvgStyle();
DCHECK(GetElement()); DCHECK(GetElement());
if (IsSVGFEFloodElement(*GetElement()) || SVGFilterPrimitiveStandardAttributes& element =
IsSVGFEDropShadowElement(*GetElement())) { ToSVGFilterPrimitiveStandardAttributes(*GetElement());
const SVGComputedStyle& new_style = this->StyleRef().SvgStyle();
if (IsSVGFEFloodElement(element) || IsSVGFEDropShadowElement(element)) {
if (new_style.FloodColor() != old_style->SvgStyle().FloodColor()) if (new_style.FloodColor() != old_style->SvgStyle().FloodColor())
ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged( element.PrimitiveAttributeChanged(SVGNames::flood_colorAttr);
this, SVGNames::flood_colorAttr);
if (new_style.FloodOpacity() != old_style->SvgStyle().FloodOpacity()) if (new_style.FloodOpacity() != old_style->SvgStyle().FloodOpacity())
ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged( element.PrimitiveAttributeChanged(SVGNames::flood_opacityAttr);
this, SVGNames::flood_opacityAttr); } else if (IsSVGFEDiffuseLightingElement(element) ||
} else if (IsSVGFEDiffuseLightingElement(*GetElement()) || IsSVGFESpecularLightingElement(element)) {
IsSVGFESpecularLightingElement(*GetElement())) {
if (new_style.LightingColor() != old_style->SvgStyle().LightingColor()) if (new_style.LightingColor() != old_style->SvgStyle().LightingColor())
ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged( element.PrimitiveAttributeChanged(SVGNames::lighting_colorAttr);
this, SVGNames::lighting_colorAttr);
} }
if (new_style.ColorInterpolationFilters() != if (new_style.ColorInterpolationFilters() !=
old_style->SvgStyle().ColorInterpolationFilters()) old_style->SvgStyle().ColorInterpolationFilters()) {
ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged( element.PrimitiveAttributeChanged(
this, SVGNames::color_interpolation_filtersAttr); SVGNames::color_interpolation_filtersAttr);
}
} }
} // namespace blink } // namespace blink
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#ifndef LayoutSVGResourceFilterPrimitive_h #ifndef LayoutSVGResourceFilterPrimitive_h
#define LayoutSVGResourceFilterPrimitive_h #define LayoutSVGResourceFilterPrimitive_h
#include "core/layout/svg/LayoutSVGResourceFilter.h" #include "core/layout/svg/LayoutSVGHiddenContainer.h"
namespace blink { namespace blink {
...@@ -50,14 +50,6 @@ class LayoutSVGResourceFilterPrimitive final : public LayoutSVGHiddenContainer { ...@@ -50,14 +50,6 @@ class LayoutSVGResourceFilterPrimitive final : public LayoutSVGHiddenContainer {
return type == kLayoutObjectSVGResourceFilterPrimitive || return type == kLayoutObjectSVGResourceFilterPrimitive ||
LayoutSVGHiddenContainer::IsOfType(type); LayoutSVGHiddenContainer::IsOfType(type);
} }
inline void PrimitiveAttributeChanged(const QualifiedName& attribute) {
LayoutObject* filter = Parent();
if (!filter || !filter->IsSVGResourceFilter())
return;
ToLayoutSVGResourceFilter(filter)->PrimitiveAttributeChanged(this,
attribute);
}
}; };
} // namespace blink } // namespace blink
......
...@@ -99,8 +99,7 @@ void SVGComponentTransferFunctionElement::SvgAttributeChanged( ...@@ -99,8 +99,7 @@ void SVGComponentTransferFunctionElement::SvgAttributeChanged(
attr_name == SVGNames::exponentAttr || attr_name == SVGNames::exponentAttr ||
attr_name == SVGNames::offsetAttr) { attr_name == SVGNames::offsetAttr) {
SVGElement::InvalidationGuard invalidation_guard(this); SVGElement::InvalidationGuard invalidation_guard(this);
InvalidateFilterPrimitiveParent(*this);
InvalidateFilterPrimitiveParent(this);
return; return;
} }
......
...@@ -41,7 +41,7 @@ void SVGFEMergeNodeElement::SvgAttributeChanged( ...@@ -41,7 +41,7 @@ void SVGFEMergeNodeElement::SvgAttributeChanged(
const QualifiedName& attr_name) { const QualifiedName& attr_name) {
if (attr_name == SVGNames::inAttr) { if (attr_name == SVGNames::inAttr) {
SVGElement::InvalidationGuard invalidation_guard(this); SVGElement::InvalidationGuard invalidation_guard(this);
InvalidateFilterPrimitiveParent(this); InvalidateFilterPrimitiveParent(*this);
return; return;
} }
......
...@@ -96,17 +96,27 @@ void SVGFilterElement::SvgAttributeChanged(const QualifiedName& attr_name) { ...@@ -96,17 +96,27 @@ void SVGFilterElement::SvgAttributeChanged(const QualifiedName& attr_name) {
if (is_xywh || attr_name == SVGNames::filterUnitsAttr || if (is_xywh || attr_name == SVGNames::filterUnitsAttr ||
attr_name == SVGNames::primitiveUnitsAttr) { attr_name == SVGNames::primitiveUnitsAttr) {
SVGElement::InvalidationGuard invalidation_guard(this); SVGElement::InvalidationGuard invalidation_guard(this);
LayoutSVGResourceContainer* layout_object = InvalidateFilterChain();
ToLayoutSVGResourceContainer(this->GetLayoutObject());
if (layout_object)
layout_object->InvalidateCacheAndMarkForLayout();
return; return;
} }
SVGElement::SvgAttributeChanged(attr_name); SVGElement::SvgAttributeChanged(attr_name);
} }
void SVGFilterElement::PrimitiveAttributeChanged(
SVGFilterPrimitiveStandardAttributes& primitive,
const QualifiedName& attribute) {
if (LayoutObject* layout_object = GetLayoutObject()) {
ToLayoutSVGResourceFilter(layout_object)
->PrimitiveAttributeChanged(primitive, attribute);
}
}
void SVGFilterElement::InvalidateFilterChain() {
if (LayoutObject* layout_object = GetLayoutObject())
ToLayoutSVGResourceFilter(layout_object)->RemoveAllClientsFromCache();
}
void SVGFilterElement::ChildrenChanged(const ChildrenChange& change) { void SVGFilterElement::ChildrenChanged(const ChildrenChange& change) {
SVGElement::ChildrenChanged(change); SVGElement::ChildrenChanged(change);
......
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
namespace blink { namespace blink {
class SVGFilterPrimitiveStandardAttributes;
class CORE_EXPORT SVGFilterElement final : public SVGElement, class CORE_EXPORT SVGFilterElement final : public SVGElement,
public SVGURIReference { public SVGURIReference {
DEFINE_WRAPPERTYPEINFO(); DEFINE_WRAPPERTYPEINFO();
...@@ -55,6 +57,13 @@ class CORE_EXPORT SVGFilterElement final : public SVGElement, ...@@ -55,6 +57,13 @@ class CORE_EXPORT SVGFilterElement final : public SVGElement,
return primitive_units_.Get(); return primitive_units_.Get();
} }
// Fine-grained invalidation of a specific property on a specific primitive.
void PrimitiveAttributeChanged(SVGFilterPrimitiveStandardAttributes&,
const QualifiedName&);
// Invalidate the entire filter chain.
void InvalidateFilterChain();
private: private:
explicit SVGFilterElement(Document&); explicit SVGFilterElement(Document&);
......
...@@ -21,8 +21,8 @@ ...@@ -21,8 +21,8 @@
#include "core/svg/SVGFilterPrimitiveStandardAttributes.h" #include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
#include "core/layout/svg/LayoutSVGResourceContainer.h"
#include "core/layout/svg/LayoutSVGResourceFilterPrimitive.h" #include "core/layout/svg/LayoutSVGResourceFilterPrimitive.h"
#include "core/svg/SVGFilterElement.h"
#include "core/svg/SVGLength.h" #include "core/svg/SVGLength.h"
#include "core/svg/graphics/filters/SVGFilterBuilder.h" #include "core/svg/graphics/filters/SVGFilterBuilder.h"
#include "core/svg_names.h" #include "core/svg_names.h"
...@@ -175,32 +175,24 @@ bool SVGFilterPrimitiveStandardAttributes::LayoutObjectIsNeeded( ...@@ -175,32 +175,24 @@ bool SVGFilterPrimitiveStandardAttributes::LayoutObjectIsNeeded(
} }
void SVGFilterPrimitiveStandardAttributes::Invalidate() { void SVGFilterPrimitiveStandardAttributes::Invalidate() {
if (LayoutObject* primitive_layout_object = GetLayoutObject()) if (SVGFilterElement* filter = ToSVGFilterElementOrNull(parentElement()))
MarkForLayoutAndParentResourceInvalidation(primitive_layout_object); filter->InvalidateFilterChain();
} }
void SVGFilterPrimitiveStandardAttributes::PrimitiveAttributeChanged( void SVGFilterPrimitiveStandardAttributes::PrimitiveAttributeChanged(
const QualifiedName& attribute) { const QualifiedName& attribute) {
if (LayoutObject* primitive_layout_object = GetLayoutObject()) if (SVGFilterElement* filter = ToSVGFilterElementOrNull(parentElement()))
static_cast<LayoutSVGResourceFilterPrimitive*>(primitive_layout_object) filter->PrimitiveAttributeChanged(*this, attribute);
->PrimitiveAttributeChanged(attribute);
} }
void InvalidateFilterPrimitiveParent(SVGElement* element) { void InvalidateFilterPrimitiveParent(SVGElement& element) {
if (!element) Element* parent = element.parentElement();
if (!parent || !parent->IsSVGElement())
return; return;
SVGElement& svgparent = ToSVGElement(*parent);
ContainerNode* parent = element->parentNode(); if (!IsSVGFilterPrimitiveStandardAttributes(svgparent))
if (!parent)
return; return;
ToSVGFilterPrimitiveStandardAttributes(svgparent).Invalidate();
LayoutObject* layout_object = parent->GetLayoutObject();
if (!layout_object || !layout_object->IsSVGResourceFilterPrimitive())
return;
LayoutSVGResourceContainer::MarkForLayoutAndParentResourceInvalidation(
layout_object, false);
} }
} // namespace blink } // namespace blink
...@@ -57,15 +57,15 @@ class SVGFilterPrimitiveStandardAttributes : public SVGElement { ...@@ -57,15 +57,15 @@ class SVGFilterPrimitiveStandardAttributes : public SVGElement {
DECLARE_VIRTUAL_TRACE(); DECLARE_VIRTUAL_TRACE();
void PrimitiveAttributeChanged(const QualifiedName&);
void Invalidate();
protected: protected:
SVGFilterPrimitiveStandardAttributes(const QualifiedName&, Document&); SVGFilterPrimitiveStandardAttributes(const QualifiedName&, Document&);
void SvgAttributeChanged(const QualifiedName&) override; void SvgAttributeChanged(const QualifiedName&) override;
void ChildrenChanged(const ChildrenChange&) override; void ChildrenChanged(const ChildrenChange&) override;
void Invalidate();
void PrimitiveAttributeChanged(const QualifiedName&);
private: private:
bool IsFilterEffect() const final { return true; } bool IsFilterEffect() const final { return true; }
...@@ -79,7 +79,14 @@ class SVGFilterPrimitiveStandardAttributes : public SVGElement { ...@@ -79,7 +79,14 @@ class SVGFilterPrimitiveStandardAttributes : public SVGElement {
Member<SVGAnimatedString> result_; Member<SVGAnimatedString> result_;
}; };
void InvalidateFilterPrimitiveParent(SVGElement*); void InvalidateFilterPrimitiveParent(SVGElement&);
inline bool IsSVGFilterPrimitiveStandardAttributes(const SVGElement& element) {
return element.IsFilterEffect();
}
DEFINE_SVGELEMENT_TYPE_CASTS_WITH_FUNCTION(
SVGFilterPrimitiveStandardAttributes);
} // namespace blink } // namespace blink
......
...@@ -177,26 +177,25 @@ void SVGFilterBuilder::BuildGraph(Filter* filter, ...@@ -177,26 +177,25 @@ void SVGFilterBuilder::BuildGraph(Filter* filter,
if (!element->IsFilterEffect()) if (!element->IsFilterEffect())
continue; continue;
SVGFilterPrimitiveStandardAttributes* effect_element = SVGFilterPrimitiveStandardAttributes& effect_element =
static_cast<SVGFilterPrimitiveStandardAttributes*>(element); ToSVGFilterPrimitiveStandardAttributes(*element);
FilterEffect* effect = effect_element->Build(this, filter); FilterEffect* effect = effect_element.Build(this, filter);
if (!effect) if (!effect)
continue; continue;
if (node_map_) if (node_map_)
node_map_->AddPrimitive(effect_element->GetLayoutObject(), effect); node_map_->AddPrimitive(effect_element.GetLayoutObject(), effect);
effect_element->SetStandardAttributes(effect, primitive_units, effect_element.SetStandardAttributes(effect, primitive_units,
reference_box); reference_box);
EColorInterpolation color_interpolation = ColorInterpolationForElement( EColorInterpolation color_interpolation = ColorInterpolationForElement(
*effect_element, filter_color_interpolation); effect_element, filter_color_interpolation);
effect->SetOperatingInterpolationSpace( effect->SetOperatingInterpolationSpace(
ResolveInterpolationSpace(color_interpolation)); ResolveInterpolationSpace(color_interpolation));
if (effect_element->TaintsOrigin(effect->InputsTaintOrigin())) if (effect_element.TaintsOrigin(effect->InputsTaintOrigin()))
effect->SetOriginTainted(); effect->SetOriginTainted();
Add(AtomicString(effect_element->result()->CurrentValue()->Value()), Add(AtomicString(effect_element.result()->CurrentValue()->Value()), effect);
effect);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment