Prevent animation when CSS attributeType is invalid.
[WebKit-https.git] / Source / WebCore / svg / animation / SVGSMILElement.h
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef SVGSMILElement_h
27 #define SVGSMILElement_h
28 #if ENABLE(SVG)
29 #include "SMILTime.h"
30 #include "SVGElement.h"
31
32 #include <wtf/HashMap.h>
33
34 namespace WebCore {
35
36 enum ResolveTarget { DoNotResolveNewTarget, ResolveNewTarget };
37
38 class ConditionEventListener;
39 class SMILTimeContainer;
40
41 // This class implements SMIL interval timing model as needed for SVG animation.
42 class SVGSMILElement : public SVGElement {
43 public:
44     SVGSMILElement(const QualifiedName&, Document*);
45     virtual ~SVGSMILElement();
46
47     static bool isSMILElement(Node*);
48
49     bool isSupportedAttribute(const QualifiedName&);
50     virtual void parseAttribute(const Attribute&) OVERRIDE;
51     virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
52     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
53     virtual void removedFrom(ContainerNode*) OVERRIDE;
54     
55     virtual bool hasValidAttributeType() = 0;
56     virtual bool hasValidAttributeName();
57     virtual void animationAttributeChanged() = 0;
58
59     SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
60
61     SVGElement* targetElement(ResolveTarget = ResolveNewTarget);
62     void resetTargetElement(ResolveTarget = ResolveNewTarget);
63     const QualifiedName& attributeName() const { return m_attributeName; }
64
65     void beginByLinkActivation();
66
67     enum Restart {
68         RestartAlways,
69         RestartWhenNotActive,
70         RestartNever
71     };
72
73     Restart restart() const;
74
75     enum FillMode {
76         FillRemove,
77         FillFreeze
78     };
79
80     FillMode fill() const;
81
82     SMILTime dur() const;
83     SMILTime repeatDur() const;
84     SMILTime repeatCount() const;
85     SMILTime maxValue() const;
86     SMILTime minValue() const;
87
88     SMILTime elapsed() const; 
89
90     SMILTime intervalBegin() const { return m_intervalBegin; }
91     SMILTime intervalEnd() const { return m_intervalEnd; }
92     SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
93     SMILTime simpleDuration() const;
94
95     void seekToIntervalCorrespondingToTime(SMILTime elapsed);
96     bool progress(SMILTime elapsed, SVGSMILElement* resultsElement, bool seekToTime);
97     SMILTime nextProgressTime() const;
98
99     void reset();
100
101     static SMILTime parseClockValue(const String&);
102     static SMILTime parseOffsetValue(const String&);
103
104     bool isContributing(SMILTime elapsed) const;
105     bool isInactive() const;
106     bool isFrozen() const;
107
108     unsigned documentOrderIndex() const { return m_documentOrderIndex; }
109     void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; }
110
111     virtual bool isAdditive() const = 0;
112     virtual void resetAnimatedType() = 0;
113     virtual void clearAnimatedType(SVGElement* targetElement) = 0;
114     virtual void applyResultsToTarget() = 0;
115
116 protected:
117     void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
118     void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
119
120     void setInactive() { m_activeState = Inactive; }
121
122     // Sub-classes may need to take action when the target is changed.
123     virtual void targetElementWillChange(SVGElement* currentTarget, SVGElement* newTarget);
124     virtual void setAttributeName(const QualifiedName&);
125
126 private:
127     virtual void startedActiveInterval() = 0;
128     void endedActiveInterval();
129     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
130
131     enum BeginOrEnd {
132         Begin,
133         End
134     };
135     
136     SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
137     void resolveFirstInterval();
138     void resolveNextInterval(bool notifyDependents);
139     void resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const;
140     SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
141     SMILTime repeatingDuration() const;
142     void checkRestart(SMILTime elapsed);
143     void beginListChanged(SMILTime eventTime);
144     void endListChanged(SMILTime eventTime);
145
146     // This represents conditions on elements begin or end list that need to be resolved on runtime
147     // for example <animate begin="otherElement.begin + 8s; button.click" ... />
148     struct Condition {
149         enum Type {
150             EventBase,
151             Syncbase,
152             AccessKey
153         };
154
155         Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeats = -1);
156         Type m_type;
157         BeginOrEnd m_beginOrEnd;
158         String m_baseID;
159         String m_name;
160         SMILTime m_offset;
161         int m_repeats;
162         RefPtr<Element> m_syncbase;
163         RefPtr<ConditionEventListener> m_eventListener;
164     };
165     bool parseCondition(const String&, BeginOrEnd beginOrEnd);
166     void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
167     Element* eventBaseFor(const Condition&);
168
169     void connectConditions();
170     void disconnectConditions();
171
172     // Event base timing
173     void handleConditionEvent(Event*, Condition*);
174
175     // Syncbase timing
176     enum NewOrExistingInterval {
177         NewInterval,
178         ExistingInterval
179     };
180
181     void notifyDependentsIntervalChanged(NewOrExistingInterval);
182     void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase, NewOrExistingInterval);
183     void addTimeDependent(SVGSMILElement*);
184     void removeTimeDependent(SVGSMILElement*);
185
186     enum ActiveState {
187         Inactive,
188         Active,
189         Frozen
190     };
191
192     QualifiedName m_attributeName;
193
194     ActiveState determineActiveState(SMILTime elapsed) const;
195     float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
196     SMILTime calculateNextProgressTime(SMILTime elapsed) const;
197
198     mutable SVGElement* m_targetElement;
199
200     Vector<Condition> m_conditions;
201     bool m_conditionsConnected;
202     bool m_hasEndEventConditions;     
203
204     bool m_isWaitingForFirstInterval;
205
206     typedef HashSet<SVGSMILElement*> TimeDependentSet;
207     TimeDependentSet m_timeDependents;
208
209     // Instance time lists
210     Vector<SMILTimeWithOrigin> m_beginTimes;
211     Vector<SMILTimeWithOrigin> m_endTimes;
212
213     // This is the upcoming or current interval
214     SMILTime m_intervalBegin;
215     SMILTime m_intervalEnd;
216
217     SMILTime m_previousIntervalBegin;
218
219     ActiveState m_activeState;
220     float m_lastPercent;
221     unsigned m_lastRepeat;
222
223     SMILTime m_nextProgressTime;
224
225     RefPtr<SMILTimeContainer> m_timeContainer;
226     unsigned m_documentOrderIndex;
227
228     mutable SMILTime m_cachedDur;
229     mutable SMILTime m_cachedRepeatDur;
230     mutable SMILTime m_cachedRepeatCount;
231     mutable SMILTime m_cachedMin;
232     mutable SMILTime m_cachedMax;
233
234     friend class ConditionEventListener;
235 };
236
237 }
238
239 #endif // ENABLE(SVG)
240 #endif // SVGSMILElement_h