1/*
2 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB.  If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21
22#include "core/svg/SVGFEDropShadowElement.h"
23
24#include "SVGNames.h"
25#include "core/rendering/style/RenderStyle.h"
26#include "core/rendering/style/SVGRenderStyle.h"
27#include "core/svg/SVGElementInstance.h"
28#include "core/svg/SVGParserUtilities.h"
29#include "core/svg/graphics/filters/SVGFilterBuilder.h"
30
31namespace WebCore {
32
33// Animated property definitions
34DEFINE_ANIMATED_STRING(SVGFEDropShadowElement, SVGNames::inAttr, In1, in1)
35DEFINE_ANIMATED_NUMBER(SVGFEDropShadowElement, SVGNames::dxAttr, Dx, dx)
36DEFINE_ANIMATED_NUMBER(SVGFEDropShadowElement, SVGNames::dyAttr, Dy, dy)
37DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEDropShadowElement, SVGNames::stdDeviationAttr, stdDeviationXIdentifier(), StdDeviationX, stdDeviationX)
38DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEDropShadowElement, SVGNames::stdDeviationAttr, stdDeviationYIdentifier(), StdDeviationY, stdDeviationY)
39
40BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEDropShadowElement)
41    REGISTER_LOCAL_ANIMATED_PROPERTY(in1)
42    REGISTER_LOCAL_ANIMATED_PROPERTY(dx)
43    REGISTER_LOCAL_ANIMATED_PROPERTY(dy)
44    REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationX)
45    REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationY)
46    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
47END_REGISTER_ANIMATED_PROPERTIES
48
49inline SVGFEDropShadowElement::SVGFEDropShadowElement(Document& document)
50    : SVGFilterPrimitiveStandardAttributes(SVGNames::feDropShadowTag, document)
51    , m_dx(2)
52    , m_dy(2)
53    , m_stdDeviationX(2)
54    , m_stdDeviationY(2)
55{
56    ScriptWrappable::init(this);
57    registerAnimatedPropertiesForSVGFEDropShadowElement();
58}
59
60PassRefPtr<SVGFEDropShadowElement> SVGFEDropShadowElement::create(Document& document)
61{
62    return adoptRef(new SVGFEDropShadowElement(document));
63}
64
65const AtomicString& SVGFEDropShadowElement::stdDeviationXIdentifier()
66{
67    DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGStdDeviationX", AtomicString::ConstructFromLiteral));
68    return s_identifier;
69}
70
71const AtomicString& SVGFEDropShadowElement::stdDeviationYIdentifier()
72{
73    DEFINE_STATIC_LOCAL(AtomicString, s_identifier, ("SVGStdDeviationY", AtomicString::ConstructFromLiteral));
74    return s_identifier;
75}
76
77void SVGFEDropShadowElement::setStdDeviation(float x, float y)
78{
79    setStdDeviationXBaseValue(x);
80    setStdDeviationYBaseValue(y);
81    invalidate();
82}
83
84bool SVGFEDropShadowElement::isSupportedAttribute(const QualifiedName& attrName)
85{
86    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
87    if (supportedAttributes.isEmpty()) {
88        supportedAttributes.add(SVGNames::inAttr);
89        supportedAttributes.add(SVGNames::dxAttr);
90        supportedAttributes.add(SVGNames::dyAttr);
91        supportedAttributes.add(SVGNames::stdDeviationAttr);
92    }
93    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
94}
95
96void SVGFEDropShadowElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
97{
98    if (!isSupportedAttribute(name)) {
99        SVGFilterPrimitiveStandardAttributes::parseAttribute(name, value);
100        return;
101    }
102
103    if (name == SVGNames::stdDeviationAttr) {
104        float x, y;
105        if (parseNumberOptionalNumber(value, x, y)) {
106            setStdDeviationXBaseValue(x);
107            setStdDeviationYBaseValue(y);
108        }
109        return;
110    }
111
112    if (name == SVGNames::inAttr) {
113        setIn1BaseValue(value);
114        return;
115    }
116
117    if (name == SVGNames::dxAttr) {
118        setDxBaseValue(value.toFloat());
119        return;
120    }
121
122    if (name == SVGNames::dyAttr) {
123        setDyBaseValue(value.toFloat());
124        return;
125    }
126
127    ASSERT_NOT_REACHED();
128}
129
130void SVGFEDropShadowElement::svgAttributeChanged(const QualifiedName& attrName)
131{
132    if (!isSupportedAttribute(attrName)) {
133        SVGFilterPrimitiveStandardAttributes::svgAttributeChanged(attrName);
134        return;
135    }
136
137    SVGElementInstance::InvalidationGuard invalidationGuard(this);
138
139    if (attrName == SVGNames::inAttr
140        || attrName == SVGNames::stdDeviationAttr
141        || attrName == SVGNames::dxAttr
142        || attrName == SVGNames::dyAttr) {
143        invalidate();
144        return;
145    }
146
147    ASSERT_NOT_REACHED();
148}
149
150PassRefPtr<FilterEffect> SVGFEDropShadowElement::build(SVGFilterBuilder* filterBuilder, Filter* filter)
151{
152    RenderObject* renderer = this->renderer();
153    if (!renderer)
154        return 0;
155
156    if (stdDeviationXCurrentValue() < 0 || stdDeviationYCurrentValue() < 0)
157        return 0;
158
159    ASSERT(renderer->style());
160    const SVGRenderStyle* svgStyle = renderer->style()->svgStyle();
161
162    Color color = svgStyle->floodColor();
163    float opacity = svgStyle->floodOpacity();
164
165    FilterEffect* input1 = filterBuilder->getEffectById(in1CurrentValue());
166    if (!input1)
167        return 0;
168
169    RefPtr<FilterEffect> effect = FEDropShadow::create(filter, stdDeviationXCurrentValue(), stdDeviationYCurrentValue(), dxCurrentValue(), dyCurrentValue(), color, opacity);
170    effect->inputEffects().append(input1);
171    return effect.release();
172}
173
174}
175