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 "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