1/*
2 * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22#include "config.h"
23
24#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
25
26#include "core/SVGNames.h"
27#include "platform/graphics/filters/FilterEffect.h"
28#include "core/rendering/svg/RenderSVGResourceFilterPrimitive.h"
29#include "core/svg/SVGLength.h"
30
31namespace blink {
32
33SVGFilterPrimitiveStandardAttributes::SVGFilterPrimitiveStandardAttributes(const QualifiedName& tagName, Document& document)
34    : SVGElement(tagName, document)
35    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth), AllowNegativeLengths))
36    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight), AllowNegativeLengths))
37    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth), ForbidNegativeLengths))
38    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight), ForbidNegativeLengths))
39    , m_result(SVGAnimatedString::create(this, SVGNames::resultAttr, SVGString::create()))
40{
41    // Spec: If the x/y attribute is not specified, the effect is as if a value of "0%" were specified.
42    m_x->setDefaultValueAsString("0%");
43    m_y->setDefaultValueAsString("0%");
44
45    // Spec: If the width/height attribute is not specified, the effect is as if a value of "100%" were specified.
46    m_width->setDefaultValueAsString("100%");
47    m_height->setDefaultValueAsString("100%");
48
49    addToPropertyMap(m_x);
50    addToPropertyMap(m_y);
51    addToPropertyMap(m_width);
52    addToPropertyMap(m_height);
53    addToPropertyMap(m_result);
54}
55
56bool SVGFilterPrimitiveStandardAttributes::isSupportedAttribute(const QualifiedName& attrName)
57{
58    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
59    if (supportedAttributes.isEmpty()) {
60        supportedAttributes.add(SVGNames::xAttr);
61        supportedAttributes.add(SVGNames::yAttr);
62        supportedAttributes.add(SVGNames::widthAttr);
63        supportedAttributes.add(SVGNames::heightAttr);
64        supportedAttributes.add(SVGNames::resultAttr);
65    }
66    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
67}
68
69void SVGFilterPrimitiveStandardAttributes::parseAttribute(const QualifiedName& name, const AtomicString& value)
70{
71    parseAttributeNew(name, value);
72}
73
74bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&)
75{
76    // When all filters support this method, it will be changed to a pure virtual method.
77    ASSERT_NOT_REACHED();
78    return false;
79}
80
81void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
82{
83    if (!isSupportedAttribute(attrName)) {
84        SVGElement::svgAttributeChanged(attrName);
85        return;
86    }
87
88    SVGElement::InvalidationGuard invalidationGuard(this);
89    invalidate();
90}
91
92void SVGFilterPrimitiveStandardAttributes::childrenChanged(const ChildrenChange& change)
93{
94    SVGElement::childrenChanged(change);
95
96    if (!change.byParser)
97        invalidate();
98}
99
100void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(FilterEffect* filterEffect) const
101{
102    ASSERT(filterEffect);
103    if (!filterEffect)
104        return;
105
106    if (hasAttribute(SVGNames::xAttr))
107        filterEffect->setHasX(true);
108    if (hasAttribute(SVGNames::yAttr))
109        filterEffect->setHasY(true);
110    if (hasAttribute(SVGNames::widthAttr))
111        filterEffect->setHasWidth(true);
112    if (hasAttribute(SVGNames::heightAttr))
113        filterEffect->setHasHeight(true);
114}
115
116RenderObject* SVGFilterPrimitiveStandardAttributes::createRenderer(RenderStyle*)
117{
118    return new RenderSVGResourceFilterPrimitive(this);
119}
120
121bool SVGFilterPrimitiveStandardAttributes::rendererIsNeeded(const RenderStyle& style)
122{
123    if (isSVGFilterElement(parentNode()))
124        return SVGElement::rendererIsNeeded(style);
125
126    return false;
127}
128
129void SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged(const QualifiedName& attribute)
130{
131    if (RenderObject* primitiveRenderer = renderer())
132        static_cast<RenderSVGResourceFilterPrimitive*>(primitiveRenderer)->primitiveAttributeChanged(attribute);
133}
134
135void invalidateFilterPrimitiveParent(SVGElement* element)
136{
137    if (!element)
138        return;
139
140    ContainerNode* parent = element->parentNode();
141
142    if (!parent)
143        return;
144
145    RenderObject* renderer = parent->renderer();
146    if (!renderer || !renderer->isSVGResourceFilterPrimitive())
147        return;
148
149    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
150}
151
152}
153