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