Unify SVG's animation and target tracking systems.
[WebKit-https.git] / Source / WebCore / svg / SVGAnimationElement.h
1 /*
2  * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5  * Copyright (C) 2008 Apple Inc. All rights reserved.
6  * Copyright (C) 2008 Cameron McCormack <cam@mcc.id.au>
7  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 #ifndef SVGAnimationElement_h
26 #define SVGAnimationElement_h
27
28 #if ENABLE(SVG)
29 #include "ElementTimeControl.h"
30 #include "SMILTime.h"
31 #include "SVGAnimatedBoolean.h"
32 #include "SVGExternalResourcesRequired.h"
33 #include "SVGSMILElement.h"
34 #include "SVGStringList.h"
35 #include "SVGTests.h"
36 #include "UnitBezier.h"
37
38 namespace WebCore {
39
40 enum AnimationMode {
41     NoAnimation,
42     FromToAnimation,
43     FromByAnimation,
44     ToAnimation,
45     ByAnimation,
46     ValuesAnimation,
47     PathAnimation // Used by AnimateMotion.
48 };
49
50 // If we have 'currentColor' or 'inherit' as animation value, we need to grab
51 // the value during the animation since the value can be animated itself.
52 enum AnimatedPropertyValueType {
53     RegularPropertyValue,
54     CurrentColorValue,
55     InheritValue
56 };
57
58 enum CalcMode {
59     CalcModeDiscrete,
60     CalcModeLinear,
61     CalcModePaced,
62     CalcModeSpline
63 };
64
65 class ConditionEventListener;
66 class TimeContainer;
67 class SVGAnimatedType;
68
69 class SVGAnimationElement : public SVGSMILElement,
70                             public SVGTests,
71                             public SVGExternalResourcesRequired,
72                             public ElementTimeControl {
73 public:
74     // SVGAnimationElement
75     float getStartTime() const;
76     float getCurrentTime() const;
77     float getSimpleDuration(ExceptionCode&) const;
78
79     // ElementTimeControl
80     virtual void beginElement();
81     virtual void beginElementAt(float offset);
82     virtual void endElement();
83     virtual void endElementAt(float offset);
84
85     static bool isTargetAttributeCSSProperty(SVGElement*, const QualifiedName&);
86
87     virtual bool isAdditive() const;
88     bool isAccumulated() const;
89     AnimationMode animationMode() const { return m_animationMode; }
90     CalcMode calcMode() const { return m_calcMode; }
91
92     enum ShouldApplyAnimation {
93         DontApplyAnimation,
94         ApplyCSSAnimation,
95         ApplyXMLAnimation
96     };
97
98     ShouldApplyAnimation shouldApplyAnimation(SVGElement* targetElement, const QualifiedName& attributeName);
99
100     AnimatedPropertyValueType fromPropertyValueType() const { return m_fromPropertyValueType; }
101     AnimatedPropertyValueType toPropertyValueType() const { return m_toPropertyValueType; }
102
103     template<typename AnimatedType>
104     void adjustForInheritance(AnimatedType (*parseTypeFromString)(SVGAnimationElement*, const String&),
105                               AnimatedPropertyValueType valueType, AnimatedType& animatedType, SVGElement* contextElement)
106     {
107         if (valueType != InheritValue)
108             return;
109         // Replace 'inherit' by its computed property value.
110         ASSERT(parseTypeFromString);
111         String typeString;
112         adjustForInheritance(contextElement, attributeName(), typeString);
113         animatedType = (*parseTypeFromString)(this, typeString);
114     }
115
116     template<typename AnimatedType>
117     bool adjustFromToListValues(const AnimatedType& fromList, const AnimatedType& toList, AnimatedType& animatedList, float percentage, bool resizeAnimatedListIfNeeded = true)
118     {
119         // If no 'to' value is given, nothing to animate.
120         unsigned toListSize = toList.size();
121         if (!toListSize)
122             return false;
123
124         // If the 'from' value is given and it's length doesn't match the 'to' value list length, fallback to a discrete animation.
125         unsigned fromListSize = fromList.size();
126         if (fromListSize != toListSize && fromListSize) {
127             if (percentage < 0.5) {
128                 if (animationMode() != ToAnimation)
129                     animatedList = AnimatedType(fromList);
130             } else
131                 animatedList = AnimatedType(toList);
132
133             return false;
134         }
135
136         ASSERT(!fromListSize || fromListSize == toListSize);
137         if (resizeAnimatedListIfNeeded && animatedList.size() < toListSize)
138             animatedList.resize(toListSize);
139
140         return true;
141     }
142
143     template<typename AnimatedType>
144     void animateDiscreteType(float percentage, const AnimatedType& fromType, const AnimatedType& toType, AnimatedType& animatedType)
145     {
146         if ((animationMode() == FromToAnimation && percentage > 0.5) || animationMode() == ToAnimation || percentage == 1) {
147             animatedType = AnimatedType(toType);
148             return;
149         }
150         animatedType = AnimatedType(fromType);
151     }
152
153     void animateAdditiveNumber(float percentage, unsigned repeatCount, float fromNumber, float toNumber, float toAtEndOfDurationNumber, float& animatedNumber)
154     {
155         float number;
156         if (calcMode() == CalcModeDiscrete)
157             number = percentage < 0.5 ? fromNumber : toNumber;
158         else
159             number = (toNumber - fromNumber) * percentage + fromNumber;
160
161         if (isAccumulated() && repeatCount)
162             number += toAtEndOfDurationNumber * repeatCount;
163
164         if (isAdditive() && animationMode() != ToAnimation)
165             animatedNumber += number;
166         else
167             animatedNumber = number;
168     }
169
170 protected:
171     SVGAnimationElement(const QualifiedName&, Document*);
172
173     void computeCSSPropertyValue(SVGElement*, CSSPropertyID, String& value);
174     virtual void determinePropertyValueTypes(const String& from, const String& to);
175
176     bool isSupportedAttribute(const QualifiedName&);
177     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
178     virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
179
180     enum AttributeType {
181         AttributeTypeCSS,
182         AttributeTypeXML,
183         AttributeTypeAuto
184     };
185     AttributeType attributeType() const { return m_attributeType; }
186
187     String toValue() const;
188     String byValue() const;
189     String fromValue() const;
190
191     String targetAttributeBaseValue();
192
193     // from SVGSMILElement
194     virtual void startedActiveInterval() OVERRIDE;
195     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) OVERRIDE;
196
197     AnimatedPropertyValueType m_fromPropertyValueType;
198     AnimatedPropertyValueType m_toPropertyValueType;
199
200     virtual void setTargetElement(SVGElement*) OVERRIDE;
201     virtual void setAttributeName(const QualifiedName&) OVERRIDE;
202     bool hasInvalidCSSAttributeType() const { return m_hasInvalidCSSAttributeType; }
203
204     virtual void updateAnimationMode();
205     void setAnimationMode(AnimationMode animationMode) { m_animationMode = animationMode; }
206     void setCalcMode(CalcMode calcMode) { m_calcMode = calcMode; }
207
208 private:
209     virtual void animationAttributeChanged() OVERRIDE;
210     void setAttributeType(const AtomicString&);
211
212     void checkInvalidCSSAttributeType(SVGElement*);
213
214     virtual bool calculateToAtEndOfDurationValue(const String& toAtEndOfDurationString) = 0;
215     virtual bool calculateFromAndToValues(const String& fromString, const String& toString) = 0;
216     virtual bool calculateFromAndByValues(const String& fromString, const String& byString) = 0;
217     virtual void calculateAnimatedValue(float percent, unsigned repeatCount, SVGSMILElement* resultElement) = 0;
218     virtual float calculateDistance(const String& /*fromString*/, const String& /*toString*/) { return -1.f; }
219
220     void currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to);
221     void calculateKeyTimesForCalcModePaced();
222     float calculatePercentFromKeyPoints(float percent) const;
223     void currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const;
224     float calculatePercentForSpline(float percent, unsigned splineIndex) const;
225     float calculatePercentForFromTo(float percent) const;
226     unsigned calculateKeyTimesIndex(float percent) const;
227
228     void applyAnimatedValue(ShouldApplyAnimation, SVGElement* targetElement, const QualifiedName& attributeName, SVGAnimatedType*);
229     void adjustForInheritance(SVGElement* targetElement, const QualifiedName& attributeName, String&);
230
231     BEGIN_DECLARE_ANIMATED_PROPERTIES(SVGAnimationElement)
232         DECLARE_ANIMATED_BOOLEAN(ExternalResourcesRequired, externalResourcesRequired)
233     END_DECLARE_ANIMATED_PROPERTIES
234
235     // SVGTests
236     virtual void synchronizeRequiredFeatures() { SVGTests::synchronizeRequiredFeatures(this); }
237     virtual void synchronizeRequiredExtensions() { SVGTests::synchronizeRequiredExtensions(this); }
238     virtual void synchronizeSystemLanguage() { SVGTests::synchronizeSystemLanguage(this); }
239
240     void setCalcMode(const AtomicString&);
241
242     bool m_animationValid;
243
244     AttributeType m_attributeType;
245     Vector<String> m_values;
246     Vector<float> m_keyTimes;
247     Vector<float> m_keyPoints;
248     Vector<UnitBezier> m_keySplines;
249     String m_lastValuesAnimationFrom;
250     String m_lastValuesAnimationTo;
251     bool m_hasInvalidCSSAttributeType;
252     CalcMode m_calcMode;
253     AnimationMode m_animationMode;
254 };
255
256 } // namespace WebCore
257
258 #endif // ENABLE(SVG)
259 #endif // SVGAnimationElement_h