1 /*
2  * Copyright (C) 2007 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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef AnimationBase_h
30 #define AnimationBase_h
31 
32 #include "RenderStyleConstants.h"
33 #include <wtf/HashMap.h>
34 #include <wtf/HashSet.h>
35 #include <wtf/text/AtomicString.h>
36 
37 namespace WebCore {
38 
39 class Animation;
40 class AnimationBase;
41 class AnimationController;
42 class CompositeAnimation;
43 class Element;
44 class Node;
45 class RenderObject;
46 class RenderStyle;
47 class TimingFunction;
48 
49 class AnimationBase : public RefCounted<AnimationBase> {
50     friend class CompositeAnimation;
51 
52 public:
53     AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim);
~AnimationBase()54     virtual ~AnimationBase() { }
55 
renderer()56     RenderObject* renderer() const { return m_object; }
clear()57     void clear()
58     {
59       endAnimation();
60       m_object = 0;
61       m_compAnim = 0;
62     }
63 
64     double duration() const;
65 
66     // Animations and Transitions go through the states below. When entering the STARTED state
67     // the animation is started. This may or may not require deferred response from the animator.
68     // If so, we stay in this state until that response is received (and it returns the start time).
69     // Otherwise, we use the current time as the start time and go immediately to AnimationStateLooping
70     // or AnimationStateEnding.
71     enum AnimState {
72         AnimationStateNew,                  // animation just created, animation not running yet
73         AnimationStateStartWaitTimer,       // start timer running, waiting for fire
74         AnimationStateStartWaitStyleAvailable,   // waiting for style setup so we can start animations
75         AnimationStateStartWaitResponse,    // animation started, waiting for response
76         AnimationStateLooping,              // response received, animation running, loop timer running, waiting for fire
77         AnimationStateEnding,               // received, animation running, end timer running, waiting for fire
78         AnimationStatePausedWaitTimer,      // in pause mode when animation started
79         AnimationStatePausedWaitStyleAvailable, // in pause mode when waiting for style setup
80         AnimationStatePausedWaitResponse,   // animation paused when in STARTING state
81         AnimationStatePausedRun,            // animation paused when in LOOPING or ENDING state
82         AnimationStateDone,                 // end timer fired, animation finished and removed
83         AnimationStateFillingForwards       // animation has ended and is retaining its final value
84     };
85 
86     enum AnimStateInput {
87         AnimationStateInputMakeNew,           // reset back to new from any state
88         AnimationStateInputStartAnimation,    // animation requests a start
89         AnimationStateInputRestartAnimation,  // force a restart from any state
90         AnimationStateInputStartTimerFired,   // start timer fired
91         AnimationStateInputStyleAvailable,    // style is setup, ready to start animating
92         AnimationStateInputStartTimeSet,      // m_startTime was set
93         AnimationStateInputLoopTimerFired,    // loop timer fired
94         AnimationStateInputEndTimerFired,     // end timer fired
95         AnimationStateInputPauseOverride,     // pause an animation due to override
96         AnimationStateInputResumeOverride,    // resume an overridden animation
97         AnimationStateInputPlayStateRunning,  // play state paused -> running
98         AnimationStateInputPlayStatePaused,   // play state running -> paused
99         AnimationStateInputEndAnimation       // force an end from any state
100     };
101 
102     // Called when animation is in AnimationStateNew to start animation
103     void updateStateMachine(AnimStateInput, double param);
104 
105     // Animation has actually started, at passed time
onAnimationStartResponse(double startTime)106     void onAnimationStartResponse(double startTime)
107     {
108         updateStateMachine(AnimationBase::AnimationStateInputStartTimeSet, startTime);
109     }
110 
111     // Called to change to or from paused state
112     void updatePlayState(EAnimPlayState);
113     bool playStatePlaying() const;
114 
waitingToStart()115     bool waitingToStart() const { return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer; }
preActive()116     bool preActive() const
117     {
118         return m_animState == AnimationStateNew || m_animState == AnimationStateStartWaitTimer || m_animState == AnimationStateStartWaitStyleAvailable || m_animState == AnimationStateStartWaitResponse;
119     }
120 
postActive()121     bool postActive() const { return m_animState == AnimationStateDone; }
active()122     bool active() const { return !postActive() && !preActive(); }
running()123     bool running() const { return !isNew() && !postActive(); }
paused()124     bool paused() const { return m_pauseTime >= 0; }
isNew()125     bool isNew() const { return m_animState == AnimationStateNew; }
waitingForStartTime()126     bool waitingForStartTime() const { return m_animState == AnimationStateStartWaitResponse; }
waitingForStyleAvailable()127     bool waitingForStyleAvailable() const { return m_animState == AnimationStateStartWaitStyleAvailable; }
128 
129     // "animating" means that something is running that requires a timer to keep firing
130     // (e.g. a software animation)
131     void setAnimating(bool inAnimating = true) { m_isAnimating = inAnimating; }
132     virtual double timeToNextService();
133 
134     double progress(double scale, double offset, const TimingFunction*) const;
135 
136     virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
137     virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
138 
shouldFireEvents()139     virtual bool shouldFireEvents() const { return false; }
140 
141     void fireAnimationEventsIfNeeded();
142 
143     bool animationsMatch(const Animation*) const;
144 
setAnimation(const Animation * anim)145     void setAnimation(const Animation* anim) { m_animation = const_cast<Animation*>(anim); }
146 
147     // Return true if this animation is overridden. This will only be the case for
148     // ImplicitAnimations and is used to determine whether or not we should force
149     // set the start time. If an animation is overridden, it will probably not get
150     // back the AnimationStateInputStartTimeSet input.
overridden()151     virtual bool overridden() const { return false; }
152 
153     // Does this animation/transition involve the given property?
affectsProperty(int)154     virtual bool affectsProperty(int /*property*/) const { return false; }
155 
isAnimatingProperty(int property,bool acceleratedOnly,bool isRunningNow)156     bool isAnimatingProperty(int property, bool acceleratedOnly, bool isRunningNow) const
157     {
158         if (acceleratedOnly && !m_isAccelerated)
159             return false;
160 
161         if (isRunningNow)
162             return (!waitingToStart() && !postActive()) && affectsProperty(property);
163 
164         return !postActive() && affectsProperty(property);
165     }
166 
isTransformFunctionListValid()167     bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
168 
169     // Freeze the animation; used by DumpRenderTree.
170     void freezeAtTime(double t);
171 
172     // Play and pause API
173     void play();
174     void pause();
175 
176     double beginAnimationUpdateTime() const;
177 
178     double getElapsedTime() const;
179     // Setting the elapsed time will adjust the start time and possibly pause time.
180     void setElapsedTime(double);
181 
styleAvailable()182     void styleAvailable()
183     {
184         ASSERT(waitingForStyleAvailable());
185         updateStateMachine(AnimationBase::AnimationStateInputStyleAvailable, -1);
186     }
187 
188 #if USE(ACCELERATED_COMPOSITING)
189     static bool animationOfPropertyIsAccelerated(int prop);
190 #endif
191 
192     static HashSet<int> animatableShorthandsAffectingProperty(int property);
193 
animation()194     const Animation* animation() const { return m_animation.get(); }
195 
196 protected:
overrideAnimations()197     virtual void overrideAnimations() { }
resumeOverriddenAnimations()198     virtual void resumeOverriddenAnimations() { }
199 
compositeAnimation()200     CompositeAnimation* compositeAnimation() { return m_compAnim; }
201 
202     // These are called when the corresponding timer fires so subclasses can do any extra work
onAnimationStart(double)203     virtual void onAnimationStart(double /*elapsedTime*/) { }
onAnimationIteration(double)204     virtual void onAnimationIteration(double /*elapsedTime*/) { }
onAnimationEnd(double)205     virtual void onAnimationEnd(double /*elapsedTime*/) { }
206 
207     // timeOffset is an offset from the current time when the animation should start. Negative values are OK.
208     // Return value indicates whether to expect an asynchronous notifyAnimationStarted() callback.
startAnimation(double)209     virtual bool startAnimation(double /*timeOffset*/) { return false; }
210     // timeOffset is the time at which the animation is being paused.
pauseAnimation(double)211     virtual void pauseAnimation(double /*timeOffset*/) { }
endAnimation()212     virtual void endAnimation() { }
213 
214     void goIntoEndingOrLoopingState();
215 
isAccelerated()216     bool isAccelerated() const { return m_isAccelerated; }
217 
218     static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b);
219     static int getPropertyAtIndex(int, bool& isShorthand);
220     static int getNumProperties();
221 
222     // Return true if we need to start software animation timers
223     static bool blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress);
224 
225     static void setNeedsStyleRecalc(Node*);
226 
227     void getTimeToNextEvent(double& time, bool& isLooping) const;
228 
229     AnimState m_animState;
230 
231     bool m_isAnimating;       // transition/animation requires continual timer firing
232     double m_startTime;
233     double m_pauseTime;
234     double m_requestedStartTime;
235     RenderObject* m_object;
236 
237     RefPtr<Animation> m_animation;
238     CompositeAnimation* m_compAnim;
239     bool m_isAccelerated;
240     bool m_transformFunctionListValid;
241     double m_totalDuration, m_nextIterationDuration;
242 
243 private:
244     static void ensurePropertyMap();
245 };
246 
247 } // namespace WebCore
248 
249 #endif // AnimationBase_h
250