2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef SVGSMILElement_h
27 #define SVGSMILElement_h
30 #include "core/svg/SVGElement.h"
31 #include "core/svg/animation/SMILTime.h"
32 #include "wtf/HashMap.h"
36 class ConditionEventListener;
37 class SMILTimeContainer;
40 template<typename T> class EventSender;
41 typedef EventSender<SVGSMILElement> SMILEventSender;
43 // This class implements SMIL interval timing model as needed for SVG animation.
44 class SVGSMILElement : public SVGElement {
46 SVGSMILElement(const QualifiedName&, Document&);
47 virtual ~SVGSMILElement();
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;
55 virtual bool hasValidAttributeType() = 0;
56 virtual bool hasValidAttributeName();
57 virtual void animationAttributeChanged() = 0;
59 SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
61 SVGElement* targetElement() const { return m_targetElement; }
62 const QualifiedName& attributeName() const { return m_attributeName; }
64 void beginByLinkActivation();
72 Restart restart() const;
79 FillMode fill() const;
82 SMILTime repeatDur() const;
83 SMILTime repeatCount() const;
84 SMILTime maxValue() const;
85 SMILTime minValue() const;
87 SMILTime elapsed() const;
89 SMILTime intervalBegin() const { return m_intervalBegin; }
90 SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
91 SMILTime simpleDuration() const;
93 void seekToIntervalCorrespondingToTime(SMILTime elapsed);
94 bool progress(SMILTime elapsed, SVGSMILElement* resultsElement, bool seekToTime);
95 SMILTime nextProgressTime() const;
99 static SMILTime parseClockValue(const String&);
100 static SMILTime parseOffsetValue(const String&);
102 bool isContributing(SMILTime elapsed) const;
103 bool isFrozen() const;
105 unsigned documentOrderIndex() const { return m_documentOrderIndex; }
106 void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; }
108 virtual void resetAnimatedType() = 0;
109 virtual void clearAnimatedType(SVGElement* targetElement) = 0;
110 virtual void applyResultsToTarget() = 0;
112 void connectSyncBaseConditions();
113 void connectEventBaseConditions();
115 void dispatchPendingEvent(SMILEventSender*);
116 void dispatchRepeatEvents(unsigned);
118 virtual bool isSVGDiscardElement() const { return false; }
121 void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
122 void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
124 void setInactive() { m_activeState = Inactive; }
126 // Sub-classes may need to take action when the target is changed.
127 virtual void setTargetElement(SVGElement*);
128 virtual void setAttributeName(const QualifiedName&);
131 virtual void buildPendingResource() OVERRIDE;
132 void clearResourceAndEventBaseReferences();
133 void clearConditions();
135 virtual void startedActiveInterval() = 0;
136 void endedActiveInterval();
137 virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
139 virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; }
146 SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
147 void resolveFirstInterval();
148 bool resolveNextInterval();
149 void resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const;
150 SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
151 SMILTime repeatingDuration() const;
153 enum RestartedInterval {
154 DidNotRestartInterval,
158 RestartedInterval maybeRestartInterval(SMILTime elapsed);
159 void beginListChanged(SMILTime eventTime);
160 void endListChanged(SMILTime eventTime);
162 // This represents conditions on elements begin or end list that need to be resolved on runtime
163 // for example <animate begin="otherElement.begin + 8s; button.click" ... />
171 Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1);
173 BeginOrEnd m_beginOrEnd;
178 RefPtr<Element> m_syncbase;
179 RefPtr<ConditionEventListener> m_eventListener;
181 bool parseCondition(const String&, BeginOrEnd beginOrEnd);
182 void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
183 SVGElement* eventBaseFor(const Condition&);
185 void disconnectSyncBaseConditions();
186 void disconnectEventBaseConditions();
189 void handleConditionEvent(Event*, Condition*);
191 void notifyDependentsIntervalChanged();
192 void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase);
193 void addSyncBaseDependent(SVGSMILElement*);
194 void removeSyncBaseDependent(SVGSMILElement*);
202 QualifiedName m_attributeName;
204 ActiveState determineActiveState(SMILTime elapsed) const;
205 float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
206 SMILTime calculateNextProgressTime(SMILTime elapsed) const;
208 mutable SVGElement* m_targetElement;
210 Vector<Condition> m_conditions;
211 bool m_syncBaseConditionsConnected;
212 bool m_hasEndEventConditions;
214 bool m_isWaitingForFirstInterval;
216 typedef HashSet<SVGSMILElement*> TimeDependentSet;
217 TimeDependentSet m_syncBaseDependents;
219 // Instance time lists
220 Vector<SMILTimeWithOrigin> m_beginTimes;
221 Vector<SMILTimeWithOrigin> m_endTimes;
223 // This is the upcoming or current interval
224 SMILTime m_intervalBegin;
225 SMILTime m_intervalEnd;
227 SMILTime m_previousIntervalBegin;
229 ActiveState m_activeState;
231 unsigned m_lastRepeat;
233 SMILTime m_nextProgressTime;
235 RefPtr<SMILTimeContainer> m_timeContainer;
236 unsigned m_documentOrderIndex;
238 Vector<unsigned> m_repeatEventCountList;
240 mutable SMILTime m_cachedDur;
241 mutable SMILTime m_cachedRepeatDur;
242 mutable SMILTime m_cachedRepeatCount;
243 mutable SMILTime m_cachedMin;
244 mutable SMILTime m_cachedMax;
246 friend class ConditionEventListener;
249 inline bool isSVGSMILElement(const Node& node)
251 return node.hasTagName(SVGNames::setTag) || node.hasTagName(SVGNames::animateTag) || node.hasTagName(SVGNames::animateMotionTag)
252 || node.hasTagName(SVGNames::animateTransformTag) || node.hasTagName((SVGNames::discardTag));
255 DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(SVGSMILElement);
259 #endif // SVGSMILElement_h