• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
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 #ifndef SVGAnimatedProperty_h
21 #define SVGAnimatedProperty_h
22 
23 #if ENABLE(SVG)
24 #include "SVGAnimatedTemplate.h"
25 #include "SVGDocumentExtensions.h"
26 #include "SynchronizableTypeWrapper.h"
27 
28 namespace WebCore {
29 
30     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
31     class SVGAnimatedProperty;
32 
33     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
34     class SVGAnimatedPropertyTearOff : public SVGAnimatedTemplate<DecoratedType> {
35     public:
36         typedef SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName> Self;
37         typedef SVGAnimatedProperty<OwnerType, AnimatedType, TagName, PropertyName> Creator;
38 
create(const Creator & creator,const OwnerElement * owner,const QualifiedName & attributeName)39         static PassRefPtr<Self> create(const Creator& creator, const OwnerElement* owner, const QualifiedName& attributeName)
40         {
41             return adoptRef(new Self(creator, owner, attributeName));
42         }
43 
44         virtual DecoratedType baseVal() const;
45         virtual void setBaseVal(DecoratedType);
46 
47         virtual DecoratedType animVal() const;
48         virtual void setAnimVal(DecoratedType);
49 
50     private:
51         SVGAnimatedPropertyTearOff(const Creator&, const OwnerElement*, const QualifiedName& attributeName);
52 
53         Creator& m_creator;
54         RefPtr<OwnerElement> m_ownerElement;
55     };
56 
57     // 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)
58     template<typename OwnerType, bool isDerivedFromSVGElement>
59     struct GetOwnerElementForType;
60 
61     template<typename OwnerType>
62     struct IsDerivedFromSVGElement;
63 
64     // Helper template used for synchronizing SVG <-> XML properties
65     template<typename OwnerElement, typename DecoratedType>
66     void synchronizeProperty(const OwnerElement* ownerElement, const QualifiedName& attributeName, DecoratedType baseValue);
67 
68     // Abstract base class
69     class SVGAnimatedPropertyBase : public Noncopyable {
70     public:
~SVGAnimatedPropertyBase()71         virtual ~SVGAnimatedPropertyBase() { }
72         virtual void synchronize() const = 0;
73     };
74 
75     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
76     class SVGAnimatedProperty : public SVGAnimatedPropertyBase {
77     public:
78         typedef OwnerTypeArg OwnerType;
79         typedef AnimatedTypeArg AnimatedType;
80 
81         typedef typename SVGAnimatedTypeValue<AnimatedType>::StorableType StorableType;
82         typedef typename SVGAnimatedTypeValue<AnimatedType>::DecoratedType DecoratedType;
83 
84         typedef GetOwnerElementForType<OwnerType, IsDerivedFromSVGElement<OwnerType>::value> OwnerElementForType;
85         typedef typename OwnerElementForType::OwnerElement OwnerElement;
86         typedef SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName> TearOff;
87 
88         // attributeName & attributeIdentifier may differ. For SVGMarkerElement, there are two exposed SVG animatable
89         // properties: orientType & orientAngle, though only one DOM attribute "orient", handle these cases!
90         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName);
91         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier);
92 
93         // "Forwarding constructors" for primitive type assignment with more than one argument
94         template<typename T1>
95         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
96                             const T1&);
97 
98         template<typename T1>
99         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
100                             const T1&);
101 
102         template<typename T1, typename T2>
103         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
104                             const T1&, const T2&);
105 
106         template<typename T1, typename T2>
107         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
108                             const T1&, const T2&);
109 
110         template<typename T1, typename T2, typename T3>
111         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName,
112                             const T1&, const T2&, const T3&);
113 
114         template<typename T1, typename T2, typename T3>
115         SVGAnimatedProperty(const OwnerType*, const QualifiedName& attributeName, const AtomicString& attributeIdentifier,
116                             const T1&, const T2&, const T3&);
117 
118         DecoratedType value() const;
119         void setValue(DecoratedType);
120 
121         DecoratedType baseValue() const;
122         void setBaseValue(DecoratedType);
123 
124         // Tear offs only used by bindings, never in internal code
125         PassRefPtr<TearOff> animatedTearOff() const;
126 
127         virtual void synchronize() const;
128 
129         void startAnimation() const;
130         void stopAnimation();
131 
132     private:
133         const OwnerElement* ownerElement() const;
134 
135     private:
136         // We're a member variable on stack, living in OwnerType, NO need to ref here.
137         const OwnerType* m_ownerType;
138 
139         const QualifiedName& m_attributeName;
140         const AtomicString& m_attributeIdentifier;
141 
142         mutable SynchronizableTypeWrapper<StorableType> m_value;
143     };
144 
145     // SVGAnimatedPropertyTearOff implementation
146     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
SVGAnimatedPropertyTearOff(const Creator & creator,const OwnerElement * owner,const QualifiedName & attributeName)147     SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::SVGAnimatedPropertyTearOff(const Creator& creator,
148                                                                                                                                         const OwnerElement* owner,
149                                                                                                                                         const QualifiedName& attributeName)
150         : SVGAnimatedTemplate<DecoratedType>(attributeName)
151         , m_creator(const_cast<Creator&>(creator))
152         , m_ownerElement(const_cast<OwnerElement*>(owner))
153     {
154         ASSERT(m_ownerElement);
155     }
156 
157     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
baseVal()158     DecoratedType SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::baseVal() const
159     {
160         return m_creator.baseValue();
161     }
162 
163     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
setBaseVal(DecoratedType newBaseVal)164     void SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::setBaseVal(DecoratedType newBaseVal)
165     {
166         m_creator.setBaseValue(newBaseVal);
167     }
168 
169     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
animVal()170     DecoratedType SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::animVal() const
171     {
172         return m_creator.value();
173     }
174 
175     template<typename OwnerType, typename OwnerElement, typename AnimatedType, typename DecoratedType, const char* TagName, const char* PropertyName>
setAnimVal(DecoratedType newAnimVal)176     void SVGAnimatedPropertyTearOff<OwnerType, OwnerElement, AnimatedType, DecoratedType, TagName, PropertyName>::setAnimVal(DecoratedType newAnimVal)
177     {
178         m_creator.setValue(newAnimVal);
179     }
180 
181     // SVGAnimatedProperty implementation
182     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName)183     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
184                                                                                                    const QualifiedName& attributeName)
185         : m_ownerType(owner)
186         , m_attributeName(attributeName)
187         , m_attributeIdentifier(attributeName.localName())
188         , m_value()
189     {
190         ASSERT(m_ownerType);
191     }
192 
193     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const AtomicString & attributeIdentifier)194     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
195                                                                                                    const QualifiedName& attributeName,
196                                                                                                    const AtomicString& attributeIdentifier)
197         : m_ownerType(owner)
198         , m_attributeName(attributeName)
199         , m_attributeIdentifier(attributeIdentifier)
200         , m_value()
201     {
202         ASSERT(m_ownerType);
203     }
204 
205     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
206     template<typename T1>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const T1 & arg1)207     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
208                                                                                                    const QualifiedName& attributeName,
209                                                                                                    const T1& arg1)
210         : m_ownerType(owner)
211         , m_attributeName(attributeName)
212         , m_attributeIdentifier(attributeName.localName())
213         , m_value(arg1)
214     {
215         ASSERT(m_ownerType);
216     }
217 
218     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
219     template<typename T1>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const AtomicString & attributeIdentifier,const T1 & arg1)220     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
221                                                                                                    const QualifiedName& attributeName,
222                                                                                                    const AtomicString& attributeIdentifier,
223                                                                                                    const T1& arg1)
224         : m_ownerType(owner)
225         , m_attributeName(attributeName)
226         , m_attributeIdentifier(attributeIdentifier)
227         , m_value(arg1)
228     {
229         ASSERT(m_ownerType);
230     }
231 
232     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
233     template<typename T1, typename T2>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const T1 & arg1,const T2 & arg2)234     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
235                                                                                                    const QualifiedName& attributeName,
236                                                                                                    const T1& arg1,
237                                                                                                    const T2& arg2)
238         : m_ownerType(owner)
239         , m_attributeName(attributeName)
240         , m_attributeIdentifier(attributeName.localName())
241         , m_value(arg1, arg2)
242     {
243         ASSERT(m_ownerType);
244     }
245 
246     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
247     template<typename T1, typename T2>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const AtomicString & attributeIdentifier,const T1 & arg1,const T2 & arg2)248     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
249                                                                                                    const QualifiedName& attributeName,
250                                                                                                    const AtomicString& attributeIdentifier,
251                                                                                                    const T1& arg1,
252                                                                                                    const T2& arg2)
253         : m_ownerType(owner)
254         , m_attributeName(attributeName)
255         , m_attributeIdentifier(attributeIdentifier)
256         , m_value(arg1, arg2)
257     {
258         ASSERT(m_ownerType);
259     }
260 
261     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
262     template<typename T1, typename T2, typename T3>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const T1 & arg1,const T2 & arg2,const T3 & arg3)263     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
264                                                                                                    const QualifiedName& attributeName,
265                                                                                                    const T1& arg1,
266                                                                                                    const T2& arg2,
267                                                                                                    const T3& arg3)
268         : m_ownerType(owner)
269         , m_attributeName(attributeName)
270         , m_attributeIdentifier(attributeName.localName())
271         , m_value(arg1, arg2, arg3)
272     {
273         ASSERT(m_ownerType);
274     }
275 
276     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
277     template<typename T1, typename T2, typename T3>
SVGAnimatedProperty(const OwnerType * owner,const QualifiedName & attributeName,const AtomicString & attributeIdentifier,const T1 & arg1,const T2 & arg2,const T3 & arg3)278     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::SVGAnimatedProperty(const OwnerType* owner,
279                                                                                                    const QualifiedName& attributeName,
280                                                                                                    const AtomicString& attributeIdentifier,
281                                                                                                    const T1& arg1,
282                                                                                                    const T2& arg2,
283                                                                                                    const T3& arg3)
284         : m_ownerType(owner)
285         , m_attributeName(attributeName)
286         , m_attributeIdentifier(attributeIdentifier)
287         , m_value(arg1, arg2, arg3)
288     {
289         ASSERT(m_ownerType);
290     }
291 
292     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
293     typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::DecoratedType
value()294     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::value() const
295     {
296         return m_value;
297     }
298 
299     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
setValue(typename SVGAnimatedProperty::DecoratedType newValue)300     void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::setValue(typename SVGAnimatedProperty::DecoratedType newValue)
301     {
302         m_value = newValue;
303         ownerElement()->setSynchronizedSVGAttributes(false);
304     }
305 
306     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
307     typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::DecoratedType
baseValue()308     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::baseValue() const
309     {
310         const OwnerElement* ownerElement = this->ownerElement();
311         SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
312         if (extensions && extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier))
313             return extensions->baseValue<DecoratedType>(ownerElement, m_attributeIdentifier);
314 
315         return m_value;
316     }
317 
318     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
setBaseValue(typename SVGAnimatedProperty::DecoratedType newValue)319     void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::setBaseValue(typename SVGAnimatedProperty::DecoratedType newValue)
320     {
321         const OwnerElement* ownerElement = this->ownerElement();
322         SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
323         if (extensions && extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier)) {
324             extensions->setBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier, newValue);
325             return;
326         }
327 
328         // Only update stored property, if not animating
329         m_value = newValue;
330         ownerElement->setSynchronizedSVGAttributes(false);
331     }
332 
333     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
334     PassRefPtr<typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::TearOff>
animatedTearOff()335     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::animatedTearOff() const
336     {
337         return lookupOrCreateWrapper<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName, TearOff, OwnerElement>(*this, ownerElement(), m_attributeName, m_attributeIdentifier);
338     }
339 
340     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
synchronize()341     void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::synchronize() const
342     {
343         if (!m_value.needsSynchronization())
344             return;
345 
346         synchronizeProperty<OwnerElement, DecoratedType>(ownerElement(), m_attributeName, baseValue());
347         m_value.setSynchronized();
348     }
349 
350     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
startAnimation()351     void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::startAnimation() const
352     {
353         const OwnerElement* ownerElement = this->ownerElement();
354         SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
355         if (extensions) {
356             ASSERT(!extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
357             extensions->setBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier, m_value);
358         }
359     }
360 
361     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
stopAnimation()362     void SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::stopAnimation()
363     {
364         const OwnerElement* ownerElement = this->ownerElement();
365         SVGDocumentExtensions* extensions = ownerElement->accessDocumentSVGExtensions();
366         if (extensions) {
367             ASSERT(extensions->hasBaseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
368             setValue(extensions->baseValue<DecoratedType>(ownerElement, m_attributeIdentifier));
369             extensions->removeBaseValue<AnimatedType>(ownerElement, m_attributeIdentifier);
370         }
371     }
372 
373     template<typename OwnerTypeArg, typename AnimatedTypeArg, const char* TagName, const char* PropertyName>
374     const typename SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::OwnerElement*
ownerElement()375     SVGAnimatedProperty<OwnerTypeArg, AnimatedTypeArg, TagName, PropertyName>::ownerElement() const
376     {
377         return OwnerElementForType::ownerElement(m_ownerType);
378     }
379 
380     // GetOwnerElementForType implementation
381     template<typename OwnerType>
382     struct GetOwnerElementForType<OwnerType, true> : Noncopyable {
383         typedef OwnerType OwnerElement;
384 
385         static const OwnerElement* ownerElement(const OwnerType* type)
386         {
387             return type;
388         }
389     };
390 
391     template<typename OwnerType>
392     struct GetOwnerElementForType<OwnerType, false> : Noncopyable {
393         typedef SVGElement OwnerElement;
394 
395         static const OwnerElement* ownerElement(const OwnerType* type)
396         {
397             const OwnerElement* context = type->contextElement();
398             ASSERT(context);
399             return context;
400         }
401     };
402 
403     // IsDerivedFromSVGElement implementation
404     template<typename OwnerType>
405     struct IsDerivedFromSVGElement : Noncopyable {
406         static const bool value = true;
407     };
408 
409     class SVGExternalResourcesRequired;
410     template<>
411     struct IsDerivedFromSVGElement<SVGExternalResourcesRequired> : Noncopyable {
412         static const bool value = false;
413     };
414 
415     class SVGFitToViewBox;
416     template<>
417     struct IsDerivedFromSVGElement<SVGFitToViewBox> : Noncopyable {
418         static const bool value = false;
419     };
420 
421     class SVGURIReference;
422     template<>
423     struct IsDerivedFromSVGElement<SVGURIReference> : Noncopyable {
424         static const bool value = false;
425     };
426 
427     // Central function handling the main SVG<->XML synchronization part.
428     template<typename OwnerElement, typename DecoratedType>
429     void synchronizeProperty(const OwnerElement* ownerElement, const QualifiedName& attributeName, DecoratedType baseValue)
430     {
431         AtomicString value(SVGAnimatedTypeValue<DecoratedType>::toString(baseValue));
432 
433         NamedNodeMap* namedAttrMap = ownerElement->attributes(false);
434         Attribute* old = namedAttrMap->getAttributeItem(attributeName);
435         if (old && value.isNull())
436             namedAttrMap->removeAttribute(old->name());
437         else if (!old && !value.isNull())
438             namedAttrMap->addAttribute(const_cast<OwnerElement*>(ownerElement)->createAttribute(attributeName, value));
439         else if (old && !value.isNull())
440             old->setValue(value);
441     }
442 
443     // Helper macro used to register animated properties within SVG* classes
444     #define ANIMATED_PROPERTY_DECLARATIONS(OwnerType, ElementTag, AttributeTag, AnimatedType, UpperProperty, LowerProperty) \
445     private: \
446         typedef SVGAnimatedProperty<OwnerType, AnimatedType, ElementTag, AttributeTag> SVGAnimatedProperty##UpperProperty; \
447         typedef SVGAnimatedTypeValue<AnimatedType>::DecoratedType DecoratedTypeFor##UpperProperty; \
448         SVGAnimatedProperty##UpperProperty m_##LowerProperty; \
449     public: \
450         DecoratedTypeFor##UpperProperty LowerProperty() const { return m_##LowerProperty.value(); } \
451         void set##UpperProperty(DecoratedTypeFor##UpperProperty type) { m_##LowerProperty.setValue(type); } \
452         DecoratedTypeFor##UpperProperty LowerProperty##BaseValue() const { return m_##LowerProperty.baseValue(); } \
453         void set##UpperProperty##BaseValue(DecoratedTypeFor##UpperProperty type) { m_##LowerProperty.setBaseValue(type); } \
454         PassRefPtr<SVGAnimatedProperty##UpperProperty::TearOff> LowerProperty##Animated() const { return m_##LowerProperty.animatedTearOff(); } \
455         void synchronize##UpperProperty() const { m_##LowerProperty.synchronize(); }
456 
457 };
458 
459 #endif
460 #endif
461