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 "SVGNames.h"
27#include "platform/graphics/filters/FilterEffect.h"
28#include "core/rendering/svg/RenderSVGResourceFilterPrimitive.h"
29#include "core/svg/SVGElementInstance.h"
30#include "core/svg/SVGLength.h"
31
32namespace WebCore {
33
34// Animated property definitions
35DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::xAttr, X, x)
36DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::yAttr, Y, y)
37DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::widthAttr, Width, width)
38DEFINE_ANIMATED_LENGTH(SVGFilterPrimitiveStandardAttributes, SVGNames::heightAttr, Height, height)
39DEFINE_ANIMATED_STRING(SVGFilterPrimitiveStandardAttributes, SVGNames::resultAttr, Result, result)
40
41BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
42    REGISTER_LOCAL_ANIMATED_PROPERTY(x)
43    REGISTER_LOCAL_ANIMATED_PROPERTY(y)
44    REGISTER_LOCAL_ANIMATED_PROPERTY(width)
45    REGISTER_LOCAL_ANIMATED_PROPERTY(height)
46    REGISTER_LOCAL_ANIMATED_PROPERTY(result)
47    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
48END_REGISTER_ANIMATED_PROPERTIES
49
50SVGFilterPrimitiveStandardAttributes::SVGFilterPrimitiveStandardAttributes(const QualifiedName& tagName, Document& document)
51    : SVGElement(tagName, document)
52    , m_x(LengthModeWidth, "0%")
53    , m_y(LengthModeHeight, "0%")
54    , m_width(LengthModeWidth, "100%")
55    , m_height(LengthModeHeight, "100%")
56{
57    // Spec: If the x/y attribute is not specified, the effect is as if a value of "0%" were specified.
58    // Spec: If the width/height attribute is not specified, the effect is as if a value of "100%" were specified.
59    registerAnimatedPropertiesForSVGFilterPrimitiveStandardAttributes();
60}
61
62bool SVGFilterPrimitiveStandardAttributes::isSupportedAttribute(const QualifiedName& attrName)
63{
64    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
65    if (supportedAttributes.isEmpty()) {
66        supportedAttributes.add(SVGNames::xAttr);
67        supportedAttributes.add(SVGNames::yAttr);
68        supportedAttributes.add(SVGNames::widthAttr);
69        supportedAttributes.add(SVGNames::heightAttr);
70        supportedAttributes.add(SVGNames::resultAttr);
71    }
72    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
73}
74
75void SVGFilterPrimitiveStandardAttributes::parseAttribute(const QualifiedName& name, const AtomicString& value)
76{
77    SVGParsingError parseError = NoError;
78
79    if (!isSupportedAttribute(name))
80        SVGElement::parseAttribute(name, value);
81    else if (name == SVGNames::xAttr)
82        setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
83    else if (name == SVGNames::yAttr)
84        setYBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
85    else if (name == SVGNames::widthAttr)
86        setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
87    else if (name == SVGNames::heightAttr)
88        setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError));
89    else if (name == SVGNames::resultAttr)
90        setResultBaseValue(value);
91    else
92        ASSERT_NOT_REACHED();
93
94    reportAttributeParsingError(parseError, name, value);
95}
96
97bool SVGFilterPrimitiveStandardAttributes::setFilterEffectAttribute(FilterEffect*, const QualifiedName&)
98{
99    // When all filters support this method, it will be changed to a pure virtual method.
100    ASSERT_NOT_REACHED();
101    return false;
102}
103
104void SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(const QualifiedName& attrName)
105{
106    if (!isSupportedAttribute(attrName)) {
107        SVGElement::svgAttributeChanged(attrName);
108        return;
109    }
110
111    SVGElementInstance::InvalidationGuard invalidationGuard(this);
112    invalidate();
113}
114
115void SVGFilterPrimitiveStandardAttributes::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
116{
117    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
118
119    if (!changedByParser)
120        invalidate();
121}
122
123void SVGFilterPrimitiveStandardAttributes::setStandardAttributes(FilterEffect* filterEffect) const
124{
125    ASSERT(filterEffect);
126    if (!filterEffect)
127        return;
128
129    if (hasAttribute(SVGNames::xAttr))
130        filterEffect->setHasX(true);
131    if (hasAttribute(SVGNames::yAttr))
132        filterEffect->setHasY(true);
133    if (hasAttribute(SVGNames::widthAttr))
134        filterEffect->setHasWidth(true);
135    if (hasAttribute(SVGNames::heightAttr))
136        filterEffect->setHasHeight(true);
137}
138
139RenderObject* SVGFilterPrimitiveStandardAttributes::createRenderer(RenderStyle*)
140{
141    return new RenderSVGResourceFilterPrimitive(this);
142}
143
144bool SVGFilterPrimitiveStandardAttributes::rendererIsNeeded(const RenderStyle& style)
145{
146    if (parentNode() && (parentNode()->hasTagName(SVGNames::filterTag)))
147        return SVGElement::rendererIsNeeded(style);
148
149    return false;
150}
151
152void SVGFilterPrimitiveStandardAttributes::primitiveAttributeChanged(const QualifiedName& attribute)
153{
154    if (RenderObject* primitiveRenderer = renderer())
155        static_cast<RenderSVGResourceFilterPrimitive*>(primitiveRenderer)->primitiveAttributeChanged(attribute);
156}
157
158void invalidateFilterPrimitiveParent(SVGElement* element)
159{
160    if (!element)
161        return;
162
163    ContainerNode* parent = element->parentNode();
164
165    if (!parent)
166        return;
167
168    RenderObject* renderer = parent->renderer();
169    if (!renderer || !renderer->isSVGResourceFilterPrimitive())
170        return;
171
172    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
173}
174
175}
176