/* * Copyright (C) 2013 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SKY_ENGINE_CORE_ANIMATION_CSS_CSSANIMATIONS_H_ #define SKY_ENGINE_CORE_ANIMATION_CSS_CSSANIMATIONS_H_ #include "sky/engine/core/animation/Animation.h" #include "sky/engine/core/animation/AnimationPlayer.h" #include "sky/engine/core/animation/InertAnimation.h" #include "sky/engine/core/animation/Interpolation.h" #include "sky/engine/core/css/StylePropertySet.h" #include "sky/engine/core/dom/Document.h" #include "sky/engine/core/rendering/style/RenderStyleConstants.h" #include "sky/engine/wtf/HashMap.h" #include "sky/engine/wtf/Vector.h" #include "sky/engine/wtf/text/AtomicString.h" namespace blink { class CSSTransitionData; class Element; class StylePropertyShorthand; // This class stores the CSS Animations/Transitions information we use during a style recalc. // This includes updates to animations/transitions as well as the Interpolations to be applied. class CSSAnimationUpdate final { public: void startAnimation(AtomicString& animationName, PassRefPtr animation) { NewAnimation newAnimation; newAnimation.name = animationName; newAnimation.animation = animation; m_newAnimations.append(newAnimation); } // Returns whether player has been cancelled and should be filtered during style application. 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 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 { ALLOW_ONLY_INLINE_ALLOCATION(); public: AtomicString name; RefPtr animation; }; const Vector& newAnimations() const { return m_newAnimations; } const Vector& cancelledAnimationNames() const { return m_cancelledAnimationNames; } const HashSet >& cancelledAnimationAnimationPlayers() const { return m_cancelledAnimationPlayers; } const Vector& animationsWithPauseToggled() const { return m_animationsWithPauseToggled; } struct NewTransition { ALLOW_ONLY_INLINE_ALLOCATION(); public: CSSPropertyID id; CSSPropertyID eventId; RawPtr from; RawPtr to; RefPtr animation; }; typedef HashMap NewTransitionMap; const NewTransitionMap& newTransitions() const { return m_newTransitions; } const HashSet& cancelledTransitions() const { return m_cancelledTransitions; } void adoptActiveInterpolationsForAnimations(HashMap >& newMap) { newMap.swap(m_activeInterpolationsForAnimations); } void adoptActiveInterpolationsForTransitions(HashMap >& newMap) { newMap.swap(m_activeInterpolationsForTransitions); } const HashMap >& activeInterpolationsForAnimations() const { return m_activeInterpolationsForAnimations; } const HashMap >& activeInterpolationsForTransitions() const { return m_activeInterpolationsForTransitions; } HashMap >& 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(); } private: // Order is significant since it defines the order in which new animations // will be started. Note that there may be multiple animations present // with the same name, due to the way in which we split up animations with // incomplete keyframes. Vector m_newAnimations; Vector m_cancelledAnimationNames; HashSet > m_cancelledAnimationPlayers; Vector m_animationsWithPauseToggled; NewTransitionMap m_newTransitions; HashSet m_cancelledTransitions; HashMap > m_activeInterpolationsForAnimations; HashMap > m_activeInterpolationsForTransitions; }; class CSSAnimations final { WTF_MAKE_NONCOPYABLE(CSSAnimations); DISALLOW_ALLOCATION(); public: CSSAnimations(); static const StylePropertyShorthand& animatableProperties(); static bool isAllowedAnimation(CSSPropertyID); // FIXME: We should change the Element* to a const Element* static PassOwnPtr calculateUpdate(Element*, const Element& parentElement, const RenderStyle&, RenderStyle* parentStyle); void setPendingUpdate(PassOwnPtr update) { m_pendingUpdate = update; } void maybeApplyPendingUpdate(Element*); bool isEmpty() const { return m_animations.isEmpty() && m_transitions.isEmpty() && !m_pendingUpdate; } void cancel(); private: struct RunningTransition { ALLOW_ONLY_INLINE_ALLOCATION(); public: RefPtr player; RawPtr from; RawPtr to; }; typedef HashMap > AnimationMap; AnimationMap m_animations; typedef HashMap TransitionMap; TransitionMap m_transitions; OwnPtr m_pendingUpdate; HashMap > m_previousActiveInterpolationsForAnimations; static void calculateTransitionUpdate(CSSAnimationUpdate*, const Element*, const RenderStyle&); static void calculateTransitionUpdateForProperty(CSSPropertyID, CSSPropertyID eventId, const CSSTransitionData&, size_t transitionIndex, 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 AnimationNode::EventDelegate { public: AnimationEventDelegate(Element* target, const AtomicString& name) : m_target(target) , m_name(name) , m_previousPhase(AnimationNode::PhaseNone) , m_previousIteration(nullValue()) { } virtual void onEventCondition(const AnimationNode*) override; private: void maybeDispatch(Document::ListenerType, const AtomicString& eventName, double elapsedTime); RawPtr m_target; const AtomicString m_name; AnimationNode::Phase m_previousPhase; double m_previousIteration; }; class TransitionEventDelegate final : public AnimationNode::EventDelegate { public: TransitionEventDelegate(Element* target, CSSPropertyID property) : m_target(target) , m_property(property) , m_previousPhase(AnimationNode::PhaseNone) { } virtual void onEventCondition(const AnimationNode*) override; private: RawPtr m_target; const CSSPropertyID m_property; AnimationNode::Phase m_previousPhase; }; }; } // namespace blink WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(blink::CSSAnimationUpdate::NewAnimation); #endif // SKY_ENGINE_CORE_ANIMATION_CSS_CSSANIMATIONS_H_