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