Home | History | Annotate | Download | only in animation
      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 #if ENABLE(SVG_ANIMATION)
     29 #include "SMILTime.h"
     30 #include "SVGElement.h"
     31 
     32 #include <wtf/HashMap.h>
     33 
     34 namespace WebCore {
     35 
     36 class ConditionEventListener;
     37 class SMILTimeContainer;
     38 
     39 // This class implements SMIL interval timing model as needed for SVG animation.
     40 class SVGSMILElement : public SVGElement {
     41 public:
     42     SVGSMILElement(const QualifiedName&, Document*);
     43     virtual ~SVGSMILElement();
     44 
     45     static bool isSMILElement(Node*);
     46 
     47     virtual void parseMappedAttribute(Attribute*);
     48     virtual void attributeChanged(Attribute*, bool preserveDecls);
     49     virtual void insertedIntoDocument();
     50     virtual void removedFromDocument();
     51     virtual void finishParsingChildren();
     52 
     53     virtual bool hasValidAttributeType() const = 0;
     54 
     55     SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
     56 
     57     SVGElement* targetElement() const;
     58     void resetTargetElement() { m_targetElement = 0; }
     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     String xlinkHref() const;
     79 
     80     SMILTime dur() const;
     81     SMILTime repeatDur() const;
     82     SMILTime repeatCount() const;
     83     SMILTime maxValue() const;
     84     SMILTime minValue() const;
     85 
     86     SMILTime elapsed() const;
     87 
     88     SMILTime intervalBegin() const { return m_intervalBegin; }
     89     SMILTime intervalEnd() const { return m_intervalEnd; }
     90     SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
     91     SMILTime simpleDuration() const;
     92 
     93     void progress(SMILTime elapsed, SVGSMILElement* resultsElement);
     94     SMILTime nextProgressTime() const;
     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 resetToBaseValue(const String&) = 0;
    108     virtual void applyResultsToTarget() = 0;
    109 
    110 protected:
    111     void addBeginTime(SMILTime);
    112     void addEndTime(SMILTime);
    113 
    114 private:
    115     virtual void startedActiveInterval() = 0;
    116     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
    117     virtual void endedActiveInterval() = 0;
    118 
    119     enum BeginOrEnd {
    120         Begin,
    121         End
    122     };
    123 
    124     SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
    125     void resolveFirstInterval();
    126     void resolveNextInterval();
    127     void resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const;
    128     SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
    129     SMILTime repeatingDuration() const;
    130     void checkRestart(SMILTime elapsed);
    131     void beginListChanged();
    132     void endListChanged();
    133     void reschedule();
    134 
    135     // This represents conditions on elements begin or end list that need to be resolved on runtime
    136     // for example <animate begin="otherElement.begin + 8s; button.click" ... />
    137     struct Condition {
    138         enum Type {
    139             EventBase,
    140             Syncbase,
    141             AccessKey
    142         };
    143 
    144         Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeats = -1);
    145         Type m_type;
    146         BeginOrEnd m_beginOrEnd;
    147         String m_baseID;
    148         String m_name;
    149         SMILTime m_offset;
    150         int m_repeats;
    151         RefPtr<Element> m_syncbase;
    152         RefPtr<ConditionEventListener> m_eventListener;
    153     };
    154     bool parseCondition(const String&, BeginOrEnd beginOrEnd);
    155     void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
    156     Element* eventBaseFor(const Condition&) const;
    157 
    158     void connectConditions();
    159     void disconnectConditions();
    160 
    161     // Event base timing
    162     void handleConditionEvent(Event*, Condition*);
    163 
    164     // Syncbase timing
    165     enum NewOrExistingInterval {
    166         NewInterval,
    167         ExistingInterval
    168     };
    169 
    170     void notifyDependentsIntervalChanged(NewOrExistingInterval);
    171     void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase, NewOrExistingInterval);
    172     void addTimeDependent(SVGSMILElement*);
    173     void removeTimeDependent(SVGSMILElement*);
    174 
    175     enum ActiveState {
    176         Inactive,
    177         Active,
    178         Frozen
    179     };
    180 
    181     QualifiedName m_attributeName;
    182 
    183     ActiveState determineActiveState(SMILTime elapsed) const;
    184     float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
    185     SMILTime calculateNextProgressTime(SMILTime elapsed) const;
    186 
    187     mutable SVGElement* m_targetElement;
    188 
    189     Vector<Condition> m_conditions;
    190     bool m_conditionsConnected;
    191     bool m_hasEndEventConditions;
    192 
    193     typedef HashSet<SVGSMILElement*> TimeDependentSet;
    194     TimeDependentSet m_timeDependents;
    195 
    196     // Instance time lists
    197     Vector<SMILTime> m_beginTimes;
    198     Vector<SMILTime> m_endTimes;
    199 
    200     // This is the upcoming or current interval
    201     SMILTime m_intervalBegin;
    202     SMILTime m_intervalEnd;
    203 
    204     SMILTime m_previousIntervalBegin;
    205 
    206     bool m_isWaitingForFirstInterval;
    207 
    208     ActiveState m_activeState;
    209     float m_lastPercent;
    210     unsigned m_lastRepeat;
    211 
    212     SMILTime m_nextProgressTime;
    213 
    214     RefPtr<SMILTimeContainer> m_timeContainer;
    215     unsigned m_documentOrderIndex;
    216 
    217     mutable SMILTime m_cachedDur;
    218     mutable SMILTime m_cachedRepeatDur;
    219     mutable SMILTime m_cachedRepeatCount;
    220     mutable SMILTime m_cachedMin;
    221     mutable SMILTime m_cachedMax;
    222 
    223     friend class ConditionEventListener;
    224 };
    225 
    226 }
    227 
    228 #endif // ENABLE(SVG)
    229 #endif // SVGSMILElement_h
    230 
    231