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