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 "core/SVGNames.h" 30 #include "core/svg/SVGElement.h" 31 #include "core/svg/animation/SMILTime.h" 32 #include "platform/heap/Heap.h" 33 #include "wtf/HashMap.h" 34 35 namespace WebCore { 36 37 class ConditionEventListener; 38 class SMILTimeContainer; 39 class SVGSMILElement; 40 41 template<typename T> class EventSender; 42 typedef EventSender<SVGSMILElement> SMILEventSender; 43 44 // This class implements SMIL interval timing model as needed for SVG animation. 45 class SVGSMILElement : public SVGElement { 46 public: 47 SVGSMILElement(const QualifiedName&, Document&); 48 virtual ~SVGSMILElement(); 49 50 bool isSupportedAttribute(const QualifiedName&); 51 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; 52 virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE; 53 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 54 virtual void removedFrom(ContainerNode*) OVERRIDE; 55 56 virtual bool hasValidAttributeType() = 0; 57 virtual bool hasValidAttributeName(); 58 virtual void animationAttributeChanged() = 0; 59 60 SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); } 61 62 SVGElement* targetElement() const { return m_targetElement; } 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_interval.begin; } 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 isFrozen() const; 105 106 unsigned documentOrderIndex() const { return m_documentOrderIndex; } 107 void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; } 108 109 virtual void resetAnimatedType() = 0; 110 virtual void clearAnimatedType(SVGElement* targetElement) = 0; 111 virtual void applyResultsToTarget() = 0; 112 113 void connectSyncBaseConditions(); 114 void connectEventBaseConditions(); 115 116 void dispatchPendingEvent(SMILEventSender*); 117 void dispatchRepeatEvents(unsigned); 118 119 virtual bool isSVGDiscardElement() const { return false; } 120 121 void trace(Visitor*) OVERRIDE; 122 123 protected: 124 void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin); 125 void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin); 126 127 void setInactive() { m_activeState = Inactive; } 128 129 // Sub-classes may need to take action when the target is changed. 130 virtual void setTargetElement(SVGElement*); 131 virtual void setAttributeName(const QualifiedName&); 132 133 private: 134 virtual void buildPendingResource() OVERRIDE; 135 void clearResourceAndEventBaseReferences(); 136 void clearConditions(); 137 138 virtual void startedActiveInterval() = 0; 139 void endedActiveInterval(); 140 virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0; 141 142 virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; } 143 144 enum BeginOrEnd { 145 Begin, 146 End 147 }; 148 149 SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const; 150 151 enum ResolveInterval { 152 FirstInterval, 153 NextInterval 154 }; 155 156 SMILInterval resolveInterval(ResolveInterval) const; 157 void resolveFirstInterval(); 158 bool resolveNextInterval(); 159 SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const; 160 SMILTime repeatingDuration() const; 161 162 enum RestartedInterval { 163 DidNotRestartInterval, 164 DidRestartInterval 165 }; 166 167 RestartedInterval maybeRestartInterval(SMILTime elapsed); 168 void beginListChanged(SMILTime eventTime); 169 void endListChanged(SMILTime eventTime); 170 171 // This represents conditions on elements begin or end list that need to be resolved on runtime 172 // for example <animate begin="otherElement.begin + 8s; button.click" ... /> 173 class Condition : public NoBaseWillBeGarbageCollectedFinalized<Condition> { 174 public: 175 enum Type { 176 EventBase, 177 Syncbase, 178 AccessKey 179 }; 180 181 Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1); 182 static PassOwnPtrWillBeRawPtr<Condition> create(Type type, BeginOrEnd beginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1) 183 { 184 return adoptPtrWillBeNoop(new Condition(type, beginOrEnd, baseID, name, offset, repeat)); 185 } 186 ~Condition(); 187 void trace(Visitor*); 188 189 Type type() const { return m_type; } 190 BeginOrEnd beginOrEnd() const { return m_beginOrEnd; } 191 String baseID() const { return m_baseID; } 192 String name() const { return m_name; } 193 SMILTime offset() const { return m_offset; } 194 int repeat() const { return m_repeat; } 195 SVGSMILElement* syncBase() const { return m_syncBase.get(); } 196 void setSyncBase(SVGSMILElement* element) { m_syncBase = element; } 197 ConditionEventListener* eventListener() const { return m_eventListener.get(); } 198 void setEventListener(PassRefPtr<ConditionEventListener>); 199 200 private: 201 Type m_type; 202 BeginOrEnd m_beginOrEnd; 203 String m_baseID; 204 String m_name; 205 SMILTime m_offset; 206 int m_repeat; 207 RefPtrWillBeMember<SVGSMILElement> m_syncBase; 208 RefPtr<ConditionEventListener> m_eventListener; 209 }; 210 bool parseCondition(const String&, BeginOrEnd beginOrEnd); 211 void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd); 212 SVGElement* eventBaseFor(const Condition&); 213 214 void disconnectSyncBaseConditions(); 215 void disconnectEventBaseConditions(); 216 217 // Event base timing 218 void handleConditionEvent(Event*, Condition*); 219 220 void notifyDependentsIntervalChanged(); 221 void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase); 222 void addSyncBaseDependent(SVGSMILElement*); 223 void removeSyncBaseDependent(SVGSMILElement*); 224 225 enum ActiveState { 226 Inactive, 227 Active, 228 Frozen 229 }; 230 231 QualifiedName m_attributeName; 232 233 ActiveState determineActiveState(SMILTime elapsed) const; 234 float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const; 235 SMILTime calculateNextProgressTime(SMILTime elapsed) const; 236 237 RawPtrWillBeMember<SVGElement> m_targetElement; 238 239 WillBeHeapVector<OwnPtrWillBeMember<Condition> > m_conditions; 240 bool m_syncBaseConditionsConnected; 241 bool m_hasEndEventConditions; 242 243 bool m_isWaitingForFirstInterval; 244 245 typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGSMILElement> > TimeDependentSet; 246 TimeDependentSet m_syncBaseDependents; 247 248 // Instance time lists 249 Vector<SMILTimeWithOrigin> m_beginTimes; 250 Vector<SMILTimeWithOrigin> m_endTimes; 251 252 // This is the upcoming or current interval 253 SMILInterval m_interval; 254 255 SMILTime m_previousIntervalBegin; 256 257 ActiveState m_activeState; 258 float m_lastPercent; 259 unsigned m_lastRepeat; 260 261 SMILTime m_nextProgressTime; 262 263 RefPtrWillBeMember<SMILTimeContainer> m_timeContainer; 264 unsigned m_documentOrderIndex; 265 266 Vector<unsigned> m_repeatEventCountList; 267 268 mutable SMILTime m_cachedDur; 269 mutable SMILTime m_cachedRepeatDur; 270 mutable SMILTime m_cachedRepeatCount; 271 mutable SMILTime m_cachedMin; 272 mutable SMILTime m_cachedMax; 273 274 friend class ConditionEventListener; 275 }; 276 277 inline bool isSVGSMILElement(const Node& node) 278 { 279 return node.hasTagName(SVGNames::setTag) || node.hasTagName(SVGNames::animateTag) || node.hasTagName(SVGNames::animateMotionTag) 280 || node.hasTagName(SVGNames::animateTransformTag) || node.hasTagName((SVGNames::discardTag)); 281 } 282 283 DEFINE_ELEMENT_TYPE_CASTS_WITH_FUNCTION(SVGSMILElement); 284 285 } 286 287 #endif // SVGSMILElement_h 288