1/* 2 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved. 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 SVGAnimatedTypeAnimator_h 21#define SVGAnimatedTypeAnimator_h 22 23#if ENABLE(SVG) 24#include "SVGAnimatedProperty.h" 25#include "SVGAnimatedType.h" 26#include "SVGAttributeToPropertyMap.h" 27#include "SVGElementInstance.h" 28#include <wtf/PassOwnPtr.h> 29 30namespace WebCore { 31 32struct SVGElementAnimatedProperties { 33 SVGElementAnimatedProperties() 34 : element(0) 35 { } 36 37 SVGElementAnimatedProperties(SVGElement* element, Vector<RefPtr<SVGAnimatedProperty> >& properties) 38 : element(element) 39 , properties(properties) 40 { } 41 42 SVGElement* element; 43 Vector<RefPtr<SVGAnimatedProperty> > properties; 44}; 45typedef Vector<SVGElementAnimatedProperties> SVGElementAnimatedPropertyList; 46 47class SVGAnimationElement; 48 49class SVGAnimatedTypeAnimator { 50 WTF_MAKE_FAST_ALLOCATED; 51public: 52 virtual ~SVGAnimatedTypeAnimator() { } 53 virtual PassOwnPtr<SVGAnimatedType> constructFromString(const String&) = 0; 54 55 virtual PassOwnPtr<SVGAnimatedType> startAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0; 56 virtual void stopAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0; 57 virtual void resetAnimValToBaseVal(const SVGElementAnimatedPropertyList&, SVGAnimatedType*) = 0; 58 virtual void animValWillChange(const SVGElementAnimatedPropertyList&) = 0; 59 virtual void animValDidChange(const SVGElementAnimatedPropertyList&) = 0; 60 virtual void addAnimatedTypes(SVGAnimatedType*, SVGAnimatedType*) = 0; 61 62 virtual void calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*) = 0; 63 virtual float calculateDistance(const String& fromString, const String& toString) = 0; 64 65 void calculateFromAndToValues(OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, const String& fromString, const String& toString) 66 { 67 from = constructFromString(fromString); 68 to = constructFromString(toString); 69 } 70 71 void calculateFromAndByValues(OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, const String& fromString, const String& byString) 72 { 73 from = constructFromString(fromString); 74 to = constructFromString(byString); 75 addAnimatedTypes(from.get(), to.get()); 76 } 77 78 void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; } 79 AnimatedPropertyType type() const { return m_type; } 80 81 SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement* targetElement, const QualifiedName& attributeName) 82 { 83 ASSERT(targetElement); 84 85 SVGElementAnimatedPropertyList propertiesByInstance; 86 87 Vector<RefPtr<SVGAnimatedProperty> > targetProperties; 88 targetElement->localAttributeToPropertyMap().animatedPropertiesForAttribute(targetElement, attributeName, targetProperties); 89 90 if (!SVGAnimatedType::supportsAnimVal(m_type)) 91 return SVGElementAnimatedPropertyList(); 92 93 SVGElementAnimatedProperties propertiesPair(targetElement, targetProperties); 94 propertiesByInstance.append(propertiesPair); 95 96 const HashSet<SVGElementInstance*>& instances = targetElement->instancesForElement(); 97 const HashSet<SVGElementInstance*>::const_iterator end = instances.end(); 98 for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) { 99 SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); 100 if (!shadowTreeElement) 101 continue; 102 103 Vector<RefPtr<SVGAnimatedProperty> > instanceProperties; 104 targetElement->localAttributeToPropertyMap().animatedPropertiesForAttribute(shadowTreeElement, attributeName, instanceProperties); 105 106 SVGElementAnimatedProperties instancePropertiesPair(shadowTreeElement, instanceProperties); 107 propertiesByInstance.append(instancePropertiesPair); 108 } 109 110#if !ASSERT_DISABLED 111 SVGElementAnimatedPropertyList::const_iterator propertiesEnd = propertiesByInstance.end(); 112 for (SVGElementAnimatedPropertyList::const_iterator it = propertiesByInstance.begin(); it != propertiesEnd; ++it) { 113 size_t propertiesSize = it->properties.size(); 114 for (size_t i = 0; i < propertiesSize; ++i) { 115 RefPtr<SVGAnimatedProperty> property = it->properties[i]; 116 if (property->animatedPropertyType() != m_type) { 117 ASSERT(m_type == AnimatedAngle); 118 ASSERT(property->animatedPropertyType() == AnimatedEnumeration); 119 } 120 } 121 } 122#endif 123 124 return propertiesByInstance; 125 } 126 127protected: 128 SVGAnimatedTypeAnimator(AnimatedPropertyType type, SVGAnimationElement* animationElement, SVGElement* contextElement) 129 : m_type(type) 130 , m_animationElement(animationElement) 131 , m_contextElement(contextElement) 132 { 133 } 134 135 // Helpers for animators that operate on single types, eg. just one SVGAnimatedInteger. 136 template<typename AnimValType> 137 typename AnimValType::ContentType* constructFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes) 138 { 139 ASSERT(animatedTypes[0].properties.size() == 1); 140 const typename AnimValType::ContentType& animatedType = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue(); 141 142 typename AnimValType::ContentType* copy = new typename AnimValType::ContentType(animatedType); 143 executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, copy); 144 return copy; 145 } 146 147 template<typename AnimValType> 148 void resetFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, typename AnimValType::ContentType& (SVGAnimatedType::*getter)()) 149 { 150 ASSERT(animatedTypes[0].properties.size() == 1); 151 ASSERT(type); 152 ASSERT(type->type() == m_type); 153 typename AnimValType::ContentType& animatedTypeValue = (type->*getter)(); 154 animatedTypeValue = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue(); 155 156 executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue); 157 } 158 159 template<typename AnimValType> 160 void stopAnimValAnimationForType(const SVGElementAnimatedPropertyList& animatedTypes) 161 { 162 ASSERT(animatedTypes[0].properties.size() == 1); 163 executeAction<AnimValType>(StopAnimationAction, animatedTypes, 0); 164 } 165 166 template<typename AnimValType> 167 void animValDidChangeForType(const SVGElementAnimatedPropertyList& animatedTypes) 168 { 169 ASSERT(animatedTypes[0].properties.size() == 1); 170 executeAction<AnimValType>(AnimValDidChangeAction, animatedTypes, 0); 171 } 172 173 template<typename AnimValType> 174 void animValWillChangeForType(const SVGElementAnimatedPropertyList& animatedTypes) 175 { 176 ASSERT(animatedTypes[0].properties.size() == 1); 177 executeAction<AnimValType>(AnimValWillChangeAction, animatedTypes, 0); 178 } 179 180 // Helpers for animators that operate on pair types, eg. a pair of SVGAnimatedIntegers. 181 template<typename AnimValType1, typename AnimValType2> 182 pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>* constructFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes) 183 { 184 ASSERT(animatedTypes[0].properties.size() == 2); 185 const typename AnimValType1::ContentType& firstType = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue(); 186 const typename AnimValType2::ContentType& secondType = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue(); 187 188 pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>* copy = new pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>(firstType, secondType); 189 executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, ©->first); 190 executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, ©->second); 191 return copy; 192 } 193 194 template<typename AnimValType1, typename AnimValType2> 195 void resetFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& (SVGAnimatedType::*getter)()) 196 { 197 ASSERT(animatedTypes[0].properties.size() == 2); 198 ASSERT(type); 199 ASSERT(type->type() == m_type); 200 201 pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& animatedTypeValue = (type->*getter)(); 202 animatedTypeValue.first = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue(); 203 animatedTypeValue.second = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue(); 204 205 executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue.first); 206 executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, &animatedTypeValue.second); 207 } 208 209 template<typename AnimValType1, typename AnimValType2> 210 void stopAnimValAnimationForTypes(const SVGElementAnimatedPropertyList& animatedTypes) 211 { 212 ASSERT(animatedTypes[0].properties.size() == 2); 213 executeAction<AnimValType1>(StopAnimationAction, animatedTypes, 0); 214 executeAction<AnimValType2>(StopAnimationAction, animatedTypes, 1); 215 } 216 217 template<typename AnimValType1, typename AnimValType2> 218 void animValDidChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes) 219 { 220 ASSERT(animatedTypes[0].properties.size() == 2); 221 executeAction<AnimValType1>(AnimValDidChangeAction, animatedTypes, 0); 222 executeAction<AnimValType2>(AnimValDidChangeAction, animatedTypes, 1); 223 } 224 225 template<typename AnimValType1, typename AnimValType2> 226 void animValWillChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes) 227 { 228 ASSERT(animatedTypes[0].properties.size() == 2); 229 executeAction<AnimValType1>(AnimValWillChangeAction, animatedTypes, 0); 230 executeAction<AnimValType2>(AnimValWillChangeAction, animatedTypes, 1); 231 } 232 233 template<typename AnimValType> 234 AnimValType* castAnimatedPropertyToActualType(SVGAnimatedProperty* property) 235 { 236 ASSERT(property); 237 ASSERT(property->contextElement()); 238 // We can't assert property->animatedPropertyType() == m_type, as there's an exception for SVGMarkerElements orient attribute. 239 if (property->animatedPropertyType() != m_type) { 240 ASSERT(m_type == AnimatedAngle); 241 ASSERT(property->animatedPropertyType() == AnimatedEnumeration); 242 } 243 return static_cast<AnimValType*>(property); 244 } 245 246 AnimatedPropertyType m_type; 247 SVGAnimationElement* m_animationElement; 248 SVGElement* m_contextElement; 249 250private: 251 enum AnimationAction { 252 StartAnimationAction, 253 StopAnimationAction, 254 AnimValWillChangeAction, 255 AnimValDidChangeAction 256 }; 257 258 template<typename AnimValType> 259 void executeAction(AnimationAction action, const SVGElementAnimatedPropertyList& animatedTypes, unsigned whichProperty, typename AnimValType::ContentType* type = 0) 260 { 261 SVGElementInstance::InstanceUpdateBlocker blocker(animatedTypes[0].element); 262 263 SVGElementAnimatedPropertyList::const_iterator end = animatedTypes.end(); 264 for (SVGElementAnimatedPropertyList::const_iterator it = animatedTypes.begin(); it != end; ++it) { 265 ASSERT_WITH_SECURITY_IMPLICATION(whichProperty < it->properties.size()); 266 AnimValType* property = castAnimatedPropertyToActualType<AnimValType>(it->properties[whichProperty].get()); 267 268 switch (action) { 269 case StartAnimationAction: 270 ASSERT(type); 271 if (!property->isAnimating()) 272 property->animationStarted(type); 273 break; 274 case StopAnimationAction: 275 ASSERT(!type); 276 property->animationEnded(); 277 break; 278 case AnimValWillChangeAction: 279 ASSERT(!type); 280 property->animValWillChange(); 281 break; 282 case AnimValDidChangeAction: 283 ASSERT(!type); 284 property->animValDidChange(); 285 break; 286 } 287 } 288 } 289}; 290 291} // namespace WebCore 292 293#endif // ENABLE(SVG) 294#endif // SVGAnimatedTypeAnimator_h 295