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