Use modern for-loops in WebCore/svg.
[WebKit-https.git] / Source / WebCore / svg / SVGAnimatedTypeAnimator.h
1 /*
2  * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
3  * Copyright (C) 2013 Samsung Electronics. All rights reserved.
4  *
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.
9  *
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.
14  *
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.
19  */
20
21 #ifndef SVGAnimatedTypeAnimator_h
22 #define SVGAnimatedTypeAnimator_h
23
24 #include "SVGAnimatedProperty.h"
25 #include "SVGAnimatedType.h"
26 #include <wtf/StdLibExtras.h>
27
28 namespace WebCore {
29
30 struct SVGElementAnimatedProperties {
31     SVGElement* element;
32     Vector<RefPtr<SVGAnimatedProperty>> properties;
33 };
34 typedef Vector<SVGElementAnimatedProperties> SVGElementAnimatedPropertyList;
35
36 class SVGAnimationElement;
37
38 class SVGAnimatedTypeAnimator {
39     WTF_MAKE_FAST_ALLOCATED;
40 public:
41     virtual ~SVGAnimatedTypeAnimator();
42     virtual std::unique_ptr<SVGAnimatedType> constructFromString(const String&) = 0;
43
44     virtual std::unique_ptr<SVGAnimatedType> startAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0;
45     virtual void stopAnimValAnimation(const SVGElementAnimatedPropertyList&) = 0;
46     virtual void resetAnimValToBaseVal(const SVGElementAnimatedPropertyList&, SVGAnimatedType*) = 0;
47     virtual void animValWillChange(const SVGElementAnimatedPropertyList&) = 0;
48     virtual void animValDidChange(const SVGElementAnimatedPropertyList&) = 0;
49     virtual void addAnimatedTypes(SVGAnimatedType*, SVGAnimatedType*) = 0;
50
51     virtual void calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*, SVGAnimatedType*) = 0;
52     virtual float calculateDistance(const String& fromString, const String& toString) = 0;
53
54     void calculateFromAndToValues(std::unique_ptr<SVGAnimatedType>&, std::unique_ptr<SVGAnimatedType>&, const String& fromString, const String& toString);
55     void calculateFromAndByValues(std::unique_ptr<SVGAnimatedType>&, std::unique_ptr<SVGAnimatedType>&, const String& fromString, const String& byString);
56
57     void setContextElement(SVGElement* contextElement) { m_contextElement = contextElement; }
58     AnimatedPropertyType type() const { return m_type; }
59
60     SVGElementAnimatedPropertyList findAnimatedPropertiesForAttributeName(SVGElement&, const QualifiedName&);
61
62 protected:
63     SVGAnimatedTypeAnimator(AnimatedPropertyType, SVGAnimationElement*, SVGElement*);
64
65     // Helpers for animators that operate on single types, eg. just one SVGAnimatedInteger.
66     template<typename AnimValType>
67     std::unique_ptr<typename AnimValType::ContentType> constructFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes)
68     {
69         ASSERT(animatedTypes[0].properties.size() == 1);
70         const typename AnimValType::ContentType& animatedType = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue();
71
72         auto copy = std::make_unique<typename AnimValType::ContentType>(animatedType);
73         executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, copy.get());
74         return copy;
75     }
76
77     template<typename AnimValType>
78     void resetFromBaseValue(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, typename AnimValType::ContentType& (SVGAnimatedType::*getter)())
79     {
80         ASSERT(animatedTypes[0].properties.size() == 1);
81         ASSERT(type);
82         ASSERT(type->type() == m_type);
83         typename AnimValType::ContentType& animatedTypeValue = (type->*getter)();
84         animatedTypeValue = castAnimatedPropertyToActualType<AnimValType>(animatedTypes[0].properties[0].get())->currentBaseValue();
85
86         executeAction<AnimValType>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue);
87     }
88
89     template<typename AnimValType>
90     void stopAnimValAnimationForType(const SVGElementAnimatedPropertyList& animatedTypes)
91     {
92         ASSERT(animatedTypes[0].properties.size() == 1);
93         executeAction<AnimValType>(StopAnimationAction, animatedTypes, 0);
94     }
95
96     template<typename AnimValType>
97     void animValDidChangeForType(const SVGElementAnimatedPropertyList& animatedTypes)
98     {
99         ASSERT(animatedTypes[0].properties.size() == 1);
100         executeAction<AnimValType>(AnimValDidChangeAction, animatedTypes, 0);
101     }
102
103     template<typename AnimValType>
104     void animValWillChangeForType(const SVGElementAnimatedPropertyList& animatedTypes)
105     {
106         ASSERT(animatedTypes[0].properties.size() == 1);
107         executeAction<AnimValType>(AnimValWillChangeAction, animatedTypes, 0);
108     }
109
110     // Helpers for animators that operate on pair types, eg. a pair of SVGAnimatedIntegers.
111     template<typename AnimValType1, typename AnimValType2>
112     std::unique_ptr<std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>> constructFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes)
113     {
114         ASSERT(animatedTypes[0].properties.size() == 2);
115         const typename AnimValType1::ContentType& firstType = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue();
116         const typename AnimValType2::ContentType& secondType = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue();
117
118         auto copy = std::make_unique<std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>>(firstType, secondType);
119         executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, &copy->first);
120         executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, &copy->second);
121         return copy;
122     }
123
124     template<typename AnimValType1, typename AnimValType2>
125     void resetFromBaseValues(const SVGElementAnimatedPropertyList& animatedTypes, SVGAnimatedType* type, std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& (SVGAnimatedType::*getter)())
126     {
127         ASSERT(animatedTypes[0].properties.size() == 2);
128         ASSERT(type);
129         ASSERT(type->type() == m_type);
130
131         std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>& animatedTypeValue = (type->*getter)();
132         animatedTypeValue.first = castAnimatedPropertyToActualType<AnimValType1>(animatedTypes[0].properties[0].get())->currentBaseValue();
133         animatedTypeValue.second = castAnimatedPropertyToActualType<AnimValType2>(animatedTypes[0].properties[1].get())->currentBaseValue();
134
135         executeAction<AnimValType1>(StartAnimationAction, animatedTypes, 0, &animatedTypeValue.first);
136         executeAction<AnimValType2>(StartAnimationAction, animatedTypes, 1, &animatedTypeValue.second);
137     }
138
139     template<typename AnimValType1, typename AnimValType2>
140     void stopAnimValAnimationForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
141     {
142         ASSERT(animatedTypes[0].properties.size() == 2);
143         executeAction<AnimValType1>(StopAnimationAction, animatedTypes, 0);
144         executeAction<AnimValType2>(StopAnimationAction, animatedTypes, 1);
145     }
146
147     template<typename AnimValType1, typename AnimValType2>
148     void animValDidChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
149     {
150         ASSERT(animatedTypes[0].properties.size() == 2);
151         executeAction<AnimValType1>(AnimValDidChangeAction, animatedTypes, 0);
152         executeAction<AnimValType2>(AnimValDidChangeAction, animatedTypes, 1);
153     }
154
155     template<typename AnimValType1, typename AnimValType2>
156     void animValWillChangeForTypes(const SVGElementAnimatedPropertyList& animatedTypes)
157     {
158         ASSERT(animatedTypes[0].properties.size() == 2);
159         executeAction<AnimValType1>(AnimValWillChangeAction, animatedTypes, 0);
160         executeAction<AnimValType2>(AnimValWillChangeAction, animatedTypes, 1);
161     }
162
163     template<typename AnimValType>
164     AnimValType* castAnimatedPropertyToActualType(SVGAnimatedProperty* property)
165     {
166         ASSERT(property);
167         ASSERT(property->contextElement());
168         // We can't assert property->animatedPropertyType() == m_type, as there's an exception for SVGMarkerElements orient attribute.
169         if (property->animatedPropertyType() != m_type) {
170             ASSERT(m_type == AnimatedAngle);
171             ASSERT(property->animatedPropertyType() == AnimatedEnumeration);
172         }
173         return static_cast<AnimValType*>(property);
174     }
175
176     AnimatedPropertyType m_type;
177     SVGAnimationElement* m_animationElement;
178     SVGElement* m_contextElement;
179
180 private:
181     enum AnimationAction {
182         StartAnimationAction,
183         StopAnimationAction,
184         AnimValWillChangeAction,
185         AnimValDidChangeAction
186     };
187
188     template<typename AnimValType>
189     void executeAction(AnimationAction action, const SVGElementAnimatedPropertyList& animatedTypes, unsigned whichProperty, typename AnimValType::ContentType* type = 0)
190     {
191         // FIXME: Can't use SVGElement::InstanceUpdateBlocker because of circular header dependency. Would be nice to untangle this.
192         setInstanceUpdatesBlocked(*animatedTypes[0].element, true);
193
194         for (auto& animatedType : animatedTypes) {
195             ASSERT_WITH_SECURITY_IMPLICATION(whichProperty < animatedType.properties.size());
196             AnimValType* property = castAnimatedPropertyToActualType<AnimValType>(animatedType.properties[whichProperty].get());
197
198             switch (action) {
199             case StartAnimationAction:
200                 ASSERT(type);
201                 if (!property->isAnimating())
202                     property->animationStarted(type);
203                 break;
204             case StopAnimationAction:
205                 ASSERT(!type);
206                 property->animationEnded();
207                 break;
208             case AnimValWillChangeAction:
209                 ASSERT(!type);
210                 property->animValWillChange();
211                 break;
212             case AnimValDidChangeAction:
213                 ASSERT(!type);
214                 property->animValDidChange();
215                 break;
216             }
217         }
218
219         setInstanceUpdatesBlocked(*animatedTypes[0].element, false);
220     }
221
222     static void setInstanceUpdatesBlocked(SVGElement&, bool);
223 };
224
225 } // namespace WebCore
226
227 #endif // SVGAnimatedTypeAnimator_h