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