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