Rename SVGProperty to SVGLegacyProperty and rename SVGAnimatedProperty to SVGLegacyAn...
[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  * Copyright (C) 2018 Apple Inc. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #pragma once
23
24 #include "SVGAnimatedType.h"
25 #include "SVGLegacyAnimatedProperty.h"
26 #include <wtf/StdLibExtras.h>
27
28 namespace WebCore {
29
30 struct SVGElementAnimatedProperties {
31     SVGElement* element;
32     Vector<RefPtr<SVGLegacyAnimatedProperty>> 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<SVGAnimatedType> constructFromBaseValue(const SVGElementAnimatedPropertyList& animatedProperties)
68     {
69         ASSERT(animatedProperties[0].properties.size() == 1);
70         const auto* animatedProperty = castAnimatedPropertyToActualType<AnimValType>(animatedProperties[0].properties[0].get());
71
72         auto animatedType = SVGAnimatedType::create(animatedProperty->currentBaseValue());
73         auto& animatedValue = animatedType->template as<typename AnimValType::ContentType>();
74         executeAction<AnimValType>(StartAnimationAction, animatedProperties, 0, &animatedValue);
75         return animatedType;
76     }
77
78     template<typename AnimValType>
79     void resetFromBaseValue(const SVGElementAnimatedPropertyList& animatedProperties, SVGAnimatedType& animatedType)
80     {
81         ASSERT(animatedProperties[0].properties.size() == 1);
82         ASSERT(animatedType.type() == m_type);
83         auto* animatedProperty = castAnimatedPropertyToActualType<AnimValType>(animatedProperties[0].properties[0].get());
84         animatedProperty->synchronizeWrappersIfNeeded();
85
86         auto& animatedValue = animatedType.as<typename AnimValType::ContentType>();
87         animatedValue = animatedProperty->currentBaseValue();
88         executeAction<AnimValType>(StartAnimationAction, animatedProperties, 0, &animatedValue);
89     }
90
91     template<typename AnimValType>
92     void stopAnimValAnimationForType(const SVGElementAnimatedPropertyList& animatedProperties)
93     {
94         ASSERT(animatedProperties[0].properties.size() == 1);
95         executeAction<AnimValType>(StopAnimationAction, animatedProperties, 0);
96     }
97
98     template<typename AnimValType>
99     void animValDidChangeForType(const SVGElementAnimatedPropertyList& animatedProperties)
100     {
101         ASSERT(animatedProperties[0].properties.size() == 1);
102         executeAction<AnimValType>(AnimValDidChangeAction, animatedProperties, 0);
103     }
104
105     template<typename AnimValType>
106     void animValWillChangeForType(const SVGElementAnimatedPropertyList& animatedProperties)
107     {
108         ASSERT(animatedProperties[0].properties.size() == 1);
109         executeAction<AnimValType>(AnimValWillChangeAction, animatedProperties, 0);
110     }
111
112     // Helpers for animators that operate on pair types, eg. a pair of SVGAnimatedIntegers.
113     template<typename AnimValType1, typename AnimValType2>
114     std::unique_ptr<SVGAnimatedType> constructFromBaseValues(const SVGElementAnimatedPropertyList& animatedProperties)
115     {
116         ASSERT(animatedProperties[0].properties.size() == 2);
117         const auto* firstAnimatedProperty = castAnimatedPropertyToActualType<AnimValType1>(animatedProperties[0].properties[0].get());
118         const auto* secondAnimatedProperty = castAnimatedPropertyToActualType<AnimValType2>(animatedProperties[0].properties[1].get());
119
120         auto animatedType = SVGAnimatedType::create(std::make_pair(firstAnimatedProperty->currentBaseValue(), secondAnimatedProperty->currentBaseValue()));
121         auto& AnimatedValue = animatedType->template as<std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>>();
122         executeAction<AnimValType1>(StartAnimationAction, animatedProperties, 0, &AnimatedValue.first);
123         executeAction<AnimValType2>(StartAnimationAction, animatedProperties, 1, &AnimatedValue.second);
124         return animatedType;
125     }
126
127     template<typename AnimValType1, typename AnimValType2>
128     void resetFromBaseValues(const SVGElementAnimatedPropertyList& animatedProperties, SVGAnimatedType& animatedType)
129     {
130         ASSERT(animatedProperties[0].properties.size() == 2);
131         ASSERT(animatedType.type() == m_type);
132         auto* firstAnimatedProperty = castAnimatedPropertyToActualType<AnimValType1>(animatedProperties[0].properties[0].get());
133         auto* secondAnimatedProperty =  castAnimatedPropertyToActualType<AnimValType2>(animatedProperties[0].properties[1].get());
134         firstAnimatedProperty->synchronizeWrappersIfNeeded();
135         secondAnimatedProperty->synchronizeWrappersIfNeeded();
136
137         auto& animatedValue = animatedType.as<std::pair<typename AnimValType1::ContentType, typename AnimValType2::ContentType>>();
138         animatedValue.first = firstAnimatedProperty->currentBaseValue();
139         animatedValue.second = secondAnimatedProperty->currentBaseValue();
140         executeAction<AnimValType1>(StartAnimationAction, animatedProperties, 0, &animatedValue.first);
141         executeAction<AnimValType2>(StartAnimationAction, animatedProperties, 1, &animatedValue.second);
142     }
143
144     template<typename AnimValType1, typename AnimValType2>
145     void stopAnimValAnimationForTypes(const SVGElementAnimatedPropertyList& animatedProperties)
146     {
147         ASSERT(animatedProperties[0].properties.size() == 2);
148         executeAction<AnimValType1>(StopAnimationAction, animatedProperties, 0);
149         executeAction<AnimValType2>(StopAnimationAction, animatedProperties, 1);
150     }
151
152     template<typename AnimValType1, typename AnimValType2>
153     void animValDidChangeForTypes(const SVGElementAnimatedPropertyList& animatedProperties)
154     {
155         ASSERT(animatedProperties[0].properties.size() == 2);
156         executeAction<AnimValType1>(AnimValDidChangeAction, animatedProperties, 0);
157         executeAction<AnimValType2>(AnimValDidChangeAction, animatedProperties, 1);
158     }
159
160     template<typename AnimValType1, typename AnimValType2>
161     void animValWillChangeForTypes(const SVGElementAnimatedPropertyList& animatedProperties)
162     {
163         ASSERT(animatedProperties[0].properties.size() == 2);
164         executeAction<AnimValType1>(AnimValWillChangeAction, animatedProperties, 0);
165         executeAction<AnimValType2>(AnimValWillChangeAction, animatedProperties, 1);
166     }
167
168     template<typename AnimValType>
169     AnimValType* castAnimatedPropertyToActualType(SVGLegacyAnimatedProperty* property)
170     {
171         ASSERT(property);
172         ASSERT(property->contextElement());
173         // We can't assert property->animatedPropertyType() == m_type, as there's an exception for SVGMarkerElements orient attribute.
174         if (property->animatedPropertyType() != m_type) {
175             ASSERT(m_type == AnimatedAngle);
176             ASSERT(property->animatedPropertyType() == AnimatedEnumeration);
177         }
178         return static_cast<AnimValType*>(property);
179     }
180
181     AnimatedPropertyType m_type;
182     SVGAnimationElement* m_animationElement;
183     SVGElement* m_contextElement;
184
185 private:
186     enum AnimationAction {
187         StartAnimationAction,
188         StopAnimationAction,
189         AnimValWillChangeAction,
190         AnimValDidChangeAction
191     };
192
193     template<typename AnimValType>
194     void executeAction(AnimationAction action, const SVGElementAnimatedPropertyList& animatedProperties, unsigned whichProperty, typename AnimValType::ContentType* animatedValue = nullptr)
195     {
196         // FIXME: Can't use SVGElement::InstanceUpdateBlocker because of circular header dependency. Would be nice to untangle this.
197         setInstanceUpdatesBlocked(*animatedProperties[0].element, true);
198
199         for (auto& animatedProperty : animatedProperties) {
200             RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(whichProperty < animatedProperty.properties.size());
201             AnimValType* property = castAnimatedPropertyToActualType<AnimValType>(animatedProperty.properties[whichProperty].get());
202
203             switch (action) {
204             case StartAnimationAction:
205                 ASSERT(animatedValue);
206                 if (!property->isAnimating())
207                     property->animationStarted(animatedValue);
208                 break;
209             case StopAnimationAction:
210                 ASSERT(!animatedValue);
211                 if (property->isAnimating())
212                     property->animationEnded();
213                 break;
214             case AnimValWillChangeAction:
215                 ASSERT(!animatedValue);
216                 property->animValWillChange();
217                 break;
218             case AnimValDidChangeAction:
219                 ASSERT(!animatedValue);
220                 property->animValDidChange();
221                 break;
222             }
223         }
224
225         setInstanceUpdatesBlocked(*animatedProperties[0].element, false);
226     }
227
228     static void setInstanceUpdatesBlocked(SVGElement&, bool);
229 };
230
231 } // namespace WebCore