summaryrefslogtreecommitdiffstats
path: root/WebCore/page/animation/AnimationBase.h
blob: a9571192545d8cff706383a994ebb9a4367c5ea4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
 * Copyright (C) 2007 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer. 
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution. 
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef AnimationBase_h
#define AnimationBase_h

#include "AtomicString.h"
#include <wtf/HashMap.h>

namespace WebCore {

class Animation;
class AnimationBase;
class AnimationController;
class CompositeAnimation;
class Element;
class Node;
class RenderObject;
class RenderStyle;
class TimingFunction;

class AnimationBase : public RefCounted<AnimationBase> {
    friend class CompositeAnimation;

public:
    AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim);
    virtual ~AnimationBase();

    RenderObject* renderer() const { return m_object; }
    void clearRenderer() { m_object = 0; }
    
    double duration() const;

    // Animations and Transitions go through the states below. When entering the STARTED state
    // the animation is started. This may or may not require deferred response from the animator.
    // If so, we stay in this state until that response is received (and it returns the start time).
    // Otherwise, we use the current time as the start time and go immediately to AnimationStateLooping
    // or AnimationStateEnding.
    enum AnimState { 
        AnimationStateNew,                  // animation just created, animation not running yet
        AnimationStateStartWaitTimer,       // start timer running, waiting for fire
        AnimationStateStartWaitStyleAvailable,   // waiting for style setup so we can start animations
        AnimationStateStartWaitResponse,    // animation started, waiting for response
        AnimationStateLooping,              // response received, animation running, loop timer running, waiting for fire
        AnimationStateEnding,               // received, animation running, end timer running, waiting for fire
        AnimationStatePausedWaitTimer,      // in pause mode when animation started
        AnimationStatePausedWaitResponse,   // animation paused when in STARTING state
        AnimationStatePausedRun,            // animation paused when in LOOPING or ENDING state
        AnimationStateDone,                 // end timer fired, animation finished and removed
        AnimationStateFillingForwards       // animation has ended and is retaining its final value
    };

    enum AnimStateInput {
        AnimationStateInputMakeNew,           // reset back to new from any state
        AnimationStateInputStartAnimation,    // animation requests a start
        AnimationStateInputRestartAnimation,  // force a restart from any state
        AnimationStateInputStartTimerFired,   // start timer fired
        AnimationStateInputStyleAvailable,    // style is setup, ready to start animating
        AnimationStateInputStartTimeSet,      // m_startTime was set
        AnimationStateInputLoopTimerFired,    // loop timer fired
        AnimationStateInputEndTimerFired,     // end timer fired
        AnimationStateInputPauseOverride,     // pause an animation due to override
        AnimationStateInputResumeOverride,    // resume an overridden animation
        AnimationStateInputPlayStateRunning,  // play state paused -> running
        AnimationStateInputPlayStatePaused,   // play state running -> paused
        AnimationStateInputEndAnimation       // force an end from any state
    };

    // Called when animation is in AnimationStateNew to start animation
    void updateStateMachine(AnimStateInput, double param);

    // Animation has actually started, at passed time
    void onAnimationStartResponse(double startTime)
    {
        updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, startTime);
    }

    // Called to change to or from paused state
    void updatePlayState(bool running);
    bool playStatePlaying() const;

    bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer; }
    bool preActive() const
    {
        return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStateStartWaitStyleAvailable || m_animState == AnimationStateStartWaitResponse;
    }

    bool postActive() const { return m_animState == AnimationStateDone; }
    bool active() const { return !postActive() && !preActive(); }
    bool running() const { return !isNew() && !postActive(); }
    bool paused() const { return m_pauseTime >= 0; }
    bool isNew() const { return m_animState == AnimationStateNew; }
    bool waitingForStartTime() const { return m_animState == AnimationStateStartWaitResponse; }
    bool waitingForStyleAvailable() const { return m_animState == AnimationStateStartWaitStyleAvailable; }

    // "animating" means that something is running that requires a timer to keep firing
    // (e.g. a software animation)
    void setAnimating(bool inAnimating = true) { m_isAnimating = inAnimating; }
    virtual double timeToNextService();

    double progress(double scale, double offset, const TimingFunction*) const;

    virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
    virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0;

    virtual bool shouldFireEvents() const { return false; }

    void fireAnimationEventsIfNeeded();

    bool animationsMatch(const Animation*) const;

    void setAnimation(const Animation* anim) { m_animation = const_cast<Animation*>(anim); }

    // Return true if this animation is overridden. This will only be the case for
    // ImplicitAnimations and is used to determine whether or not we should force
    // set the start time. If an animation is overridden, it will probably not get
    // back the AnimationStateInputStartTimeSet input.
    virtual bool overridden() const { return false; }

    // Does this animation/transition involve the given property?
    virtual bool affectsProperty(int /*property*/) const { return false; }
    bool isAnimatingProperty(int property, bool isRunningNow) const
    {
        if (m_fallbackAnimating)
            return false;
            
        if (isRunningNow)
            return (!waitingToStart() && !postActive()) && affectsProperty(property);

        return !postActive() && affectsProperty(property);
    }

    bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
    
    // Freeze the animation; used by DumpRenderTree.
    void freezeAtTime(double t);
    
    double beginAnimationUpdateTime() const;
    
    double getElapsedTime() const;
    
    AnimationBase* next() const { return m_next; }
    void setNext(AnimationBase* animation) { m_next = animation; }
    
    void styleAvailable() 
    {
        ASSERT(waitingForStyleAvailable());
        updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1);
    }

#if USE(ACCELERATED_COMPOSITING)
    static bool animationOfPropertyIsAccelerated(int prop);
#endif

protected:
    virtual void overrideAnimations() { }
    virtual void resumeOverriddenAnimations() { }

    CompositeAnimation* compositeAnimation() { return m_compAnim; }

    // These are called when the corresponding timer fires so subclasses can do any extra work
    virtual void onAnimationStart(double /*elapsedTime*/) { }
    virtual void onAnimationIteration(double /*elapsedTime*/) { }
    virtual void onAnimationEnd(double /*elapsedTime*/) { }
    
    // timeOffset is an offset from the current time when the animation should start. Negative values are OK.
    // Return value indicates whether to expect an asynchronous notifyAnimationStarted() callback.
    virtual bool startAnimation(double /*timeOffset*/) { return false; }
    // timeOffset is the time at which the animation is being paused.
    virtual void pauseAnimation(double /*timeOffset*/) { }
    virtual void endAnimation() { }

    void goIntoEndingOrLoopingState();

    bool isFallbackAnimating() const { return m_fallbackAnimating; }

    static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b);
    static int getPropertyAtIndex(int, bool& isShorthand);
    static int getNumProperties();

    // Return true if we need to start software animation timers
    static bool blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress);

    static void setNeedsStyleRecalc(Node*);
    
    void getTimeToNextEvent(double& time, bool& isLooping) const;

    AnimState m_animState;

    bool m_isAnimating;       // transition/animation requires continual timer firing
    double m_startTime;
    double m_pauseTime;
    double m_requestedStartTime;
    RenderObject* m_object;

    RefPtr<Animation> m_animation;
    CompositeAnimation* m_compAnim;
    bool m_fallbackAnimating;       // true when animating an accelerated property but have to fall back to software
    bool m_transformFunctionListValid;
    double m_totalDuration, m_nextIterationDuration;
    
    AnimationBase* m_next;
};

} // namespace WebCore

#endif // AnimationBase_h