diff options
Diffstat (limited to 'WebCore/page/animation/AnimationController.cpp')
-rw-r--r-- | WebCore/page/animation/AnimationController.cpp | 243 |
1 files changed, 131 insertions, 112 deletions
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp index f85e6c1..f9c9a47 100644 --- a/WebCore/page/animation/AnimationController.cpp +++ b/WebCore/page/animation/AnimationController.cpp @@ -28,84 +28,22 @@ #include "config.h" #include "AnimationController.h" + #include "AnimationBase.h" -#include "CompositeAnimation.h" +#include "AnimationControllerPrivate.h" #include "CSSParser.h" +#include "CompositeAnimation.h" #include "EventNames.h" #include "Frame.h" -#include "Timer.h" +#include "RenderObject.h" #include <wtf/CurrentTime.h> +#include <wtf/UnusedParam.h> namespace WebCore { static const double cAnimationTimerDelay = 0.025; static const double cBeginAnimationUpdateTimeNotSet = -1; -class AnimationControllerPrivate { -public: - AnimationControllerPrivate(Frame*); - ~AnimationControllerPrivate(); - - PassRefPtr<CompositeAnimation> accessCompositeAnimation(RenderObject*); - bool clear(RenderObject*); - - void animationTimerFired(Timer<AnimationControllerPrivate>*); - void updateAnimationTimer(bool callSetChanged = false); - - void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*); - void startUpdateRenderingDispatcher(); - void addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime); - void addNodeChangeToDispatch(PassRefPtr<Node>); - - bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); } - - void suspendAnimations(Document*); - void resumeAnimations(Document*); - - void styleAvailable(); - - bool isAnimatingPropertyOnRenderer(RenderObject*, int property, bool isRunningNow) const; - - bool pauseAnimationAtTime(RenderObject*, const String& name, double t); - bool pauseTransitionAtTime(RenderObject*, const String& property, double t); - unsigned numberOfActiveAnimations() const; - - double beginAnimationUpdateTime() - { - if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet) - m_beginAnimationUpdateTime = currentTime(); - return m_beginAnimationUpdateTime; - } - - void setBeginAnimationUpdateTime(double t) { m_beginAnimationUpdateTime = t; } - - void addToStyleAvailableWaitList(AnimationBase*); - void removeFromStyleAvailableWaitList(AnimationBase*); - -private: - typedef HashMap<RenderObject*, RefPtr<CompositeAnimation> > RenderObjectAnimationMap; - - RenderObjectAnimationMap m_compositeAnimations; - Timer<AnimationControllerPrivate> m_animationTimer; - Timer<AnimationControllerPrivate> m_updateRenderingDispatcher; - Frame* m_frame; - - class EventToDispatch { - public: - RefPtr<Element> element; - AtomicString eventType; - String name; - double elapsedTime; - }; - - Vector<EventToDispatch> m_eventsToDispatch; - Vector<RefPtr<Node> > m_nodeChangesToDispatch; - - double m_beginAnimationUpdateTime; - AnimationBase* m_styleAvailableWaiters; - AnimationBase* m_lastStyleAvailableWaiter; -}; - AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) , m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired) @@ -113,6 +51,9 @@ AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet) , m_styleAvailableWaiters(0) , m_lastStyleAvailableWaiter(0) + , m_responseWaiters(0) + , m_lastResponseWaiter(0) + , m_waitingForAResponse(false) { } @@ -124,7 +65,7 @@ PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimat { RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); if (!animation) { - animation = CompositeAnimation::create(m_frame->animation()); + animation = CompositeAnimation::create(this); m_compositeAnimations.set(renderer, animation); } return animation; @@ -155,7 +96,7 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa needsService = t; if (needsService == 0) { if (callSetChanged) { - Node* node = it->first->element(); + Node* node = it->first->node(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); node->setChanged(AnimationStyleChange); calledSetChanged = true; @@ -209,7 +150,7 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC m_nodeChangesToDispatch.clear(); - if (m_frame && m_frame->document()) + if (m_frame) m_frame->document()->updateRendering(); } @@ -233,6 +174,10 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) { + ASSERT(!node || (node->document() && !node->document()->inPageCache())); + if (!node) + return; + m_nodeChangesToDispatch.append(node); startUpdateRenderingDispatcher(); } @@ -240,7 +185,7 @@ void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node) void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*) { // Make sure animationUpdateTime is updated, so that it is current even if no - // styleChange has happened (e.g. hardware animations) + // styleChange has happened (e.g. accelerated animations) setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate @@ -248,7 +193,7 @@ void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPr updateAnimationTimer(true); } -bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const +bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const { RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer); if (!animation) @@ -294,6 +239,7 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co if (compAnim->pauseAnimationAtTime(name, t)) { renderer->node()->setChanged(AnimationStyleChange); + startUpdateRenderingDispatcher(); return true; } @@ -311,12 +257,39 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) { renderer->node()->setChanged(AnimationStyleChange); + startUpdateRenderingDispatcher(); return true; } return false; } +double AnimationControllerPrivate::beginAnimationUpdateTime() +{ + if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet) + m_beginAnimationUpdateTime = currentTime(); + return m_beginAnimationUpdateTime; +} + +PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer) +{ + if (!renderer) + return 0; + + RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer); + if (!rendererAnimations) + return renderer->style(); + + // Make sure animationUpdateTime is updated, so that it is current even if no + // styleChange has happened (e.g. accelerated animations). + setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); + RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle(); + if (!animatingStyle) + animatingStyle = renderer->style(); + + return animatingStyle.release(); +} + unsigned AnimationControllerPrivate::numberOfActiveAnimations() const { unsigned count = 0; @@ -364,13 +337,83 @@ void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase* void AnimationControllerPrivate::styleAvailable() { // Go through list of waiters and send them on their way - for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next()) + for (AnimationBase* animation = m_styleAvailableWaiters; animation; ) { + AnimationBase* nextAnimation = animation->next(); + animation->setNext(0); animation->styleAvailable(); + animation = nextAnimation; + } m_styleAvailableWaiters = 0; m_lastStyleAvailableWaiter = 0; } +void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse) +{ + // If willGetResponse is true, it means this animation is actually waiting for a response + // (which will come in as a call to notifyAnimationStarted()). + // In that case we don't need to add it to this list. We just set a waitingForAResponse flag + // which says we are waiting for the response. If willGetResponse is false, this animation + // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for + // another animation to which it will sync. + // + // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is + // true. If so, we just return and will do our work when the first notifyXXXStarted() call + // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will + // do our work right away. In both cases we call the onAnimationStartResponse() method + // on each animation. In the first case we send in the time we got from notifyXXXStarted(). + // In the second case, we just pass in the beginAnimationUpdateTime(). + // + // This will synchronize all software and accelerated animations started in the same + // updateRendering cycle. + // + ASSERT(!animation->next()); + + if (willGetResponse) + m_waitingForAResponse = true; + + if (m_responseWaiters) + m_lastResponseWaiter->setNext(animation); + else + m_responseWaiters = animation; + + m_lastResponseWaiter = animation; + animation->setNext(0); +} + +void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove) +{ + AnimationBase* prevAnimation = 0; + for (AnimationBase* animation = m_responseWaiters; animation; animation = animation->next()) { + if (animation == animationToRemove) { + if (prevAnimation) + prevAnimation->setNext(animation->next()); + else + m_responseWaiters = animation->next(); + + if (m_lastResponseWaiter == animation) + m_lastResponseWaiter = prevAnimation; + + animationToRemove->setNext(0); + } + prevAnimation = animation; + } +} + +void AnimationControllerPrivate::startTimeResponse(double t) +{ + // Go through list of waiters and send them on their way + for (AnimationBase* animation = m_responseWaiters; animation; ) { + AnimationBase* nextAnimation = animation->next(); + animation->setNext(0); + animation->onAnimationStartResponse(t); + animation = nextAnimation; + } + + m_responseWaiters = 0; + m_lastResponseWaiter = 0; +} + AnimationController::AnimationController(Frame* frame) : m_data(new AnimationControllerPrivate(frame)) { @@ -387,7 +430,7 @@ void AnimationController::cancelAnimations(RenderObject* renderer) return; if (m_data->clear(renderer)) { - Node* node = renderer->element(); + Node* node = renderer->node(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); node->setChanged(AnimationStyleChange); } @@ -408,7 +451,7 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend // against the animations in the style and make sure we're in sync. If destination values // have changed, we reset the animation. We then do a blend to get new values and we return // a new style. - ASSERT(renderer->element()); // FIXME: We do not animate generated content yet. + ASSERT(renderer->node()); // FIXME: We do not animate generated content yet. RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer); RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle); @@ -425,16 +468,14 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend return blendedStyle.release(); } -void AnimationController::setAnimationStartTime(RenderObject* renderer, double t) +PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer) { - RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer); - rendererAnimations->setAnimationStartTime(t); + return m_data->getAnimatedStyleForRenderer(renderer); } -void AnimationController::setTransitionStartTime(RenderObject* renderer, int property, double t) +void AnimationController::notifyAnimationStarted(RenderObject*, double startTime) { - RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer); - rendererAnimations->setTransitionStartTime(property, t); + m_data->receivedStartTimeResponse(startTime); } bool AnimationController::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t) @@ -452,7 +493,7 @@ bool AnimationController::pauseTransitionAtTime(RenderObject* renderer, const St return m_data->pauseTransitionAtTime(renderer, property, t); } -bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, int property, bool isRunningNow) const +bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const { return m_data->isAnimatingPropertyOnRenderer(renderer, property, isRunningNow); } @@ -467,28 +508,6 @@ void AnimationController::resumeAnimations(Document* document) m_data->resumeAnimations(document); } -void AnimationController::startUpdateRenderingDispatcher() -{ - m_data->startUpdateRenderingDispatcher(); -} - -void AnimationController::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime) -{ - m_data->addEventToDispatch(element, eventType, name, elapsedTime); -} - -void AnimationController::addNodeChangeToDispatch(PassRefPtr<Node> node) -{ - ASSERT(!node || (node->document() && !node->document()->inPageCache())); - if (node) - m_data->addNodeChangeToDispatch(node); -} - -double AnimationController::beginAnimationUpdateTime() -{ - return m_data->beginAnimationUpdateTime(); -} - void AnimationController::beginAnimationUpdate() { m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet); @@ -496,17 +515,17 @@ void AnimationController::beginAnimationUpdate() void AnimationController::endAnimationUpdate() { - m_data->styleAvailable(); + m_data->endAnimationUpdate(); } -void AnimationController::addToStyleAvailableWaitList(AnimationBase* animation) +bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property) { - m_data->addToStyleAvailableWaitList(animation); -} - -void AnimationController::removeFromStyleAvailableWaitList(AnimationBase* animation) -{ - m_data->removeFromStyleAvailableWaitList(animation); +#if USE(ACCELERATED_COMPOSITING) + return AnimationBase::animationOfPropertyIsAccelerated(property); +#else + UNUSED_PARAM(property); + return false; +#endif } } // namespace WebCore |