#pragma once
#include "Animation.h"
#include "CSSPropertyBlendingClient.h"
#include "CSSPropertyNames.h"
#include "RenderStyleConstants.h"
namespace WebCore {
class CompositeAnimation;
class Element;
class FloatRect;
class LayoutRect;
class RenderBoxModelObject;
class RenderElement;
class RenderStyle;
class TimingFunction;
class AnimationBase : public RefCounted<AnimationBase>
, public CSSPropertyBlendingClient {
friend class CompositeAnimation;
friend class CSSPropertyAnimation;
WTF_MAKE_FAST_ALLOCATED;
public:
AnimationBase(const Animation& transition, Element&, CompositeAnimation&);
virtual ~AnimationBase();
Element* element() const { return m_element.get(); }
const RenderStyle& currentStyle() const override;
RenderElement* renderer() const override;
RenderBoxModelObject* compositedRenderer() const;
void clear();
double duration() const;
enum class AnimationState : uint8_t {
New, StartWaitTimer, StartWaitStyleAvailable, StartWaitResponse, Looping, Ending, PausedNew, PausedWaitTimer, PausedWaitStyleAvailable, PausedWaitResponse, PausedRun, Done, FillingForwards };
enum class AnimationStateInput : uint8_t {
MakeNew, StartAnimation, RestartAnimation, StartTimerFired, StyleAvailable, StartTimeSet, LoopTimerFired, EndTimerFired, PauseOverride, ResumeOverride, PlayStateRunning, PlayStatePaused, EndAnimation };
void updateStateMachine(AnimationStateInput, double param);
void onAnimationStartResponse(MonotonicTime startTime)
{
updateStateMachine(AnimationStateInput::StartTimeSet, startTime.secondsSinceEpoch().seconds());
}
void updatePlayState(AnimationPlayState);
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 || 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 override { return m_isAccelerated; }
virtual Optional<Seconds> timeToNextService();
double progress(double scale = 1, double offset = 0, const TimingFunction* = nullptr) const;
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 override { return m_transformFunctionListsMatch; }
bool filterFunctionListsMatch() const override { return m_filterFunctionListsMatch; }
#if ENABLE(FILTERS_LEVEL_2)
bool backdropFilterFunctionListsMatch() const override { return m_backdropFilterFunctionListsMatch; }
#endif
bool colorFilterFunctionListsMatch() const override { return m_colorFilterFunctionListsMatch; }
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(bool = false) { }
virtual const RenderStyle& unanimatedStyle() const = 0;
void goIntoEndingOrLoopingState();
AnimationState state() const { return m_animationState; }
static void setNeedsStyleRecalc(Element*);
void getTimeToNextEvent(Seconds& 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;
protected:
bool m_isAccelerated { false };
bool m_transformFunctionListsMatch { false };
bool m_filterFunctionListsMatch { false };
#if ENABLE(FILTERS_LEVEL_2)
bool m_backdropFilterFunctionListsMatch { false };
#endif
private:
RefPtr<Element> m_element;
protected:
CompositeAnimation* m_compositeAnimation; Ref<Animation> m_animation;
Optional<double> m_startTime;
Optional<double> m_pauseTime;
double m_requestedStartTime { 0 };
Optional<double> m_totalDuration;
Optional<double> m_nextIterationDuration;
AnimationState m_animationState { AnimationState::New };
bool m_colorFilterFunctionListsMatch { false };
};
}