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
25 #include "SVGAnimatedTemplate.h"
26 #include "SVGDocumentExtensions.h"
27 #include "SynchronizableTypeWrapper.h"
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
> {
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
);
52 SVGAnimatedPropertyTearOff(const Creator
&, const OwnerElement
*, const QualifiedName
& attributeName
);
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
{
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
{
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
98 SVGAnimatedProperty(const OwnerType
*, const QualifiedName
& attributeName
,
101 template<typename T1
>
102 SVGAnimatedProperty(const OwnerType
*, const QualifiedName
& attributeName
, const AtomicString
& attributeIdentifier
,
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();
137 const OwnerElement
* ownerElement() const;
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
;
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
)
194 , m_attributeName(attributeName
)
195 , m_attributeIdentifier(attributeName
.localName())
198 , m_registered(false)
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
)
210 , m_attributeName(attributeName
)
211 , m_attributeIdentifier(attributeIdentifier
)
214 , m_registered(false)
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
,
227 , m_attributeName(attributeName
)
228 , m_attributeIdentifier(attributeName
.localName())
231 , m_registered(false)
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
,
245 , m_attributeName(attributeName
)
246 , m_attributeIdentifier(attributeIdentifier
)
249 , m_registered(false)
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
,
263 , m_attributeName(attributeName
)
264 , m_attributeIdentifier(attributeName
.localName())
265 , m_value(arg1
, arg2
)
267 , m_registered(false)
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
,
282 , m_attributeName(attributeName
)
283 , m_attributeIdentifier(attributeIdentifier
)
284 , m_value(arg1
, arg2
)
286 , m_registered(false)
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
,
301 , m_attributeName(attributeName
)
302 , m_attributeIdentifier(attributeName
.localName())
303 , m_value(arg1
, arg2
, arg3
)
305 , m_registered(false)
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
,
321 , m_attributeName(attributeName
)
322 , m_attributeIdentifier(attributeIdentifier
)
323 , m_value(arg1
, arg2
, arg3
)
325 , m_registered(false)
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
);
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
);
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
);
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
);
372 // Only update stored property, if not animating
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);
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())
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
)
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();
460 // IsDerivedFromSVGElement implementation
461 template<typename OwnerType
>
462 struct IsDerivedFromSVGElement
: Noncopyable
{
463 static const bool value
= true;
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) \
501 typedef SVGAnimatedProperty<OwnerType, AnimatedType, ElementTag, AttributeTag> SVGAnimatedProperty##UpperProperty; \
502 typedef SVGAnimatedTypeValue<AnimatedType>::DecoratedType DecoratedTypeFor##UpperProperty; \
503 SVGAnimatedProperty##UpperProperty m_##LowerProperty; \
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(); }