| Index: third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
|
| diff --git a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
|
| index a032ced8955bf4a00af58d009d31da8dca2896f4..36e291aa67f9e3aebdeabbf9351a1cd8883301e9 100644
|
| --- a/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
|
| +++ b/third_party/WebKit/Source/core/svg/graphics/filters/SVGFilterBuilder.cpp
|
| @@ -20,30 +20,127 @@
|
| #include "config.h"
|
| #include "core/svg/graphics/filters/SVGFilterBuilder.h"
|
|
|
| +#include "core/css/CSSPrimitiveValue.h"
|
| +#include "core/css/CSSPrimitiveValueMappings.h"
|
| +#include "core/css/StylePropertySet.h"
|
| +#include "core/dom/ElementTraversal.h"
|
| +#include "core/layout/LayoutObject.h"
|
| +#include "core/svg/SVGFilterElement.h"
|
| +#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
|
| +#include "platform/graphics/filters/Filter.h"
|
| #include "platform/graphics/filters/SourceAlpha.h"
|
| #include "platform/graphics/filters/SourceGraphic.h"
|
|
|
| namespace blink {
|
|
|
| -SVGFilterBuilder::SVGFilterBuilder(PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic)
|
| +void SVGFilterGraphNodeMap::addBuiltinEffect(FilterEffect* effect)
|
| {
|
| - RefPtrWillBeRawPtr<FilterEffect> sourceGraphicRef = sourceGraphic;
|
| - m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphicRef);
|
| - m_builtinEffects.add(SourceAlpha::effectName(), SourceAlpha::create(sourceGraphicRef.get()));
|
| - addBuiltinEffects();
|
| + m_effectReferences.add(effect, FilterEffectSet());
|
| +}
|
| +
|
| +void SVGFilterGraphNodeMap::addPrimitive(LayoutObject* object, PassRefPtrWillBeRawPtr<FilterEffect> prpEffect)
|
| +{
|
| + RefPtrWillBeRawPtr<FilterEffect> effect = prpEffect;
|
| +
|
| + // The effect must be a newly created filter effect.
|
| + ASSERT(!m_effectReferences.contains(effect));
|
| + ASSERT(object && !m_effectRenderer.contains(object));
|
| + m_effectReferences.add(effect, FilterEffectSet());
|
| +
|
| + unsigned numberOfInputEffects = effect->inputEffects().size();
|
| +
|
| + // Add references from the inputs of this effect to the effect itself, to
|
| + // allow determining what effects needs to be invalidated when a certain
|
| + // effect changes.
|
| + for (unsigned i = 0; i < numberOfInputEffects; ++i)
|
| + effectReferences(effect->inputEffect(i)).add(effect.get());
|
| +
|
| + m_effectRenderer.add(object, effect.get());
|
| }
|
|
|
| -DEFINE_TRACE(SVGFilterBuilder)
|
| +void SVGFilterGraphNodeMap::invalidateDependentEffects(FilterEffect* effect)
|
| +{
|
| + if (!effect->hasImageFilter())
|
| + return;
|
| +
|
| + effect->clearResult();
|
| +
|
| + FilterEffectSet& effectReferences = this->effectReferences(effect);
|
| + for (FilterEffect* effectReference : effectReferences)
|
| + invalidateDependentEffects(effectReference);
|
| +}
|
| +
|
| +DEFINE_TRACE(SVGFilterGraphNodeMap)
|
| {
|
| #if ENABLE(OILPAN)
|
| - visitor->trace(m_builtinEffects);
|
| - visitor->trace(m_namedEffects);
|
| visitor->trace(m_effectRenderer);
|
| visitor->trace(m_effectReferences);
|
| - visitor->trace(m_lastEffect);
|
| #endif
|
| }
|
|
|
| +SVGFilterBuilder::SVGFilterBuilder(
|
| + PassRefPtrWillBeRawPtr<FilterEffect> sourceGraphic,
|
| + PassRefPtrWillBeRawPtr<SVGFilterGraphNodeMap> nodeMap)
|
| + : m_nodeMap(nodeMap)
|
| +{
|
| + RefPtrWillBeRawPtr<FilterEffect> sourceGraphicRef = sourceGraphic;
|
| + m_builtinEffects.add(SourceGraphic::effectName(), sourceGraphicRef);
|
| + m_builtinEffects.add(SourceAlpha::effectName(), SourceAlpha::create(sourceGraphicRef.get()));
|
| + addBuiltinEffects();
|
| +}
|
| +
|
| +void SVGFilterBuilder::addBuiltinEffects()
|
| +{
|
| + if (!m_nodeMap)
|
| + return;
|
| + for (const auto& entry : m_builtinEffects)
|
| + m_nodeMap->addBuiltinEffect(entry.value.get());
|
| +}
|
| +
|
| +// Returns the color-interpolation-filters property of the element.
|
| +static EColorInterpolation colorInterpolationForElement(SVGElement& element, EColorInterpolation parentColorInterpolation)
|
| +{
|
| + if (const LayoutObject* layoutObject = element.layoutObject())
|
| + return layoutObject->styleRef().svgStyle().colorInterpolationFilters();
|
| +
|
| + // No layout has been performed, try to determine the property value
|
| + // "manually" (used by external SVG files.)
|
| + if (const StylePropertySet* propertySet = element.presentationAttributeStyle()) {
|
| + RefPtrWillBeRawPtr<CSSValue> cssValue = propertySet->getPropertyCSSValue(CSSPropertyColorInterpolationFilters);
|
| + if (cssValue && cssValue->isPrimitiveValue()) {
|
| + const CSSPrimitiveValue& primitiveValue = *((CSSPrimitiveValue*)cssValue.get());
|
| + return static_cast<EColorInterpolation>(primitiveValue);
|
| + }
|
| + }
|
| + // 'auto' is the default (per Filter Effects), but since the property is
|
| + // inherited, propagate the parent's value.
|
| + return parentColorInterpolation;
|
| +}
|
| +
|
| +void SVGFilterBuilder::buildGraph(Filter* filter, SVGFilterElement& filterElement, const FloatRect& referenceBox)
|
| +{
|
| + EColorInterpolation filterColorInterpolation = colorInterpolationForElement(filterElement, CI_AUTO);
|
| +
|
| + for (SVGElement* element = Traversal<SVGElement>::firstChild(filterElement); element; element = Traversal<SVGElement>::nextSibling(*element)) {
|
| + if (!element->isFilterEffect())
|
| + continue;
|
| +
|
| + SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element);
|
| + RefPtrWillBeRawPtr<FilterEffect> effect = effectElement->build(this, filter);
|
| + if (!effect)
|
| + continue;
|
| +
|
| + if (m_nodeMap && effectElement->layoutObject())
|
| + m_nodeMap->addPrimitive(effectElement->layoutObject(), effect);
|
| + effectElement->setStandardAttributes(effect.get());
|
| + effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement.primitiveUnits()->currentValue()->enumValue(), referenceBox));
|
| + EColorInterpolation colorInterpolation = colorInterpolationForElement(*effectElement, filterColorInterpolation);
|
| + effect->setOperatingColorSpace(colorInterpolation == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
|
| +
|
| + add(AtomicString(effectElement->result()->currentValue()->value()), effect);
|
| + }
|
| +}
|
| +
|
| void SVGFilterBuilder::add(const AtomicString& id, PassRefPtrWillBeRawPtr<FilterEffect> effect)
|
| {
|
| if (id.isEmpty()) {
|
| @@ -74,42 +171,4 @@ FilterEffect* SVGFilterBuilder::getEffectById(const AtomicString& id) const
|
| return m_builtinEffects.get(SourceGraphic::effectName());
|
| }
|
|
|
| -void SVGFilterBuilder::appendEffectToEffectReferences(PassRefPtrWillBeRawPtr<FilterEffect> prpEffect, LayoutObject* object)
|
| -{
|
| - RefPtrWillBeRawPtr<FilterEffect> effect = prpEffect;
|
| -
|
| - // The effect must be a newly created filter effect.
|
| - ASSERT(!m_effectReferences.contains(effect));
|
| - ASSERT(object && !m_effectRenderer.contains(object));
|
| - m_effectReferences.add(effect, FilterEffectSet());
|
| -
|
| - unsigned numberOfInputEffects = effect->inputEffects().size();
|
| -
|
| - // It is not possible to add the same value to a set twice.
|
| - for (unsigned i = 0; i < numberOfInputEffects; ++i)
|
| - effectReferences(effect->inputEffect(i)).add(effect.get());
|
| - m_effectRenderer.add(object, effect.get());
|
| -}
|
| -
|
| -void SVGFilterBuilder::clearEffects()
|
| -{
|
| - m_lastEffect = nullptr;
|
| - m_namedEffects.clear();
|
| - m_effectReferences.clear();
|
| - m_effectRenderer.clear();
|
| - addBuiltinEffects();
|
| -}
|
| -
|
| -void SVGFilterBuilder::clearResultsRecursive(FilterEffect* effect)
|
| -{
|
| - if (!effect->hasImageFilter())
|
| - return;
|
| -
|
| - effect->clearResult();
|
| -
|
| - FilterEffectSet& effectReferences = this->effectReferences(effect);
|
| - for (FilterEffect* effectReference : effectReferences)
|
| - clearResultsRecursive(effectReference);
|
| -}
|
| -
|
| } // namespace blink
|
|
|