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
27#ifndef SVGSMILElement_h
28#define SVGSMILElement_h
29#if ENABLE(SVG_ANIMATION)
30
31#include "SVGElement.h"
32#include "SMILTime.h"
33#include <wtf/HashMap.h>
34
35namespace WebCore {
36
37    class ConditionEventListener;
38    class SMILTimeContainer;
39
40    // This class implements SMIL interval timing model as needed for SVG animation.
41    class SVGSMILElement : public SVGElement {
42    public:
43        SVGSMILElement(const QualifiedName&, Document*);
44        virtual ~SVGSMILElement();
45
46        static bool isSMILElement(Node* node);
47
48        virtual void parseMappedAttribute(MappedAttribute*);
49        virtual void attributeChanged(Attribute*, bool preserveDecls);
50        virtual void insertedIntoDocument();
51        virtual void removedFromDocument();
52        virtual void finishParsingChildren();
53
54        SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
55
56        SVGElement* targetElement() const;
57        String attributeName() const;
58
59        void beginByLinkActivation();
60
61        enum Restart { RestartAlways, RestartWhenNotActive, RestartNever };
62        Restart restart() const;
63
64        enum FillMode { FillRemove, FillFreeze };
65        FillMode fill() const;
66
67        String xlinkHref() const;
68
69        SMILTime dur() const;
70        SMILTime repeatDur() const;
71        SMILTime repeatCount() const;
72        SMILTime maxValue() const;
73        SMILTime minValue() const;
74
75        SMILTime elapsed() const;
76
77        SMILTime intervalBegin() const { return m_intervalBegin; }
78        SMILTime intervalEnd() const { return m_intervalEnd; }
79        SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
80        SMILTime simpleDuration() const;
81
82        void progress(SMILTime elapsed, SVGSMILElement* resultsElement);
83        SMILTime nextProgressTime() const;
84
85        static SMILTime parseClockValue(const String&);
86        static SMILTime parseOffsetValue(const String&);
87
88        bool isContributing(SMILTime elapsed) const;
89        bool isInactive() const;
90        bool isFrozen() const;
91
92        unsigned documentOrderIndex() const { return m_documentOrderIndex; }
93        void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; }
94
95        virtual bool isAdditive() const = 0;
96        virtual void resetToBaseValue(const String&) = 0;
97        virtual void applyResultsToTarget() = 0;
98
99protected:
100        void addBeginTime(SMILTime time);
101        void addEndTime(SMILTime time);
102
103private:
104        virtual void startedActiveInterval() = 0;
105        virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
106        virtual void endedActiveInterval() = 0;
107
108        enum BeginOrEnd { Begin, End };
109        SMILTime findInstanceTime(BeginOrEnd beginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
110        void resolveFirstInterval();
111        void resolveNextInterval();
112        void resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const;
113        SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
114        SMILTime repeatingDuration() const;
115        void checkRestart(SMILTime elapsed);
116        void beginListChanged();
117        void endListChanged();
118        void reschedule();
119
120        // This represents conditions on elements begin or end list that need to be resolved on runtime
121        // for example <animate begin="otherElement.begin + 8s; button.click" ... />
122        struct Condition {
123            enum Type { EventBase, Syncbase, AccessKey };
124            Condition(Type, BeginOrEnd beginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeats = -1);
125            Type m_type;
126            BeginOrEnd m_beginOrEnd;
127            String m_baseID;
128            String m_name;
129            SMILTime m_offset;
130            int m_repeats;
131            RefPtr<Element> m_syncbase;
132            RefPtr<ConditionEventListener> m_eventListener;
133        };
134        bool parseCondition(const String&, BeginOrEnd beginOrEnd);
135        void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
136
137        void connectConditions();
138        void disconnectConditions();
139
140        // Event base timing
141        void handleConditionEvent(Event*, Condition*);
142
143        // Syncbase timing
144        enum NewOrExistingInterval { NewInterval, ExistingInterval };
145        void notifyDependentsIntervalChanged(NewOrExistingInterval);
146        void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase, NewOrExistingInterval);
147        void addTimeDependent(SVGSMILElement*);
148        void removeTimeDependent(SVGSMILElement*);
149
150        enum ActiveState { Inactive, Active, Frozen };
151        ActiveState determineActiveState(SMILTime elapsed) const;
152        float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
153        SMILTime calculateNextProgressTime(SMILTime elapsed) const;
154
155        Vector<Condition> m_conditions;
156        bool m_conditionsConnected;
157        bool m_hasEndEventConditions;
158
159        typedef HashSet<SVGSMILElement*> TimeDependentSet;
160        TimeDependentSet m_timeDependents;
161
162        // Instance time lists
163        Vector<SMILTime> m_beginTimes;
164        Vector<SMILTime> m_endTimes;
165
166        // This is the upcoming or current interval
167        SMILTime m_intervalBegin;
168        SMILTime m_intervalEnd;
169
170        SMILTime m_previousIntervalBegin;
171
172        bool m_isWaitingForFirstInterval;
173
174        ActiveState m_activeState;
175        float m_lastPercent;
176        unsigned m_lastRepeat;
177
178        SMILTime m_nextProgressTime;
179
180        RefPtr<SMILTimeContainer> m_timeContainer;
181        unsigned m_documentOrderIndex;
182
183        mutable SMILTime m_cachedDur;
184        mutable SMILTime m_cachedRepeatDur;
185        mutable SMILTime m_cachedRepeatCount;
186        mutable SMILTime m_cachedMin;
187        mutable SMILTime m_cachedMax;
188
189        friend class ConditionEventListener;
190    };
191
192}
193
194#endif
195#endif
196
197