Rubber-stamped by Brady Eidson.
[webbrowser.git] / WebCore / svg / SVGAnimatedProperty.h
blob984046fbe3c59878f7d95be6633c821ceb3b1031
1 /*
2 Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 Copyright (C) Research In Motion Limited 2009. All rights reserved.
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
21 #ifndef SVGAnimatedProperty_h
22 #define SVGAnimatedProperty_h
24 #if ENABLE(SVG)
25 #include "SVGAnimatedTemplate.h"
26 #include "SVGDocumentExtensions.h"
27 #include "SynchronizableTypeWrapper.h"
29 namespace WebCore {
31 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
32 class SVGAnimatedProperty;
34 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
35 class SVGAnimatedPropertyTearOff : public SVGAnimatedTemplate<DecoratedType> {
36 public:
37 typedef SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName> Self;
38 typedef SVGAnimatedProperty<OwnerType, AnimatedType, TagName, PropertyName> Creator;
40 static PassRefPtr<Self> create(const Creator& creator, const OwnerElement* owner, const QualifiedName& attributeName)
42 return adoptRef(new Self(creator, owner, attributeName));
45 virtual DecoratedType baseVal() const;
46 virtual void setBaseVal(DecoratedType);
48 virtual DecoratedType animVal() const;
49 virtual void setAnimVal(DecoratedType);
51 private:
52 SVGAnimatedPropertyTearOff(const Creator&, const OwnerElement*, const QualifiedName& attributeName);
54 Creator& m_creator;
55 RefPtr<OwnerElement> m_ownerElement;
58 // Helper templates mapping owner types to owner elements (for SVG*Element OwnerType is equal to OwnerElement, for non-SVG*Element derived types, they're different)
59 template<typename OwnerType, bool isDerivedFromSVGElement>
60 struct GetOwnerElementForType;
62 template<typename OwnerType>
63 struct IsDerivedFromSVGElement;
65 // Helper template used for synchronizing SVG <-> XML properties
66 template<typename OwnerType, typename DecoratedType, bool isDerivedFromSVGElement>
67 struct PropertySynchronizer;
69 // Abstract base class
70 class SVGAnimatedPropertyBase : public Noncopyable {
71 public:
72 virtual ~SVGAnimatedPropertyBase() { }
73 virtual void synchronize() const = 0;
74 virtual void startAnimation() const = 0;
75 virtual void stopAnimation() = 0;
78 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
79 class SVGAnimatedProperty : public SVGAnimatedPropertyBase {
80 public:
81 typedef OwnerTypeArg OwnerType;
82 typedef AnimatedTypeArg AnimatedType;
84 typedef typename SVGAnimatedTypeValue<AnimatedType>::StorableType StorableType;
85 typedef typename SVGAnimatedTypeValue<AnimatedType>::DecoratedType DecoratedType;
87 typedef GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value> OwnerElementForType;
88 typedef typename OwnerElementForType::OwnerElement OwnerElement;
89 typedef SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName> TearOff;
91 // attributeName & attributeIdentifier may differ. For SVGMarkerElement, there are two exposed SVG animatable
92 // properties: orientType & orientAngle, though only one DOM attribute "orient", handle these cases!
93 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName);
94 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier);
96 // "Forwarding constructors" for primitive type assignment with more than one argument
97 template<typename T1>
98 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
99 const T1&);
101 template<typename T1>
102 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
103 const T1&);
105 template<typename T1, typename T2>
106 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
107 const T1&, const T2&);
109 template<typename T1, typename T2>
110 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
111 const T1&, const T2&);
113 template<typename T1, typename T2, typename T3>
114 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
115 const T1&, const T2&, const T3&);
117 template<typename T1, typename T2, typename T3>
118 SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
119 const T1&, const T2&, const T3&);
121 DecoratedType value() const;
122 void setValue(DecoratedType);
124 DecoratedType baseValue() const;
125 void setBaseValue(DecoratedType);
127 // Tear offs only used by bindings, never in internal code
128 PassRefPtr<TearOff> animatedTearOff() const;
130 void registerProperty();
131 virtual void synchronize() const;
133 void startAnimation() const;
134 void stopAnimation();
136 private:
137 const OwnerElement* ownerElement() const;
139 private:
140 // We're a member variable on stack, living in OwnerType, NO need to ref here.
141 const OwnerType* m_ownerType;
143 const QualifiedName& m_attributeName;
144 const AtomicString& m_attributeIdentifier;
146 mutable SynchronizableTypeWrapper<StorableType> m_value;
148 #ifndef NDEBUG
149 bool m_registered;
150 #endif
153 // SVGAnimatedPropertyTearOff implementation
154 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
155 SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::SVGAnimatedPropertyTearOff(const Creator& creator,
156 const OwnerElement* owner,
157 const QualifiedName& attributeName)
158 : SVGAnimatedTemplate<DecoratedType>(attributeName)
159 , m_creator(const_cast<Creator&>(creator))
160 , m_ownerElement(const_cast<OwnerElement*>(owner))
162 ASSERT(m_ownerElement);
165 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
166 DecoratedType SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::baseVal() const
168 return m_creator.baseValue();
171 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
172 void SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::setBaseVal(DecoratedType newBaseVal)
174 m_creator.setBaseValue(newBaseVal);
177 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
178 DecoratedType SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::animVal() const
180 return m_creator.value();
183 template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
184 void SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::setAnimVal(DecoratedType newAnimVal)
186 m_creator.setValue(newAnimVal);
189 // SVGAnimatedProperty implementation
190 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
191 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
192 const QualifiedName& attributeName)
193 : m_ownerType(owner)
194 , m_attributeName(attributeName)
195 , m_attributeIdentifier(attributeName.localName())
196 , m_value()
197 #ifndef NDEBUG
198 , m_registered(false)
199 #endif
201 ASSERT(m_ownerType);
202 registerProperty();
205 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
206 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
207 const QualifiedName& attributeName,
208 const AtomicString& attributeIdentifier)
209 : m_ownerType(owner)
210 , m_attributeName(attributeName)
211 , m_attributeIdentifier(attributeIdentifier)
212 , m_value()
213 #ifndef NDEBUG
214 , m_registered(false)
215 #endif
217 ASSERT(m_ownerType);
218 registerProperty();
221 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
222 template<typename T1>
223 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
224 const QualifiedName& attributeName,
225 const T1& arg1)
226 : m_ownerType(owner)
227 , m_attributeName(attributeName)
228 , m_attributeIdentifier(attributeName.localName())
229 , m_value(arg1)
230 #ifndef NDEBUG
231 , m_registered(false)
232 #endif
234 ASSERT(m_ownerType);
235 registerProperty();
238 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
239 template<typename T1>
240 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
241 const QualifiedName& attributeName,
242 const AtomicString& attributeIdentifier,
243 const T1& arg1)
244 : m_ownerType(owner)
245 , m_attributeName(attributeName)
246 , m_attributeIdentifier(attributeIdentifier)
247 , m_value(arg1)
248 #ifndef NDEBUG
249 , m_registered(false)
250 #endif
252 ASSERT(m_ownerType);
253 registerProperty();
256 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
257 template<typename T1, typename T2>
258 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
259 const QualifiedName& attributeName,
260 const T1& arg1,
261 const T2& arg2)
262 : m_ownerType(owner)
263 , m_attributeName(attributeName)
264 , m_attributeIdentifier(attributeName.localName())
265 , m_value(arg1, arg2)
266 #ifndef NDEBUG
267 , m_registered(false)
268 #endif
270 ASSERT(m_ownerType);
271 registerProperty();
274 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
275 template<typename T1, typename T2>
276 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
277 const QualifiedName& attributeName,
278 const AtomicString& attributeIdentifier,
279 const T1& arg1,
280 const T2& arg2)
281 : m_ownerType(owner)
282 , m_attributeName(attributeName)
283 , m_attributeIdentifier(attributeIdentifier)
284 , m_value(arg1, arg2)
285 #ifndef NDEBUG
286 , m_registered(false)
287 #endif
289 ASSERT(m_ownerType);
290 registerProperty();
293 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
294 template<typename T1, typename T2, typename T3>
295 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
296 const QualifiedName& attributeName,
297 const T1& arg1,
298 const T2& arg2,
299 const T3& arg3)
300 : m_ownerType(owner)
301 , m_attributeName(attributeName)
302 , m_attributeIdentifier(attributeName.localName())
303 , m_value(arg1, arg2, arg3)
304 #ifndef NDEBUG
305 , m_registered(false)
306 #endif
308 ASSERT(m_ownerType);
309 registerProperty();
312 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
313 template<typename T1, typename T2, typename T3>
314 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
315 const QualifiedName& attributeName,
316 const AtomicString& attributeIdentifier,
317 const T1& arg1,
318 const T2& arg2,
319 const T3& arg3)
320 : m_ownerType(owner)
321 , m_attributeName(attributeName)
322 , m_attributeIdentifier(attributeIdentifier)
323 , m_value(arg1, arg2, arg3)
324 #ifndef NDEBUG
325 , m_registered(false)
326 #endif
328 ASSERT(m_ownerType);
329 registerProperty();
332 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
333 typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::DecoratedType
334 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::value() const
336 ASSERT(m_registered);
337 return m_value;
340 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
341 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::setValue(typename SVGAnimatedProperty::DecoratedType newValue)
343 ASSERT(m_registered);
344 m_value = newValue;
345 ownerElement()->setSynchronizedSVGAttributes(false);
348 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
349 typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::DecoratedType
350 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::baseValue() const
352 ASSERT(m_registered);
353 const OwnerElement* ownerElement = this->ownerElement();
354 SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
355 if (extensions && extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier))
356 return extensions->baseValue<DecoratedType>(ownerElement, m_attributeIdentifier);
358 return m_value;
361 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
362 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::setBaseValue(typename SVGAnimatedProperty::DecoratedType newValue)
364 ASSERT(m_registered);
365 const OwnerElement* ownerElement = this->ownerElement();
366 SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
367 if (extensions && extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier)) {
368 extensions->setBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier, newValue);
369 return;
372 // Only update stored property, if not animating
373 m_value = newValue;
374 ownerElement->setSynchronizedSVGAttributes(false);
377 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
378 PassRefPtr<typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::TearOff>
379 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::animatedTearOff() const
381 ASSERT(m_registered);
382 return lookupOrCreateWrapper<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName, TearOff, OwnerElement>(*this, ownerElement(), m_attributeName, m_attributeIdentifier);
385 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
386 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::registerProperty()
388 ASSERT(!m_registered);
389 ownerElement()->propertyController().registerProperty(m_attributeName, this);
391 #ifndef NDEBUG
392 m_registered = true;
393 #endif
396 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
397 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::synchronize() const
399 ASSERT(m_registered);
400 if (!m_value.needsSynchronization())
401 return;
403 PropertySynchronizer<OwnerElement, DecoratedType, IsDerivedFromSVGElement<OwnerType>::value>::synchronize(ownerElement(), m_attributeName, baseValue());
404 m_value.setSynchronized();
407 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
408 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::startAnimation() const
410 ASSERT(m_registered);
411 const OwnerElement* ownerElement = this->ownerElement();
412 if (SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions()) {
413 ASSERT(!extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
414 extensions->setBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier, m_value);
418 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
419 void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::stopAnimation()
421 ASSERT(m_registered);
422 const OwnerElement* ownerElement = this->ownerElement();
423 if (SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions()) {
424 ASSERT(extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
425 setValue(extensions->baseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
426 extensions->removeBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier);
430 template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
431 const typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::OwnerElement*
432 SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::ownerElement() const
434 return OwnerElementForType::ownerElement(m_ownerType);
437 // GetOwnerElementForType implementation
438 template<typename OwnerType>
439 struct GetOwnerElementForType<OwnerType, true> : Noncopyable {
440 typedef OwnerType OwnerElement;
442 static const OwnerElement* ownerElement(const OwnerType* type)
444 return type;
448 template<typename OwnerType>
449 struct GetOwnerElementForType<OwnerType, false> : Noncopyable {
450 typedef SVGElement OwnerElement;
452 static const OwnerElement* ownerElement(const OwnerType* type)
454 const OwnerElement* context = type->contextElement();
455 ASSERT(context);
456 return context;
460 // IsDerivedFromSVGElement implementation
461 template<typename OwnerType>
462 struct IsDerivedFromSVGElement : Noncopyable {
463 static const bool value = true;
466 class SVGViewSpec;
467 template<>
468 struct IsDerivedFromSVGElement<SVGViewSpec> : Noncopyable {
469 static const bool value = false;
472 // PropertySynchronizer implementation
473 template<typename OwnerElement, typename DecoratedType>
474 struct PropertySynchronizer<OwnerElement, DecoratedType, true> : Noncopyable {
475 static void synchronize(const OwnerElement* ownerElement, const QualifiedName& attributeName, DecoratedType baseValue)
477 AtomicString value(SVGAnimatedTypeValue<DecoratedType>::toString(baseValue));
479 NamedNodeMap* namedAttrMap = ownerElement->attributes(false);
480 Attribute* old = namedAttrMap->getAttributeItem(attributeName);
481 if (old && value.isNull())
482 namedAttrMap->removeAttribute(old->name());
483 else if (!old && !value.isNull())
484 namedAttrMap->addAttribute(const_cast<OwnerElement*>(ownerElement)->createAttribute(attributeName, value));
485 else if (old && !value.isNull())
486 old->setValue(value);
490 template<typename OwnerElement, typename DecoratedType>
491 struct PropertySynchronizer<OwnerElement, DecoratedType, false> : Noncopyable {
492 static void synchronize(const OwnerElement*, const QualifiedName&, DecoratedType)
494 // no-op, for types not inheriting from Element, thus nothing to synchronize
498 // Helper macro used to register animated properties within SVG* classes
499 #define ANIMATED_PROPERTY_DECLARATIONS(OwnerType, ElementTag, AttributeTag, AnimatedType, UpperProperty, LowerProperty) \
500 private: \
501 typedef SVGAnimatedProperty<OwnerType, AnimatedType, ElementTag, AttributeTag> SVGAnimatedProperty##UpperProperty; \
502 typedef SVGAnimatedTypeValue<AnimatedType>::DecoratedType DecoratedTypeFor##UpperProperty; \
503 SVGAnimatedProperty##UpperProperty m_##LowerProperty; \
504 public: \
505 DecoratedTypeFor##UpperProperty LowerProperty() const { return m_##LowerProperty.value(); } \
506 void set##UpperProperty(DecoratedTypeFor##UpperProperty type) { m_##LowerProperty.setValue(type); } \
507 DecoratedTypeFor##UpperProperty LowerProperty##BaseValue() const { return m_##LowerProperty.baseValue(); } \
508 void set##UpperProperty##BaseValue(DecoratedTypeFor##UpperProperty type) { m_##LowerProperty.setBaseValue(type); } \
509 PassRefPtr<SVGAnimatedProperty##UpperProperty::TearOff> LowerProperty##Animated() const { return m_##LowerProperty.animatedTearOff(); }
513 #endif
514 #endif