#pragma once
#include "Animation.h"
#include "CSSPropertyNames.h"
#include "RenderStyleConstants.h"
#include <wtf/RefCounted.h>
#include <wtf/text/AtomicString.h>
namespace WebCore {
class CompositeAnimation;
class Element;
class FloatRect;
class LayoutRect;
class RenderElement;
class RenderStyle;
class TimingFunction;
class AnimationBase : public RefCounted<AnimationBase> {
friend class CompositeAnimation;
friend class CSSPropertyAnimation;
WTF_MAKE_FAST_ALLOCATED;
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; }
bool isAccelerated() const { return m_isAccelerated; }
virtual double timeToNextService();
double progress(double scale = 1, double offset = 0, const TimingFunction* = nullptr) const;
virtual bool animate(CompositeAnimation*, RenderElement*, const RenderStyle* , const RenderStyle* , std::unique_ptr<RenderStyle>& , bool& didBlendStyle) = 0;
virtual void getAnimatedStyle(std::unique_ptr<RenderStyle>& ) = 0;
virtual bool computeExtentOfTransformAnimation(LayoutRect&) const = 0;
virtual bool shouldFireEvents() const { return false; }
void fireAnimationEventsIfNeeded();
bool animationsMatch(const Animation&) const;
const Animation& animation() const { return m_animation; }
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,
};
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;
return false;
}
bool transformFunctionListsMatch() const { return m_transformFunctionListsMatch; }
bool filterFunctionListsMatch() const { return m_filterFunctionListsMatch; }
#if ENABLE(FILTERS_LEVEL_2)
bool backdropFilterFunctionListsMatch() const { return m_backdropFilterFunctionListsMatch; }
#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);
}
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();
AnimationState state() const { return m_animationState; }
static void setNeedsStyleRecalc(Element*);
void getTimeToNextEvent(double& time, bool& isLooping) const;
double fractionalTime(double scale, double elapsedTime, double offset) const;
bool computeTransformedExtentViaTransformList(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;
bool computeTransformedExtentViaMatrix(const FloatRect& rendererBox, const RenderStyle&, LayoutRect& bounds) const;
RenderElement* m_object;
CompositeAnimation* m_compositeAnimation; Ref<Animation> m_animation;
double m_startTime { 0 };
double m_pauseTime { -1 };
double m_requestedStartTime { 0 };
double m_totalDuration { -1 };
double m_nextIterationDuration { -1 };
AnimationState m_animationState { AnimationState::New };
bool m_isAccelerated { false };
bool m_transformFunctionListsMatch { false };
bool m_filterFunctionListsMatch { false };
#if ENABLE(FILTERS_LEVEL_2)
bool m_backdropFilterFunctionListsMatch { false };
#endif
};
}