/* | |
* 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 |