#ifndef TimedItem_h
#define TimedItem_h
#include "core/animation/Timing.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/RefCounted.h"
namespace WebCore {
class AnimationPlayer;
class TimedItem;
class TimedItemTiming;
static inline bool isNull(double value)
{
return std::isnan(value);
}
static inline double nullValue()
{
return std::numeric_limits<double>::quiet_NaN();
}
class TimedItem : public RefCounted<TimedItem> {
friend class AnimationPlayer;
public:
enum Phase {
PhaseBefore,
PhaseActive,
PhaseAfter,
PhaseNone,
};
class EventDelegate {
public:
virtual ~EventDelegate() { };
virtual void onEventCondition(const TimedItem*, bool isFirstSample, Phase previousPhase, double previousIteration) = 0;
};
virtual ~TimedItem() { }
virtual bool isAnimation() const { return false; }
Phase phase() const { return ensureCalculated().phase; }
bool isCurrent() const { return ensureCalculated().isCurrent; }
bool isInEffect() const { return ensureCalculated().isInEffect; }
bool isInPlay() const { return ensureCalculated().isInPlay; }
double timeToForwardsEffectChange() const { return ensureCalculated().timeToForwardsEffectChange; }
double timeToReverseEffectChange() const { return ensureCalculated().timeToReverseEffectChange; }
double currentIteration() const { return ensureCalculated().currentIteration; }
double duration() const { return iterationDuration(); }
double activeDuration() const;
double timeFraction() const { return ensureCalculated().timeFraction; }
double startTime() const { return m_startTime; }
double endTime() const { return startTime() + specifiedTiming().startDelay + activeDuration() + specifiedTiming().endDelay; }
const AnimationPlayer* player() const { return m_player; }
AnimationPlayer* player() { return m_player; }
AnimationPlayer* player(bool& isNull) { isNull = !m_player; return m_player; }
const Timing& specifiedTiming() const { return m_specified; }
PassRefPtr<TimedItemTiming> specified();
void updateSpecifiedTiming(const Timing&);
double localTime(bool& isNull) const { isNull = !m_player; return ensureCalculated().localTime; }
double currentIteration(bool& isNull) const { isNull = !ensureCalculated().isInEffect; return ensureCalculated().currentIteration; }
protected:
TimedItem(const Timing&, PassOwnPtr<EventDelegate> = nullptr);
void updateInheritedTime(double inheritedTime) const;
void invalidate() const { m_needsUpdate = true; };
private:
double iterationDuration() const;
double repeatedDuration() const;
virtual void updateChildrenAndEffects() const = 0;
virtual double intrinsicIterationDuration() const { return 0; };
virtual double calculateTimeToEffectChange(bool forwards, double localTime, double timeToNextIteration) const = 0;
virtual void didAttach() { };
virtual void willDetach() { };
void attach(AnimationPlayer* player)
{
m_player = player;
didAttach();
};
void detach()
{
ASSERT(m_player);
willDetach();
m_player = 0;
};
TimedItem* const m_parent;
const double m_startTime;
AnimationPlayer* m_player;
Timing m_specified;
OwnPtr<EventDelegate> m_eventDelegate;
mutable struct CalculatedTiming {
Phase phase;
double currentIteration;
double timeFraction;
bool isCurrent;
bool isInEffect;
bool isInPlay;
double localTime;
double timeToForwardsEffectChange;
double timeToReverseEffectChange;
} m_calculated;
mutable bool m_isFirstSample;
mutable bool m_needsUpdate;
mutable double m_lastUpdateTime;
const CalculatedTiming& ensureCalculated() const;
};
}
#endif