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 59 SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); } 60 61 SVGElement* targetElement() const { return m_targetElement; } 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 89 SMILTime intervalBegin() const { return m_intervalBegin; } 90 SMILTime intervalEnd() const { return m_intervalEnd; } 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 107 unsigned documentOrderIndex() const { return m_documentOrderIndex; } 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 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 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 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