Eliminate styleDidChange with StyleDifferenceEqual when updates are actually necessary
[WebKit-https.git] / Source / WebCore / page / animation / AnimationBase.h
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 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 "Animation.h"
33 #include "CSSPropertyNames.h"
34 #include "RenderStyleConstants.h"
35 #include <wtf/HashMap.h>
36 #include <wtf/HashSet.h>
37 #include <wtf/RefCounted.h>
38 #include <wtf/text/AtomicString.h>
39
40 namespace WebCore {
41
42 class CompositeAnimation;
43 class Element;
44 class FloatRect;
45 class LayoutRect;
46 class RenderElement;
47 class RenderStyle;
48 class TimingFunction;
49
50 class AnimationBase : public RefCounted<AnimationBase> {
51     friend class CompositeAnimation;
52     friend class CSSPropertyAnimation;
53     WTF_MAKE_FAST_ALLOCATED;
54 public:
55     AnimationBase(Animation& transition, RenderElement*, CompositeAnimation*);
56     virtual ~AnimationBase() { }
57
58     RenderElement* renderer() const { return m_object; }
59     void clear()
60     {
61         endAnimation();
62         m_object = nullptr;
63         m_compositeAnimation = nullptr;
64     }
65
66     double duration() const;
67
68     // Animations and Transitions go through the states below. When entering the STARTED state
69     // the animation is started. This may or may not require deferred response from the animator.
70     // If so, we stay in this state until that response is received (and it returns the start time).
71     // Otherwise, we use the current time as the start time and go immediately to AnimationState::Looping
72     // or AnimationState::Ending.
73     enum class AnimationState {
74         New,                        // animation just created, animation not running yet
75         StartWaitTimer,             // start timer running, waiting for fire
76         StartWaitStyleAvailable,    // waiting for style setup so we can start animations
77         StartWaitResponse,          // animation started, waiting for response
78         Looping,                    // response received, animation running, loop timer running, waiting for fire
79         Ending,                     // received, animation running, end timer running, waiting for fire
80         PausedNew,                  // in pause mode when animation was created
81         PausedWaitTimer,            // in pause mode when animation started
82         PausedWaitStyleAvailable,   // in pause mode when waiting for style setup
83         PausedWaitResponse,         // animation paused when in STARTING state
84         PausedRun,                  // animation paused when in LOOPING or ENDING state
85         Done,                       // end timer fired, animation finished and removed
86         FillingForwards             // animation has ended and is retaining its final value
87     };
88
89     enum class AnimationStateInput {
90         MakeNew,           // reset back to new from any state
91         StartAnimation,    // animation requests a start
92         RestartAnimation,  // force a restart from any state
93         StartTimerFired,   // start timer fired
94         StyleAvailable,    // style is setup, ready to start animating
95         StartTimeSet,      // m_startTime was set
96         LoopTimerFired,    // loop timer fired
97         EndTimerFired,     // end timer fired
98         PauseOverride,     // pause an animation due to override
99         ResumeOverride,    // resume an overridden animation
100         PlayStateRunning,  // play state paused -> running
101         PlayStatePaused,   // play state running -> paused
102         EndAnimation       // force an end from any state
103     };
104
105     // Called when animation is in AnimationState::New to start animation
106     void updateStateMachine(AnimationStateInput, double param);
107
108     // Animation has actually started, at passed time
109     void onAnimationStartResponse(double startTime)
110     {
111         updateStateMachine(AnimationStateInput::StartTimeSet, startTime);
112     }
113
114     // Called to change to or from paused state
115     void updatePlayState(EAnimPlayState);
116     bool playStatePlaying() const;
117
118     bool waitingToStart() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::PausedNew; }
119     bool preActive() const
120     {
121         return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::StartWaitStyleAvailable || m_animationState == AnimationState::StartWaitResponse;
122     }
123
124     bool postActive() const { return m_animationState == AnimationState::Done; }
125     bool fillingForwards() const { return m_animationState == AnimationState::FillingForwards; }
126     bool active() const { return !postActive() && !preActive(); }
127     bool running() const { return !isNew() && !postActive(); }
128     bool paused() const { return m_pauseTime >= 0 || m_animationState == AnimationState::PausedNew; }
129     bool inPausedState() const { return m_animationState >= AnimationState::PausedNew && m_animationState <= AnimationState::PausedRun; }
130     bool isNew() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::PausedNew; }
131     bool waitingForStartTime() const { return m_animationState == AnimationState::StartWaitResponse; }
132     bool waitingForStyleAvailable() const { return m_animationState == AnimationState::StartWaitStyleAvailable; }
133
134     virtual double timeToNextService();
135
136     double progress(double scale, double offset, const TimingFunction*) const;
137
138     // Returns true if the animation state changed.
139     virtual bool animate(CompositeAnimation*, RenderElement*, const RenderStyle* /*currentStyle*/, RenderStyle* /*targetStyle*/, RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
140     virtual void getAnimatedStyle(RefPtr<RenderStyle>& /*animatedStyle*/) = 0;
141
142     virtual bool computeExtentOfTransformAnimation(LayoutRect&) const = 0;
143
144     virtual bool shouldFireEvents() const { return false; }
145
146     void fireAnimationEventsIfNeeded();
147
148     bool animationsMatch(const Animation&) const;
149
150     const Animation& animation() const { return m_animation; }
151     void setAnimation(Animation& animation) { m_animation = animation; }
152
153     // Return true if this animation is overridden. This will only be the case for
154     // ImplicitAnimations and is used to determine whether or not we should force
155     // set the start time. If an animation is overridden, it will probably not get
156     // back the AnimationStateInput::StartTimeSet input.
157     virtual bool overridden() const { return false; }
158
159     // Does this animation/transition involve the given property?
160     virtual bool affectsProperty(CSSPropertyID /*property*/) const { return false; }
161
162     enum RunningStates {
163         Delaying = 1 << 0,
164         Paused = 1 << 1,
165         Running = 1 << 2,
166         FillingFowards = 1 << 3
167     };
168     typedef unsigned RunningState;
169     bool isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, RunningState runningState) const
170     {
171         if (acceleratedOnly && !m_isAccelerated)
172             return false;
173
174         if (!affectsProperty(property))
175             return false;
176
177         if ((runningState & Delaying) && preActive())
178             return true;
179
180         if ((runningState & Paused) && inPausedState())
181             return true;
182
183         if ((runningState & Running) && !inPausedState() && (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState <= AnimationState::Done))
184             return true;
185
186         if ((runningState & FillingFowards) && m_animationState == AnimationState::FillingForwards)
187             return true;
188
189         return false;
190     }
191
192     // FIXME: rename this using the "lists match" terminology.
193     bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
194     bool filterFunctionListsMatch() const { return m_filterFunctionListsMatch; }
195
196     // Freeze the animation; used by DumpRenderTree.
197     void freezeAtTime(double t);
198
199     // Play and pause API
200     void play();
201     void pause();
202     
203     double beginAnimationUpdateTime() const;
204     
205     double getElapsedTime() const;
206     // Setting the elapsed time will adjust the start time and possibly pause time.
207     void setElapsedTime(double);
208     
209     void styleAvailable() 
210     {
211         ASSERT(waitingForStyleAvailable());
212         updateStateMachine(AnimationStateInput::StyleAvailable, -1);
213     }
214
215 protected:
216     virtual void overrideAnimations() { }
217     virtual void resumeOverriddenAnimations() { }
218
219     CompositeAnimation* compositeAnimation() { return m_compositeAnimation; }
220
221     // These are called when the corresponding timer fires so subclasses can do any extra work
222     virtual void onAnimationStart(double /*elapsedTime*/) { }
223     virtual void onAnimationIteration(double /*elapsedTime*/) { }
224     virtual void onAnimationEnd(double /*elapsedTime*/) { }
225     
226     // timeOffset is an offset from the current time when the animation should start. Negative values are OK.
227     // Return value indicates whether to expect an asynchronous notifyAnimationStarted() callback.
228     virtual bool startAnimation(double /*timeOffset*/) { return false; }
229     // timeOffset is the time at which the animation is being paused.
230     virtual void pauseAnimation(double /*timeOffset*/) { }
231     virtual void endAnimation() { }
232
233     void goIntoEndingOrLoopingState();
234
235     bool isAccelerated() const { return m_isAccelerated; }
236     AnimationState state() const { return m_animationState; }
237
238     static void setNeedsStyleRecalc(Element*);
239     
240     void getTimeToNextEvent(double& time, bool& isLooping) const;
241
242     double fractionalTime(double scale, double elapsedTime, double offset) const;
243
244     // These return true if we can easily compute a bounding box by applying the style's transform to the bounds rect.
245     bool computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;
246     bool computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;
247
248     RenderElement* m_object;
249     CompositeAnimation* m_compositeAnimation; // Ideally this would be a reference, but it has to be cleared if an animation is destroyed inside an event callback.
250     Ref<Animation> m_animation;
251
252     double m_startTime { 0 };
253     double m_pauseTime { -1 };
254     double m_requestedStartTime { 0 };
255     double m_totalDuration { -1 };
256     double m_nextIterationDuration { -1 };
257
258     AnimationState m_animationState { AnimationState::New };
259     bool m_isAccelerated { false };
260     bool m_transformFunctionListValid { false };
261     bool m_filterFunctionListsMatch { false };
262 };
263
264 } // namespace WebCore
265
266 #endif // AnimationBase_h