diff options
Diffstat (limited to 'WebCore/page/animation/KeyframeAnimation.cpp')
-rw-r--r-- | WebCore/page/animation/KeyframeAnimation.cpp | 180 |
1 files changed, 136 insertions, 44 deletions
diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp index 2efa578..88a5f6a 100644 --- a/WebCore/page/animation/KeyframeAnimation.cpp +++ b/WebCore/page/animation/KeyframeAnimation.cpp @@ -29,12 +29,14 @@ #include "config.h" #include "KeyframeAnimation.h" -#include "AnimationController.h" +#include "AnimationControllerPrivate.h" #include "CSSPropertyNames.h" #include "CSSStyleSelector.h" #include "CompositeAnimation.h" #include "EventNames.h" -#include "RenderObject.h" +#include "RenderLayer.h" +#include "RenderLayerBacking.h" +#include <wtf/UnusedParam.h> namespace WebCore { @@ -45,8 +47,8 @@ KeyframeAnimation::KeyframeAnimation(const Animation* animation, RenderObject* r , m_unanimatedStyle(unanimatedStyle) { // Get the keyframe RenderStyles - if (m_object && m_object->element() && m_object->element()->isElementNode()) - m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->element()), unanimatedStyle, m_keyframes); + if (m_object && m_object->node() && m_object->node()->isElementNode()) + m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->node()), unanimatedStyle, m_keyframes); // Update the m_transformFunctionListValid flag based on whether the function lists in the keyframes match. validateTransformFunctionList(); @@ -59,32 +61,8 @@ KeyframeAnimation::~KeyframeAnimation() updateStateMachine(AnimationStateInputEndAnimation, -1); } -void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) +void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const { - // Fire the start timeout if needed - fireAnimationEventsIfNeeded(); - - // If we have not yet started, we will not have a valid start time, so just start the animation if needed. - if (isNew() && m_animation->playState() == AnimPlayStatePlaying) - updateStateMachine(AnimationStateInputStartAnimation, -1); - - // If we get this far and the animation is done, it means we are cleaning up a just finished animation. - // If so, we need to send back the targetStyle. - if (postActive()) { - if (!animatedStyle) - animatedStyle = const_cast<RenderStyle*>(targetStyle); - return; - } - - // If we are waiting for the start timer, we don't want to change the style yet. - // Special case - if the delay time is 0, then we do want to set the first frame of the - // animation right away. This avoids a flash when the animation starts. - if (waitingToStart() && m_animation->delay() > 0) - return; - - // FIXME: we need to be more efficient about determining which keyframes we are animating between. - // We should cache the last pair or something. - // Find the first key double elapsedTime = getElapsedTime(); @@ -94,8 +72,6 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render if (m_animation->direction() && (i & 1)) t = 1 - t; - const RenderStyle* fromStyle = 0; - const RenderStyle* toStyle = 0; double scale = 1; double offset = 0; Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes(); @@ -113,6 +89,48 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render fromStyle = it->style(); } + if (!fromStyle || !toStyle) + return; + + const TimingFunction* timingFunction = 0; + if (fromStyle->animations() && fromStyle->animations()->size() > 0) + timingFunction = &(fromStyle->animations()->animation(0)->timingFunction()); + + prog = progress(scale, offset, timingFunction); +} + +void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle) +{ + // Fire the start timeout if needed + fireAnimationEventsIfNeeded(); + + // If we have not yet started, we will not have a valid start time, so just start the animation if needed. + if (isNew() && m_animation->playState() == AnimPlayStatePlaying) + updateStateMachine(AnimationStateInputStartAnimation, -1); + + // If we get this far and the animation is done, it means we are cleaning up a just finished animation. + // If so, we need to send back the targetStyle. + if (postActive()) { + if (!animatedStyle) + animatedStyle = const_cast<RenderStyle*>(targetStyle); + return; + } + + // If we are waiting for the start timer, we don't want to change the style yet. + // Special case - if the delay time is 0, then we do want to set the first frame of the + // animation right away. This avoids a flash when the animation starts. + if (waitingToStart() && m_animation->delay() > 0) + return; + + // FIXME: we need to be more efficient about determining which keyframes we are animating between. + // We should cache the last pair or something. + + // Get the from/to styles and progress between + const RenderStyle* fromStyle = 0; + const RenderStyle* toStyle = 0; + double progress; + getKeyframeAnimationInterval(fromStyle, toStyle, progress); + // If either style is 0 we have an invalid case, just stop the animation. if (!fromStyle || !toStyle) { updateStateMachine(AnimationStateInputEndAnimation, -1); @@ -124,19 +142,42 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render if (!animatedStyle) animatedStyle = RenderStyle::clone(targetStyle); - const TimingFunction* timingFunction = 0; - if (fromStyle->animations() && fromStyle->animations()->size() > 0) - timingFunction = &(fromStyle->animations()->animation(0)->timingFunction()); - - double prog = progress(scale, offset, timingFunction); - HashSet<int>::const_iterator endProperties = m_keyframes.endProperties(); for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { - if (blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, prog)) + bool needsAnim = blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); + if (needsAnim) setAnimating(); + else { +#if USE(ACCELERATED_COMPOSITING) + // If we are running an accelerated animation, set a flag in the style + // to indicate it. This can be used to make sure we get an updated + // style for hit testing, etc. + animatedStyle->setIsRunningAcceleratedAnimation(); +#endif + } } } +void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle) +{ + // Get the from/to styles and progress between + const RenderStyle* fromStyle = 0; + const RenderStyle* toStyle = 0; + double progress; + getKeyframeAnimationInterval(fromStyle, toStyle, progress); + + // If either style is 0 we have an invalid case + if (!fromStyle || !toStyle) + return; + + if (!animatedStyle) + animatedStyle = RenderStyle::clone(m_object->style()); + + HashSet<int>::const_iterator endProperties = m_keyframes.endProperties(); + for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) + blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress); +} + bool KeyframeAnimation::hasAnimationForProperty(int property) const { HashSet<int>::const_iterator end = m_keyframes.endProperties(); @@ -148,14 +189,38 @@ bool KeyframeAnimation::hasAnimationForProperty(int property) const return false; } -void KeyframeAnimation::endAnimation(bool) +bool KeyframeAnimation::startAnimation(double beginTime) +{ +#if USE(ACCELERATED_COMPOSITING) + if (m_object && m_object->hasLayer()) { + RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); + if (layer->isComposited()) + return layer->backing()->startAnimation(beginTime, m_animation.get(), m_keyframes); + } +#else + UNUSED_PARAM(beginTime); +#endif + return false; +} + +void KeyframeAnimation::endAnimation(bool reset) { - // Restore the original (unanimated) style - if (m_object) - setChanged(m_object->element()); + if (m_object) { +#if USE(ACCELERATED_COMPOSITING) + if (m_object->hasLayer()) { + RenderLayer* layer = toRenderBoxModelObject(m_object)->layer(); + if (layer->isComposited()) + layer->backing()->animationFinished(m_keyframes.animationName(), 0, reset); + } +#else + UNUSED_PARAM(reset); +#endif + // Restore the original (unanimated) style + setChanged(m_object->node()); + } } -bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) +bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const { return m_object->document()->hasListenerType(listenerType); } @@ -201,7 +266,7 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double return false; // Schedule event handling - m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); + m_compAnim->animationControllerPriv()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime); // Restore the original (unanimated) style if (eventType == eventNames().webkitAnimationEndEvent && element->renderer()) @@ -287,4 +352,31 @@ void KeyframeAnimation::validateTransformFunctionList() m_transformFunctionListValid = true; } +double KeyframeAnimation::willNeedService() +{ + double t = AnimationBase::willNeedService(); +#if USE(ACCELERATED_COMPOSITING) + if (t != 0 || preActive()) + return t; + + // A return value of 0 means we need service. But if we only have accelerated animations we + // only need service at the end of the transition + HashSet<int>::const_iterator endProperties = m_keyframes.endProperties(); + bool acceleratedPropertiesOnly = true; + + for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) { + if (!animationOfPropertyIsAccelerated(*it) || isFallbackAnimating()) { + acceleratedPropertiesOnly = false; + break; + } + } + + if (acceleratedPropertiesOnly) { + bool isLooping; + getTimeToNextEvent(t, isLooping); + } +#endif + return t; +} + } // namespace WebCore |