2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
31 #ifndef NewSVGAnimatedProperty_h
32 #define NewSVGAnimatedProperty_h
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"
48 class NewSVGAnimatedPropertyBase : public RefCounted<NewSVGAnimatedPropertyBase> {
50 virtual ~NewSVGAnimatedPropertyBase();
52 virtual NewSVGPropertyBase* currentValueBase() = 0;
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();
61 virtual bool needsSynchronizeAttribute() = 0;
62 virtual void synchronizeAttribute();
64 AnimatedPropertyType type() const
69 SVGElement* contextElement() const
71 return m_contextElement;
74 const QualifiedName& attributeName() const
76 return m_attributeName;
79 bool isAnimating() const
84 bool isReadOnly() const
94 bool isSpecified() const;
97 NewSVGAnimatedPropertyBase(AnimatedPropertyType, SVGElement*, const QualifiedName& attributeName);
101 const AnimatedPropertyType m_type;
105 // This reference is kept alive from V8 wrapper
106 SVGElement* m_contextElement;
108 const QualifiedName& m_attributeName;
110 WTF_MAKE_NONCOPYABLE(NewSVGAnimatedPropertyBase);
113 template <typename Property>
114 class NewSVGAnimatedPropertyCommon : public NewSVGAnimatedPropertyBase {
116 Property* baseValue()
118 return m_baseValue.get();
121 Property* currentValue()
123 return m_currentValue ? m_currentValue.get() : m_baseValue.get();
126 const Property* currentValue() const
128 return const_cast<NewSVGAnimatedPropertyCommon*>(this)->currentValue();
131 virtual NewSVGPropertyBase* currentValueBase() OVERRIDE
133 return currentValue();
136 void setBaseValueAsString(const String& value, SVGParsingError& parseError)
138 TrackExceptionState es;
140 m_baseValue->setValueAsString(value, es);
142 if (es.hadException())
143 parseError = ParsingAttributeFailedError;
146 virtual PassRefPtr<NewSVGPropertyBase> createAnimatedValue() OVERRIDE
148 return m_baseValue->clone();
151 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> passValue) OVERRIDE
153 ASSERT(isAnimating());
155 RefPtr<NewSVGPropertyBase> value = passValue;
156 ASSERT(value->type() == Property::classType());
157 m_currentValue = static_pointer_cast<Property>(value.release());
160 virtual void animationEnded() OVERRIDE
162 NewSVGAnimatedPropertyBase::animationEnded();
164 ASSERT(m_currentValue);
165 m_currentValue.clear();
169 NewSVGAnimatedPropertyCommon(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
170 : NewSVGAnimatedPropertyBase(Property::classType(), contextElement, attributeName)
171 , m_baseValue(initialValue)
176 RefPtr<Property> m_baseValue;
177 RefPtr<Property> m_currentValue;
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> {
186 static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
188 return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue));
191 virtual bool needsSynchronizeAttribute() OVERRIDE
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();
198 virtual void synchronizeAttribute() OVERRIDE
200 NewSVGAnimatedPropertyBase::synchronizeAttribute();
201 m_baseValueUpdated = false;
204 // SVGAnimated* DOM Spec implementations:
206 // baseVal()/setBaseVal()/animVal() are only to be used from SVG DOM implementation.
207 // Use currentValue() from C++ code.
208 PrimitiveType baseVal()
210 return this->baseValue()->value();
213 void setBaseVal(PrimitiveType value, WebCore::ExceptionState& exceptionState)
215 if (this->isReadOnly()) {
216 exceptionState.throwDOMException(NoModificationAllowedError, "The attribute is read-only.");
220 this->baseValue()->setValue(value);
221 m_baseValueUpdated = true;
223 ASSERT(this->attributeName() != nullQName());
224 this->contextElement()->invalidateSVGAttributes();
225 this->contextElement()->svgAttributeChanged(this->attributeName());
228 PrimitiveType animVal()
230 return this->currentValue()->value();
234 NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
235 : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue)
236 , m_baseValueUpdated(false)
240 bool m_baseValueUpdated;
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> {
250 static PassRefPtr<NewSVGAnimatedProperty<Property> > create(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
252 return adoptRef(new NewSVGAnimatedProperty<Property>(contextElement, attributeName, initialValue));
255 virtual void setAnimatedValue(PassRefPtr<NewSVGPropertyBase> value) OVERRIDE
257 NewSVGAnimatedPropertyCommon<Property>::setAnimatedValue(value);
258 updateAnimValTearOffIfNeeded();
261 virtual void animationEnded() OVERRIDE
263 NewSVGAnimatedPropertyCommon<Property>::animationEnded();
264 updateAnimValTearOffIfNeeded();
267 virtual bool needsSynchronizeAttribute() OVERRIDE
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();
274 // SVGAnimated* DOM Spec implementations:
276 // baseVal()/animVal() are only to be used from SVG DOM implementation.
277 // Use currentValue() from C++ code.
278 virtual TearOffType* baseVal()
280 if (!m_baseValTearOff) {
281 m_baseValTearOff = TearOffType::create(this->baseValue(), this->contextElement(), PropertyIsNotAnimVal, this->attributeName());
282 if (this->isReadOnly())
283 m_baseValTearOff->setIsReadOnlyProperty();
286 return m_baseValTearOff.get();
289 TearOffType* animVal()
291 if (!m_animValTearOff)
292 m_animValTearOff = TearOffType::create(this->currentValue(), this->contextElement(), PropertyIsAnimVal, this->attributeName());
294 return m_animValTearOff.get();
298 NewSVGAnimatedProperty(SVGElement* contextElement, const QualifiedName& attributeName, PassRefPtr<Property> initialValue)
299 : NewSVGAnimatedPropertyCommon<Property>(contextElement, attributeName, initialValue)
304 void updateAnimValTearOffIfNeeded()
306 if (m_animValTearOff)
307 m_animValTearOff->setTarget(this->currentValue());
310 // When still (not animated):
311 // Both m_animValTearOff and m_baseValTearOff target m_baseValue.
313 // m_animValTearOff targets m_currentValue.
314 // m_baseValTearOff targets m_baseValue.
315 RefPtr<TearOffType> m_baseValTearOff;
316 RefPtr<TearOffType> m_animValTearOff;
321 #endif // NewSVGAnimatedProperty_h