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
29 #include "SVGNames.h"
30 #include "core/svg/SVGElement.h"
31 #include "core/svg/animation/SMILTime.h"
32 #include "wtf/HashMap.h"
33
34 namespace WebCore {
35
36 class ConditionEventListener;
37 class SMILTimeContainer;
38 class SVGSMILElement;
39
40 template<typename T> class EventSender;
41 typedef EventSender<SVGSMILElement> SMILEventSender;
42
43 // This class implements SMIL interval timing model as needed for SVG animation.
44 class SVGSMILElement : public SVGElement {
45 public:
46 SVGSMILElement(const QualifiedName&, Document&);
47 virtual ~SVGSMILElement();
48
49 bool isSupportedAttribute(const QualifiedName&);
50 virtual void parseAttribute(const QualifiedName&, const AtomicString&) 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
timeContainer()59 SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
60
targetElement()61 SVGElement* targetElement() const { return m_targetElement; }
attributeName()62 const QualifiedName& attributeName() const { return m_attributeName; }
63
64 void beginByLinkActivation();
65
66 enum Restart {
67 RestartAlways,
68 RestartWhenNotActive,
69 RestartNever
70 };
71
72 Restart restart() const;
73
74 enum FillMode {
75 FillRemove,
76 FillFreeze
77 };
78
79 FillMode fill() const;
80
81 SMILTime dur() const;
82 SMILTime repeatDur() const;
83 SMILTime repeatCount() const;
84 SMILTime maxValue() const;
85 SMILTime minValue() const;
86
87 SMILTime elapsed() const;
88
intervalBegin()89 SMILTime intervalBegin() const { return m_intervalBegin; }
intervalEnd()90 SMILTime intervalEnd() const { return m_intervalEnd; }
previousIntervalBegin()91 SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
92 SMILTime simpleDuration() const;
93
94 void seekToIntervalCorrespondingToTime(SMILTime elapsed);
95 bool progress(SMILTime elapsed, SVGSMILElement* resultsElement, bool seekToTime);
96 SMILTime nextProgressTime() const;
97
98 void reset();
99
100 static SMILTime parseClockValue(const String&);
101 static SMILTime parseOffsetValue(const String&);
102
103 bool isContributing(SMILTime elapsed) const;
104 bool isInactive() const;
105 bool isFrozen() const;
106
documentOrderIndex()107 unsigned documentOrderIndex() const { return m_documentOrderIndex; }
setDocumentOrderIndex(unsigned index)108 void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; }
109
110 virtual bool isAdditive() const = 0;
111 virtual void resetAnimatedType() = 0;
112 virtual void clearAnimatedType(SVGElement* targetElement) = 0;
113 virtual void applyResultsToTarget() = 0;
114
115 void connectConditions();
116
117 void dispatchPendingEvent(SMILEventSender*);
118 void dispatchRepeatEvents(unsigned);
119
120 protected:
121 void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
122 void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
123
setInactive()124 void setInactive() { m_activeState = Inactive; }
125
126 // Sub-classes may need to take action when the target is changed.
127 virtual void setTargetElement(SVGElement*);
128 virtual void setAttributeName(const QualifiedName&);
129
130 private:
131 void buildPendingResource();
132 void clearResourceReferences();
133
134 virtual void startedActiveInterval() = 0;
135 void endedActiveInterval();
136 virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
137
rendererIsNeeded(const RenderStyle &)138 virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; }
139
140 enum BeginOrEnd {
141 Begin,
142 End
143 };
144
145 SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
146 void resolveFirstInterval();
147 bool resolveNextInterval();
148 void resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const;
149 SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
150 SMILTime repeatingDuration() const;
151 void checkRestart(SMILTime elapsed);
152 void beginListChanged(SMILTime eventTime);
153 void endListChanged(SMILTime eventTime);
154
155 // This represents conditions on elements begin or end list that need to be resolved on runtime
156 // for example <animate begin="otherElement.begin + 8s; button.click" ... />
157 struct Condition {
158 enum Type {
159 EventBase,
160 Syncbase,
161 AccessKey
162 };
163
164 Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1);
165 Type m_type;
166 BeginOrEnd m_beginOrEnd;
167 String m_baseID;
168 String m_name;
169 SMILTime m_offset;
170 int m_repeat;
171 RefPtr<Element> m_syncbase;
172 RefPtr<ConditionEventListener> m_eventListener;
173 };
174 bool parseCondition(const String&, BeginOrEnd beginOrEnd);
175 void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
176 Element* eventBaseFor(const Condition&);
177
178 void disconnectConditions();
179
180 // Event base timing
181 void handleConditionEvent(Event*, Condition*);
182
183 void notifyDependentsIntervalChanged();
184 void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase);
185 void addTimeDependent(SVGSMILElement*);
186 void removeTimeDependent(SVGSMILElement*);
187
188 enum ActiveState {
189 Inactive,
190 Active,
191 Frozen
192 };
193
194 QualifiedName m_attributeName;
195
196 ActiveState determineActiveState(SMILTime elapsed) const;
197 float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
198 SMILTime calculateNextProgressTime(SMILTime elapsed) const;
199
200 mutable SVGElement* m_targetElement;
201
202 Vector<Condition> m_conditions;
203 bool m_conditionsConnected;
204 bool m_hasEndEventConditions;
205
206 bool m_isWaitingForFirstInterval;
207
208 typedef HashSet<SVGSMILElement*> TimeDependentSet;
209 TimeDependentSet m_timeDependents;
210
211 // Instance time lists
212 Vector<SMILTimeWithOrigin> m_beginTimes;
213 Vector<SMILTimeWithOrigin> m_endTimes;
214
215 // This is the upcoming or current interval
216 SMILTime m_intervalBegin;
217 SMILTime m_intervalEnd;
218
219 SMILTime m_previousIntervalBegin;
220
221 ActiveState m_activeState;
222 float m_lastPercent;
223 unsigned m_lastRepeat;
224
225 SMILTime m_nextProgressTime;
226
227 RefPtr<SMILTimeContainer> m_timeContainer;
228 unsigned m_documentOrderIndex;
229
230 Vector<unsigned> m_repeatEventCountList;
231
232 mutable SMILTime m_cachedDur;
233 mutable SMILTime m_cachedRepeatDur;
234 mutable SMILTime m_cachedRepeatCount;
235 mutable SMILTime m_cachedMin;
236 mutable SMILTime m_cachedMax;
237
238 friend class ConditionEventListener;
239 };
240
isSVGSMILElement(const Node & node)241 inline bool isSVGSMILElement(const Node& node)
242 {
243 return node.hasTagName(SVGNames::setTag) || node.hasTagName(SVGNames::animateTag) || node.hasTagName(SVGNames::animateMotionTag)
244 || node.hasTagName(SVGNames::animateTransformTag) || node.hasTagName(SVGNames::animateColorTag);
245 }
246
247 DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(SVGSMILElement);
248
249 }
250
251 #endif // SVGSMILElement_h
252