#ifndef CSSAnimations_h
#define CSSAnimations_h
#include "core/animation/Animation.h"
#include "core/animation/AnimationPlayer.h"
#include "core/animation/InertAnimation.h"
#include "core/animation/Interpolation.h"
#include "core/animation/css/CSSAnimationData.h"
#include "core/css/StylePropertySet.h"
#include "core/dom/Document.h"
#include "core/rendering/style/RenderStyleConstants.h"
#include "wtf/HashMap.h"
#include "wtf/Vector.h"
#include "wtf/text/AtomicString.h"
namespace WebCore {
class Element;
class StylePropertyShorthand;
class StyleResolver;
class StyleRuleKeyframes;
class CSSAnimationUpdate FINAL : public NoBaseWillBeGarbageCollectedFinalized<CSSAnimationUpdate> {
public:
void startAnimation(AtomicString& animationName, PassRefPtr<InertAnimation> animation)
{
NewAnimation newAnimation;
newAnimation.name = animationName;
newAnimation.animation = animation;
m_newAnimations.append(newAnimation);
}
bool isCancelledAnimation(const AnimationPlayer* player) const { return m_cancelledAnimationPlayers.contains(player); }
void cancelAnimation(const AtomicString& name, AnimationPlayer& player)
{
m_cancelledAnimationNames.append(name);
m_cancelledAnimationPlayers.add(&player);
}
void toggleAnimationPaused(const AtomicString& name)
{
m_animationsWithPauseToggled.append(name);
}
void startTransition(CSSPropertyID id, CSSPropertyID eventId, const AnimatableValue* from, const AnimatableValue* to, PassRefPtr<InertAnimation> animation)
{
NewTransition newTransition;
newTransition.id = id;
newTransition.eventId = eventId;
newTransition.from = from;
newTransition.to = to;
newTransition.animation = animation;
m_newTransitions.set(id, newTransition);
}
bool isCancelledTransition(CSSPropertyID id) const { return m_cancelledTransitions.contains(id); }
void cancelTransition(CSSPropertyID id) { m_cancelledTransitions.add(id); }
struct NewAnimation {
AtomicString name;
RefPtr<InertAnimation> animation;
};
const Vector<NewAnimation>& newAnimations() const { return m_newAnimations; }
const Vector<AtomicString>& cancelledAnimationNames() const { return m_cancelledAnimationNames; }
const HashSet<const AnimationPlayer*>& cancelledAnimationAnimationPlayers() const { return m_cancelledAnimationPlayers; }
const Vector<AtomicString>& animationsWithPauseToggled() const { return m_animationsWithPauseToggled; }
struct NewTransition {
ALLOW_ONLY_INLINE_ALLOCATION();
public:
void trace(Visitor* visitor)
{
visitor->trace(from);
visitor->trace(to);
}
CSSPropertyID id;
CSSPropertyID eventId;
RawPtrWillBeMember<const AnimatableValue> from;
RawPtrWillBeMember<const AnimatableValue> to;
RefPtr<InertAnimation> animation;
};
typedef WillBeHeapHashMap<CSSPropertyID, NewTransition> NewTransitionMap;
const NewTransitionMap& newTransitions() const { return m_newTransitions; }
const HashSet<CSSPropertyID>& cancelledTransitions() const { return m_cancelledTransitions; }
void adoptActiveInterpolationsForAnimations(WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& newMap) { newMap.swap(m_activeInterpolationsForAnimations); }
void adoptActiveInterpolationsForTransitions(WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& newMap) { newMap.swap(m_activeInterpolationsForTransitions); }
const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations() const { return m_activeInterpolationsForAnimations; }
const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions() const { return m_activeInterpolationsForTransitions; }
WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations() { return m_activeInterpolationsForAnimations; }
bool isEmpty() const
{
return m_newAnimations.isEmpty()
&& m_cancelledAnimationNames.isEmpty()
&& m_cancelledAnimationPlayers.isEmpty()
&& m_animationsWithPauseToggled.isEmpty()
&& m_newTransitions.isEmpty()
&& m_cancelledTransitions.isEmpty()
&& m_activeInterpolationsForAnimations.isEmpty()
&& m_activeInterpolationsForTransitions.isEmpty();
}
void trace(Visitor*);
private:
Vector<NewAnimation> m_newAnimations;
Vector<AtomicString> m_cancelledAnimationNames;
HashSet<const AnimationPlayer*> m_cancelledAnimationPlayers;
Vector<AtomicString> m_animationsWithPauseToggled;
NewTransitionMap m_newTransitions;
HashSet<CSSPropertyID> m_cancelledTransitions;
WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_activeInterpolationsForAnimations;
WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_activeInterpolationsForTransitions;
};
class CSSAnimations FINAL : public NoBaseWillBeGarbageCollectedFinalized<CSSAnimations> {
public:
static const StyleRuleKeyframes* matchScopedKeyframesRule(StyleResolver*, const Element*, const StringImpl*);
static bool isAnimatableProperty(CSSPropertyID);
static const StylePropertyShorthand& animatableProperties();
static PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
void setPendingUpdate(PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> update) { m_pendingUpdate = update; }
void maybeApplyPendingUpdate(Element*);
bool isEmpty() const { return m_animations.isEmpty() && m_transitions.isEmpty() && !m_pendingUpdate; }
void cancel();
void trace(Visitor*);
private:
struct RunningTransition {
ALLOW_ONLY_INLINE_ALLOCATION();
public:
void trace(Visitor* visitor)
{
visitor->trace(from);
visitor->trace(to);
}
Animation* transition;
RawPtrWillBeMember<const AnimatableValue> from;
RawPtrWillBeMember<const AnimatableValue> to;
};
typedef HashMap<AtomicString, RefPtr<AnimationPlayer> > AnimationMap;
AnimationMap m_animations;
typedef WillBeHeapHashMap<CSSPropertyID, RunningTransition> TransitionMap;
TransitionMap m_transitions;
OwnPtrWillBeMember<CSSAnimationUpdate> m_pendingUpdate;
WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> > m_previousActiveInterpolationsForAnimations;
static void calculateAnimationUpdate(CSSAnimationUpdate*, Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle, StyleResolver*);
static void calculateTransitionUpdate(CSSAnimationUpdate*, const Element*, const RenderStyle&);
static void calculateTransitionUpdateForProperty(CSSPropertyID, const CSSAnimationData*, const RenderStyle& oldStyle, const RenderStyle&, const TransitionMap* activeTransitions, CSSAnimationUpdate*, const Element*);
static void calculateAnimationActiveInterpolations(CSSAnimationUpdate*, const Element*, double timelineCurrentTime);
static void calculateTransitionActiveInterpolations(CSSAnimationUpdate*, const Element*, double timelineCurrentTime);
class AnimationEventDelegate FINAL : public TimedItem::EventDelegate {
public:
AnimationEventDelegate(Element* target, const AtomicString& name)
: m_target(target)
, m_name(name)
{
}
virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
private:
void maybeDispatch(Document::ListenerType, const AtomicString& eventName, double elapsedTime);
Element* m_target;
const AtomicString m_name;
};
class TransitionEventDelegate FINAL : public TimedItem::EventDelegate {
public:
TransitionEventDelegate(Element* target, CSSPropertyID property)
: m_target(target)
, m_property(property)
{
}
virtual void onEventCondition(const TimedItem*, bool isFirstSample, TimedItem::Phase previousPhase, double previousIteration) OVERRIDE;
private:
Element* m_target;
const CSSPropertyID m_property;
};
};
}
#endif