#ifndef AnimationBase_h
#define AnimationBase_h
#include "Animation.h"
#include "CSSPropertyNames.h"
#include "RenderStyleConstants.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RefCounted.h>
#include <wtf/text/AtomicString.h>
namespace WebCore {
class AnimationController;
class CompositeAnimation;
class Element;
class RenderElement;
class RenderStyle;
class TimingFunction;
class AnimationBase : public RefCounted<AnimationBase> {
friend class CompositeAnimation;
friend class CSSPropertyAnimation;
public:
AnimationBase(const Animation& transition, RenderElement*, CompositeAnimation*);
virtual ~AnimationBase() { }
RenderElement* renderer() const { return m_object; }
void clear()
{
endAnimation();
m_object = nullptr;
m_compositeAnimation = nullptr;
}
double duration() const;
enum class AnimationState {
New, StartWaitTimer, StartWaitStyleAvailable, StartWaitResponse, Looping, Ending, PausedNew, PausedWaitTimer, PausedWaitStyleAvailable, PausedWaitResponse, PausedRun, Done, FillingForwards };
enum class AnimationStateInput {
MakeNew, StartAnimation, RestartAnimation, StartTimerFired, StyleAvailable, StartTimeSet, LoopTimerFired, EndTimerFired, PauseOverride, ResumeOverride, PlayStateRunning, PlayStatePaused, EndAnimation };
void updateStateMachine(AnimationStateInput, double param);
void onAnimationStartResponse(double startTime)
{
updateStateMachine(AnimationStateInput::StartTimeSet, startTime);
}
void updatePlayState(EAnimPlayState);
bool playStatePlaying() const;
bool waitingToStart() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::PausedNew; }
bool preActive() const
{
return m_animationState == AnimationState::New || m_animationState == AnimationState::StartWaitTimer || m_animationState == AnimationState::StartWaitStyleAvailable || m_animationState == AnimationState::StartWaitResponse;
}
bool postActive() const { return m_animationState == AnimationState::Done; }
bool fillingForwards() const { return m_animationState == AnimationState::FillingForwards; }
bool active() const { return !postActive() && !preActive(); }
bool running() const { return !isNew() && !postActive(); }
bool paused() const { return m_pauseTime >= 0 || m_animationState == AnimationState::PausedNew; }
bool inPausedState() const { return m_animationState >= AnimationState::PausedNew && m_animationState <= AnimationState::PausedRun; }
bool isNew() const { return m_animationState == AnimationState::New || m_animationState == AnimationState::PausedNew; }
bool waitingForStartTime() const { return m_animationState == AnimationState::StartWaitResponse; }
bool waitingForStyleAvailable() const { return m_animationState == AnimationState::StartWaitStyleAvailable; }
virtual double timeToNextService();
double progress(double scale, double offset, const TimingFunction*) const;
virtual void animate(CompositeAnimation*, RenderElement*, const RenderStyle* , RenderStyle* , RefPtr<RenderStyle>& ) = 0;
virtual void getAnimatedStyle(RefPtr<RenderStyle>& ) = 0;
virtual bool shouldFireEvents() const { return false; }
void fireAnimationEventsIfNeeded();
bool animationsMatch(const Animation*) const;
void setAnimation(const Animation& animation) { m_animation = const_cast<Animation*>(&animation); }
virtual bool overridden() const { return false; }
virtual bool affectsProperty(CSSPropertyID ) const { return false; }
enum RunningStates {
Delaying = 1 << 0,
Paused = 1 << 1,
Running = 1 << 2,
FillingFowards = 1 << 3
};
typedef unsigned RunningState;
bool isAnimatingProperty(CSSPropertyID property, bool acceleratedOnly, RunningState runningState) const
{
if (acceleratedOnly && !m_isAccelerated)
return false;
if (!affectsProperty(property))
return false;
if ((runningState & Delaying) && preActive())
return true;
if ((runningState & Paused) && inPausedState())
return true;
if ((runningState & Running) && !inPausedState() && (m_animationState >= AnimationState::StartWaitStyleAvailable && m_animationState <= AnimationState::Done))
return true;
if ((runningState & FillingFowards) && m_animationState == AnimationState::FillingForwards)
return true;
return false;
}
bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
#if ENABLE(CSS_FILTERS)
bool filterFunctionListsMatch() const { return m_filterFunctionListsMatch; }
#endif
void freezeAtTime(double t);
void play();
void pause();
double beginAnimationUpdateTime() const;
double getElapsedTime() const;
void setElapsedTime(double);
void styleAvailable()
{
ASSERT(waitingForStyleAvailable());
updateStateMachine(AnimationStateInput::StyleAvailable, -1);
}
const Animation& animation() const { return *m_animation; }
protected:
virtual void overrideAnimations() { }
virtual void resumeOverriddenAnimations() { }
CompositeAnimation* compositeAnimation() { return m_compositeAnimation; }
virtual void onAnimationStart(double ) { }
virtual void onAnimationIteration(double ) { }
virtual void onAnimationEnd(double ) { }
virtual bool startAnimation(double ) { return false; }
virtual void pauseAnimation(double ) { }
virtual void endAnimation() { }
void goIntoEndingOrLoopingState();
bool isAccelerated() const { return m_isAccelerated; }
static void setNeedsStyleRecalc(Element*);
void getTimeToNextEvent(double& time, bool& isLooping) const;
double fractionalTime(double scale, double elapsedTime, double offset) const;
AnimationState m_animationState;
bool m_isAccelerated;
bool m_transformFunctionListValid;
#if ENABLE(CSS_FILTERS)
bool m_filterFunctionListsMatch;
#endif
double m_startTime;
double m_pauseTime;
double m_requestedStartTime;
double m_totalDuration;
double m_nextIterationDuration;
RenderElement* m_object;
RefPtr<Animation> m_animation;
CompositeAnimation* m_compositeAnimation;
};
}
#endif // AnimationBase_h