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 "SMILTime.h" 30#include "SVGElement.h" 31 32#include <wtf/HashMap.h> 33 34namespace WebCore { 35 36class ConditionEventListener; 37class SMILTimeContainer; 38 39// This class implements SMIL interval timing model as needed for SVG animation. 40class SVGSMILElement : public SVGElement { 41public: 42 SVGSMILElement(const QualifiedName&, Document&); 43 virtual ~SVGSMILElement(); 44 45 bool isSupportedAttribute(const QualifiedName&); 46 virtual void parseAttribute(const QualifiedName&, const AtomicString&) override; 47 virtual void svgAttributeChanged(const QualifiedName&) override; 48 virtual InsertionNotificationRequest insertedInto(ContainerNode&) override; 49 virtual void removedFrom(ContainerNode&) override; 50 51 virtual bool hasValidAttributeType() = 0; 52 virtual bool hasValidAttributeName(); 53 virtual void animationAttributeChanged() = 0; 54 55 SMILTimeContainer* timeContainer() { return m_timeContainer.get(); } 56 57 SVGElement* targetElement() const { return m_targetElement; } 58 const QualifiedName& attributeName() const { return m_attributeName; } 59 60 void beginByLinkActivation(); 61 62 enum Restart { 63 RestartAlways, 64 RestartWhenNotActive, 65 RestartNever 66 }; 67 68 Restart restart() const; 69 70 enum FillMode { 71 FillRemove, 72 FillFreeze 73 }; 74 75 FillMode fill() const; 76 77 SMILTime dur() const; 78 SMILTime repeatDur() const; 79 SMILTime repeatCount() const; 80 SMILTime maxValue() const; 81 SMILTime minValue() const; 82 83 SMILTime elapsed() const; 84 85 SMILTime intervalBegin() const { return m_intervalBegin; } 86 SMILTime intervalEnd() const { return m_intervalEnd; } 87 SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; } 88 SMILTime simpleDuration() const; 89 90 void seekToIntervalCorrespondingToTime(SMILTime elapsed); 91 bool progress(SMILTime elapsed, SVGSMILElement* resultsElement, bool seekToTime); 92 SMILTime nextProgressTime() const; 93 94 void reset(); 95 96 static SMILTime parseClockValue(const String&); 97 static SMILTime parseOffsetValue(const String&); 98 99 bool isContributing(SMILTime elapsed) const; 100 bool isInactive() const; 101 bool isFrozen() const; 102 103 unsigned documentOrderIndex() const { return m_documentOrderIndex; } 104 void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; } 105 106 virtual bool isAdditive() const = 0; 107 virtual void resetAnimatedType() = 0; 108 virtual void clearAnimatedType(SVGElement* targetElement) = 0; 109 virtual void applyResultsToTarget() = 0; 110 111protected: 112 void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin); 113 void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin); 114 115 void setInactive() { m_activeState = Inactive; } 116 117 virtual bool rendererIsNeeded(const RenderStyle&) override { return false; } 118 119 // Sub-classes may need to take action when the target is changed. 120 virtual void setTargetElement(SVGElement*); 121 virtual void setAttributeName(const QualifiedName&); 122 123 virtual void didNotifySubtreeInsertions(ContainerNode*) override; 124 125private: 126 void buildPendingResource() override; 127 void clearResourceReferences(); 128 129 virtual void clearTarget() override; 130 131 virtual void startedActiveInterval() = 0; 132 void endedActiveInterval(); 133 virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0; 134 135 enum BeginOrEnd { Begin, End }; 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 virtual bool isSMILElement() const override final { return true; } 200 201 SVGElement* m_targetElement; 202 203 Vector<Condition> m_conditions; 204 bool m_conditionsConnected; 205 bool m_hasEndEventConditions; 206 207 bool m_isWaitingForFirstInterval; 208 209 typedef HashSet<SVGSMILElement*> TimeDependentSet; 210 TimeDependentSet m_timeDependents; 211 212 // Instance time lists 213 Vector<SMILTimeWithOrigin> m_beginTimes; 214 Vector<SMILTimeWithOrigin> m_endTimes; 215 216 // This is the upcoming or current interval 217 SMILTime m_intervalBegin; 218 SMILTime m_intervalEnd; 219 220 SMILTime m_previousIntervalBegin; 221 222 ActiveState m_activeState; 223 float m_lastPercent; 224 unsigned m_lastRepeat; 225 226 SMILTime m_nextProgressTime; 227 228 RefPtr<SMILTimeContainer> m_timeContainer; 229 unsigned m_documentOrderIndex; 230 231 mutable SMILTime m_cachedDur; 232 mutable SMILTime m_cachedRepeatDur; 233 mutable SMILTime m_cachedRepeatCount; 234 mutable SMILTime m_cachedMin; 235 mutable SMILTime m_cachedMax; 236 237 friend class ConditionEventListener; 238}; 239 240void isSVGSMILElement(const SVGSMILElement&); // Catch unnecessary runtime check of type known at compile time. 241inline bool isSVGSMILElement(const SVGElement& element) { return element.isSMILElement(); } 242inline bool isSVGSMILElement(const Node& node) { return node.isSVGElement() && toSVGElement(node).isSMILElement(); } 243template <> inline bool isElementOfType<const SVGSMILElement>(const Element& element) { return isSVGSMILElement(element); } 244 245NODE_TYPE_CASTS(SVGSMILElement) 246 247} 248 249#endif // SVGSMILElement_h 250