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/SVGNames.h"
     30 #include "core/svg/SVGElement.h"
     31 #include "core/svg/SVGTests.h"
     32 #include "core/svg/animation/SMILTime.h"
     33 #include "platform/heap/Heap.h"
     34 #include "wtf/HashMap.h"
     35 
     36 namespace blink {
     37 
     38 class ConditionEventListener;
     39 class SMILTimeContainer;
     40 class SVGSMILElement;
     41 
     42 template<typename T> class EventSender;
     43 typedef EventSender<SVGSMILElement> SMILEventSender;
     44 
     45 // This class implements SMIL interval timing model as needed for SVG animation.
     46 class SVGSMILElement : public SVGElement, public SVGTests {
     47 public:
     48     SVGSMILElement(const QualifiedName&, Document&);
     49     virtual ~SVGSMILElement();
     50 
     51     bool isSupportedAttribute(const QualifiedName&);
     52     virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
     53     virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
     54     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
     55     virtual void removedFrom(ContainerNode*) OVERRIDE;
     56 
     57     virtual bool hasValidAttributeType() = 0;
     58     virtual bool hasValidAttributeName();
     59     virtual void animationAttributeChanged() = 0;
     60 
     61     SMILTimeContainer* timeContainer() const { return m_timeContainer.get(); }
     62 
     63     SVGElement* targetElement() const { return m_targetElement; }
     64     const QualifiedName& attributeName() const { return m_attributeName; }
     65 
     66     void beginByLinkActivation();
     67 
     68     enum Restart {
     69         RestartAlways,
     70         RestartWhenNotActive,
     71         RestartNever
     72     };
     73 
     74     Restart restart() const;
     75 
     76     enum FillMode {
     77         FillRemove,
     78         FillFreeze
     79     };
     80 
     81     FillMode fill() const;
     82 
     83     SMILTime dur() const;
     84     SMILTime repeatDur() const;
     85     SMILTime repeatCount() const;
     86     SMILTime maxValue() const;
     87     SMILTime minValue() const;
     88 
     89     SMILTime elapsed() const;
     90 
     91     SMILTime intervalBegin() const { return m_interval.begin; }
     92     SMILTime previousIntervalBegin() const { return m_previousIntervalBegin; }
     93     SMILTime simpleDuration() const;
     94 
     95     void seekToIntervalCorrespondingToTime(SMILTime elapsed);
     96     bool progress(SMILTime elapsed, SVGSMILElement* resultsElement, bool seekToTime);
     97     SMILTime nextProgressTime() const;
     98 
     99     void reset();
    100 
    101     static SMILTime parseClockValue(const String&);
    102     static SMILTime parseOffsetValue(const String&);
    103 
    104     bool isContributing(SMILTime elapsed) const;
    105     bool isFrozen() const;
    106 
    107     unsigned documentOrderIndex() const { return m_documentOrderIndex; }
    108     void setDocumentOrderIndex(unsigned index) { m_documentOrderIndex = index; }
    109 
    110     virtual void resetAnimatedType() = 0;
    111     virtual void clearAnimatedType(SVGElement* targetElement) = 0;
    112     virtual void applyResultsToTarget() = 0;
    113 
    114     void connectSyncBaseConditions();
    115     void connectEventBaseConditions();
    116 
    117     void dispatchPendingEvent(SMILEventSender*);
    118     void dispatchRepeatEvents(unsigned);
    119 
    120     virtual bool isSVGDiscardElement() const { return false; }
    121 
    122     void trace(Visitor*) OVERRIDE;
    123 
    124 protected:
    125     void addBeginTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
    126     void addEndTime(SMILTime eventTime, SMILTime endTime, SMILTimeWithOrigin::Origin = SMILTimeWithOrigin::ParserOrigin);
    127 
    128     void setInactive() { m_activeState = Inactive; }
    129 
    130     // Sub-classes may need to take action when the target is changed.
    131     virtual void setTargetElement(SVGElement*);
    132     virtual void setAttributeName(const QualifiedName&);
    133 
    134 private:
    135     virtual void buildPendingResource() OVERRIDE;
    136     void clearResourceAndEventBaseReferences();
    137     void clearConditions();
    138 
    139     virtual void startedActiveInterval() = 0;
    140     void endedActiveInterval();
    141     virtual void updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement) = 0;
    142 
    143     virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE { return false; }
    144 
    145     enum BeginOrEnd {
    146         Begin,
    147         End
    148     };
    149 
    150     SMILTime findInstanceTime(BeginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const;
    151 
    152     enum ResolveInterval {
    153         FirstInterval,
    154         NextInterval
    155     };
    156 
    157     SMILInterval resolveInterval(ResolveInterval) const;
    158     void resolveFirstInterval();
    159     bool resolveNextInterval();
    160     SMILTime resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const;
    161     SMILTime repeatingDuration() const;
    162 
    163     enum RestartedInterval {
    164         DidNotRestartInterval,
    165         DidRestartInterval
    166     };
    167 
    168     RestartedInterval maybeRestartInterval(SMILTime elapsed);
    169     void beginListChanged(SMILTime eventTime);
    170     void endListChanged(SMILTime eventTime);
    171 
    172     // This represents conditions on elements begin or end list that need to be resolved on runtime
    173     // for example <animate begin="otherElement.begin + 8s; button.click" ... />
    174     class Condition : public NoBaseWillBeGarbageCollectedFinalized<Condition> {
    175     public:
    176         enum Type {
    177             EventBase,
    178             Syncbase,
    179             AccessKey
    180         };
    181 
    182         Condition(Type, BeginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1);
    183         static PassOwnPtrWillBeRawPtr<Condition> create(Type type, BeginOrEnd beginOrEnd, const String& baseID, const String& name, SMILTime offset, int repeat = -1)
    184         {
    185             return adoptPtrWillBeNoop(new Condition(type, beginOrEnd, baseID, name, offset, repeat));
    186         }
    187         ~Condition();
    188         void trace(Visitor*);
    189 
    190         Type type() const { return m_type; }
    191         BeginOrEnd beginOrEnd() const { return m_beginOrEnd; }
    192         String baseID() const { return m_baseID; }
    193         String name() const { return m_name; }
    194         SMILTime offset() const { return m_offset; }
    195         int repeat() const { return m_repeat; }
    196         SVGSMILElement* syncBase() const { return m_syncBase.get(); }
    197         void setSyncBase(SVGSMILElement* element) { m_syncBase = element; }
    198         ConditionEventListener* eventListener() const { return m_eventListener.get(); }
    199         void setEventListener(PassRefPtr<ConditionEventListener>);
    200 
    201     private:
    202         Type m_type;
    203         BeginOrEnd m_beginOrEnd;
    204         String m_baseID;
    205         String m_name;
    206         SMILTime m_offset;
    207         int m_repeat;
    208         RefPtrWillBeMember<SVGSMILElement> m_syncBase;
    209         RefPtr<ConditionEventListener> m_eventListener;
    210     };
    211     bool parseCondition(const String&, BeginOrEnd beginOrEnd);
    212     void parseBeginOrEnd(const String&, BeginOrEnd beginOrEnd);
    213     SVGElement* eventBaseFor(const Condition&);
    214 
    215     void disconnectSyncBaseConditions();
    216     void disconnectEventBaseConditions();
    217 
    218     // Event base timing
    219     void handleConditionEvent(Event*, Condition*);
    220 
    221     void notifyDependentsIntervalChanged();
    222     void createInstanceTimesFromSyncbase(SVGSMILElement* syncbase);
    223     void addSyncBaseDependent(SVGSMILElement*);
    224     void removeSyncBaseDependent(SVGSMILElement*);
    225 
    226     enum ActiveState {
    227         Inactive,
    228         Active,
    229         Frozen
    230     };
    231 
    232     QualifiedName m_attributeName;
    233 
    234     ActiveState determineActiveState(SMILTime elapsed) const;
    235     float calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const;
    236     SMILTime calculateNextProgressTime(SMILTime elapsed) const;
    237 
    238     RawPtrWillBeMember<SVGElement> m_targetElement;
    239 
    240     WillBeHeapVector<OwnPtrWillBeMember<Condition> > m_conditions;
    241     bool m_syncBaseConditionsConnected;
    242     bool m_hasEndEventConditions;
    243 
    244     bool m_isWaitingForFirstInterval;
    245 
    246     typedef WillBeHeapHashSet<RawPtrWillBeMember<SVGSMILElement> > TimeDependentSet;
    247     TimeDependentSet m_syncBaseDependents;
    248 
    249     // Instance time lists
    250     Vector<SMILTimeWithOrigin> m_beginTimes;
    251     Vector<SMILTimeWithOrigin> m_endTimes;
    252 
    253     // This is the upcoming or current interval
    254     SMILInterval m_interval;
    255 
    256     SMILTime m_previousIntervalBegin;
    257 
    258     ActiveState m_activeState;
    259     float m_lastPercent;
    260     unsigned m_lastRepeat;
    261 
    262     SMILTime m_nextProgressTime;
    263 
    264     RefPtrWillBeMember<SMILTimeContainer> m_timeContainer;
    265     unsigned m_documentOrderIndex;
    266 
    267     Vector<unsigned> m_repeatEventCountList;
    268 
    269     mutable SMILTime m_cachedDur;
    270     mutable SMILTime m_cachedRepeatDur;
    271     mutable SMILTime m_cachedRepeatCount;
    272     mutable SMILTime m_cachedMin;
    273     mutable SMILTime m_cachedMax;
    274 
    275     friend class ConditionEventListener;
    276 };
    277 
    278 inline bool isSVGSMILElement(const SVGElement& element)
    279 {
    280     return element.hasTagName(SVGNames::setTag) || element.hasTagName(SVGNames::animateTag) || element.hasTagName(SVGNames::animateMotionTag)
    281         || element.hasTagName(SVGNames::animateTransformTag) || element.hasTagName((SVGNames::discardTag));
    282 }
    283 
    284 DEFINE_SVGELEMENT_TYPE_CASTS_WITH_FUNCTION(SVGSMILElement);
    285 
    286 }
    287 
    288 #endif // SVGSMILElement_h
    289