Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / properties / NewSVGAnimatedProperty.h
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10 G*     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifndef NewSVGAnimatedProperty_h
32 #define NewSVGAnimatedProperty_h
33
34 #include "bindings/v8/ExceptionStatePlaceholder.h"
35 #include "bindings/v8/ScriptWrappable.h"
36 #include "core/dom/ExceptionCode.h"
37 #include "core/svg/SVGParsingError.h"
38 #include "core/svg/properties/NewSVGPropertyTearOff.h"
39 #include "core/svg/properties/SVGPropertyInfo.h"
40 #include "wtf/Noncopyable.h"
41 #include "wtf/PassRefPtr.h"
42 #include "wtf/RefCounted.h"
43
44 namespace WebCore {
45
46 class SVGElement;
47
48 class NewSVGAnimatedPropertyBase : public RefCounted<NewSVGAnimatedPropertyBase> {
49 public:
50     virtual ~NewSVGAnimatedPropertyBase();
51
52     virtual NewSVGPropertyBase* currentValueBase() = 0;
53
54     virtual void animationStarted();
55     virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() = 0;
56     virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase>) = 0;
57     virtual void animationEnded();
58     virtual void animValWillChange();
59     virtual void animValDidChange();
60
61     virtual bool needsSynchronizeAttribute() = 0;
62     virtual void synchronizeAttribute();
63
64     AnimatedPropertyType type() const
65     {
66         return m_type;
67     }
68
69     SVGElement* contextElement() const
70     {
71         return m_contextElement;
72     }
73
74     const QualifiedName& attributeName() const
75     {
76         return m_attributeName;
77     }
78
79     bool isAnimating() const
80     {
81         return m_isAnimating;
82     }
83
84     bool isReadOnly() const
85     {
86         return m_isReadOnly;
87     }
88
89     void setReadOnly()
90     {
91         m_isReadOnly = true;
92     }
93
94     bool isSpecified() const;
95
96 protected:
97     NewSVGAnimatedPropertyBase(AnimatedPropertyType, SVGElement*, const QualifiedName& attributeName);
98     void commitChange();
99
100 private:
101     const AnimatedPropertyType m_type;
102     bool m_isReadOnly;
103     bool m_isAnimating;
104
105     // This reference is kept alive from V8 wrapper
106     SVGElement* m_contextElement;
107
108     const QualifiedName& m_attributeName;
109
110     WTF_MAKE_NONCOPYABLE(NewSVGAnimatedPropertyBase);
111 };
112
113 template <typename Property>
114 class NewSVGAnimatedPropertyCommon : public NewSVGAnimatedPropertyBase {
115 public:
116     Property* baseValue()
117     {
118         return m_baseValue.get();
119     }
120
121     Property* currentValue()
122     {
123         return m_currentValue ? m_currentValue.get() : m_baseValue.get();
124     }
125
126     const Property* currentValue() const
127     {
128         return const_cast<NewSVGAnimatedPropertyCommon*>(this)->currentValue();
129     }
130
131     virtual NewSVGPropertyBase* currentValueBase() OVERRIDE
132     {
133         return currentValue();
134     }
135
136     void setBaseValueAsString(const String& value, SVGParsingError& parseError)
137     {
138         TrackExceptionState es;
139
140         m_baseValue->setValueAsString(value, es);
141
142         if (es.hadException())
143             parseError = ParsingAttributeFailedError;
144     }
145
146     virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() OVERRIDE
147     {
148         return m_baseValue->clone();
149     }
150
151     virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> passValue) OVERRIDE
152     {
153         ASSERT(isAnimating());
154
155         RefPtr<NewSVGPropertyBase> value = passValue;
156         ASSERT(value->type() == Property::classType());
157         m_currentValue = static_pointer_cast<Property>(value.release());
158     }
159
160     virtual void animationEnded() OVERRIDE
161     {
162         NewSVGAnimatedPropertyBase::animationEnded();
163
164         ASSERT(m_currentValue);
165         m_currentValue.clear();
166     }
167
168 protected:
169     NewSVGAnimatedPropertyCommon(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
170         : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attributeName)
171         , m_baseValue(initialValue)
172     {
173     }
174
175 private:
176     RefPtr<Property> m_baseValue;
177     RefPtr<Property> m_currentValue;
178 };
179
180 // Implementation of SVGAnimatedProperty which uses primitive types.
181 // This is for classes which return primitive type for its "animVal".
182 // Examples are SVGAnimatedBoolean, SVGAnimatedNumber, etc.
183 template <typename Property, typename TearOffType = typename Property::TearOffType, typename PrimitiveType = typename Property::PrimitiveType>
184 class NewSVGAnimatedProperty : public NewSVGAnimatedPropertyCommon<Property> {
185 public:
186     static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
187     {
188         return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue));
189     }
190
191     virtual bool needsSynchronizeAttribute() OVERRIDE
192     {
193         // DOM attribute synchronization is only needed if tear-off is being touched from javascript or the property is being animated.
194         // This prevents unnecessary attribute creation on target element.
195         return m_baseValueUpdated || this->isAnimating();
196     }
197
198     virtual void synchronizeAttribute() OVERRIDE
199     {
200         NewSVGAnimatedPropertyBase::synchronizeAttribute();
201         m_baseValueUpdated = false;
202     }
203
204     // SVGAnimated* DOM Spec implementations:
205
206     // baseVal()/setBaseVal()/animVal() are only to be used from SVG DOM implementation.
207     // Use currentValue() from C++ code.
208     PrimitiveType baseVal()
209     {
210         return this->baseValue()->value();
211     }
212
213     void setBaseVal(PrimitiveType value, WebCore::ExceptionState& exceptionState)
214     {
215         if (this->isReadOnly()) {
216             exceptionState.throwDOMException(NoModificationAllowedError, "The attribute is read-only.");
217             return;
218         }
219
220         this->baseValue()->setValue(value);
221         m_baseValueUpdated = true;
222
223         ASSERT(this->attributeName() != nullQName());
224         this->contextElement()->invalidateSVGAttributes();
225         this->contextElement()->svgAttributeChanged(this->attributeName());
226     }
227
228     PrimitiveType animVal()
229     {
230         return this->currentValue()->value();
231     }
232
233 protected:
234     NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
235         : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue)
236         , m_baseValueUpdated(false)
237     {
238     }
239
240     bool m_baseValueUpdated;
241 };
242
243 // Implementation of SVGAnimatedProperty which uses tear-off value types.
244 // These classes has "void" for its PrimitiveType.
245 // This is for classes which return special type for its "animVal".
246 // Examples are SVGAnimatedLength, SVGAnimatedRect, SVGAnimated*List, etc.
247 template <typename Property, typename TearOffType>
248 class NewSVGAnimatedProperty<Property, TearOffType, void> : public NewSVGAnimatedPropertyCommon<Property> {
249 public:
250     static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
251     {
252         return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue));
253     }
254
255     virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) OVERRIDE
256     {
257         NewSVGAnimatedPropertyCommon<Property>::setAnimatedValue(value);
258         updateAnimValTearOffIfNeeded();
259     }
260
261     virtual void animationEnded() OVERRIDE
262     {
263         NewSVGAnimatedPropertyCommon<Property>::animationEnded();
264         updateAnimValTearOffIfNeeded();
265     }
266
267     virtual bool needsSynchronizeAttribute() OVERRIDE
268     {
269         // DOM attribute synchronization is only needed if tear-off is being touched from javascript or the property is being animated.
270         // This prevents unnecessary attribute creation on target element.
271         return m_baseValTearOff || this->isAnimating();
272     }
273
274     // SVGAnimated* DOM Spec implementations:
275
276     // baseVal()/animVal() are only to be used from SVG DOM implementation.
277     // Use currentValue() from C++ code.
278     virtual TearOffType* baseVal()
279     {
280         if (!m_baseValTearOff) {
281             m_baseValTearOff = TearOffType::create(this->baseValue(), this->contextElement(), PropertyIsNotAnimVal, this->attributeName());
282             if (this->isReadOnly())
283                 m_baseValTearOff->setIsReadOnlyProperty();
284         }
285
286         return m_baseValTearOff.get();
287     }
288
289     TearOffType* animVal()
290     {
291         if (!m_animValTearOff)
292             m_animValTearOff = TearOffType::create(this->currentValue(), this->contextElement(), PropertyIsAnimVal, this->attributeName());
293
294         return m_animValTearOff.get();
295     }
296
297 protected:
298     NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
299         : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue)
300     {
301     }
302
303 private:
304     void updateAnimValTearOffIfNeeded()
305     {
306         if (m_animValTearOff)
307             m_animValTearOff->setTarget(this->currentValue());
308     }
309
310     // When still (not animated):
311     //     Both m_animValTearOff and m_baseValTearOff target m_baseValue.
312     // When animated:
313     //     m_animValTearOff targets m_currentValue.
314     //     m_baseValTearOff targets m_baseValue.
315     RefPtr<TearOffType> m_baseValTearOff;
316     RefPtr<TearOffType> m_animValTearOff;
317 };
318
319 }
320
321 #endif // NewSVGAnimatedProperty_h