WebCore/page/animation/AnimationController.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions
       
     6  * are met:
       
     7  *
       
     8  * 1.  Redistributions of source code must retain the above copyright
       
     9  *     notice, this list of conditions and the following disclaimer. 
       
    10  * 2.  Redistributions in binary form must reproduce the above copyright
       
    11  *     notice, this list of conditions and the following disclaimer in the
       
    12  *     documentation and/or other materials provided with the distribution. 
       
    13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
       
    14  *     its contributors may be used to endorse or promote products derived
       
    15  *     from this software without specific prior written permission. 
       
    16  *
       
    17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
       
    18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
    19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
       
    20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
       
    21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
       
    22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
       
    23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
       
    24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
       
    26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    27  */
       
    28 
       
    29 #include "config.h"
       
    30 #include "AnimationController.h"
       
    31 
       
    32 #include "AnimationBase.h"
       
    33 #include "AnimationControllerPrivate.h"
       
    34 #include "CSSParser.h"
       
    35 #include "CompositeAnimation.h"
       
    36 #include "EventNames.h"
       
    37 #include "Frame.h"
       
    38 #include "RenderView.h"
       
    39 #include "WebKitAnimationEvent.h"
       
    40 #include "WebKitTransitionEvent.h"
       
    41 #include <wtf/CurrentTime.h>
       
    42 #include <wtf/UnusedParam.h>
       
    43 
       
    44 namespace WebCore {
       
    45 
       
    46 static const double cAnimationTimerDelay = 0.025;
       
    47 static const double cBeginAnimationUpdateTimeNotSet = -1;
       
    48 
       
    49 AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
       
    50     : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired)
       
    51     , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired)
       
    52     , m_frame(frame)
       
    53     , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
       
    54     , m_styleAvailableWaiters(0)
       
    55     , m_lastStyleAvailableWaiter(0)
       
    56     , m_responseWaiters(0)
       
    57     , m_lastResponseWaiter(0)
       
    58     , m_waitingForResponse(false)
       
    59 {
       
    60 }
       
    61 
       
    62 AnimationControllerPrivate::~AnimationControllerPrivate()
       
    63 {
       
    64 }
       
    65 
       
    66 PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimation(RenderObject* renderer)
       
    67 {
       
    68     RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
       
    69     if (!animation) {
       
    70         animation = CompositeAnimation::create(this);
       
    71         m_compositeAnimations.set(renderer, animation);
       
    72     }
       
    73     return animation;
       
    74 }
       
    75 
       
    76 bool AnimationControllerPrivate::clear(RenderObject* renderer)
       
    77 {
       
    78     // Return false if we didn't do anything OR we are suspended (so we don't try to
       
    79     // do a setNeedsStyleRecalc() when suspended).
       
    80     PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer);
       
    81     if (!animation)
       
    82         return false;
       
    83     animation->clearRenderer();
       
    84     return animation->isSuspended();
       
    85 }
       
    86 
       
    87 void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = false*/)
       
    88 {
       
    89     double needsService = -1;
       
    90     bool calledSetChanged = false;
       
    91 
       
    92     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
       
    93     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
       
    94         CompositeAnimation* compAnim = it->second.get();
       
    95         if (!compAnim->isSuspended() && compAnim->hasAnimations()) {
       
    96             double t = compAnim->timeToNextService();
       
    97             if (t != -1 && (t < needsService || needsService == -1))
       
    98                 needsService = t;
       
    99             if (needsService == 0) {
       
   100                 if (callSetChanged) {
       
   101                     Node* node = it->first->node();
       
   102                     ASSERT(!node || (node->document() && !node->document()->inPageCache()));
       
   103                     node->setNeedsStyleRecalc(SyntheticStyleChange);
       
   104                     calledSetChanged = true;
       
   105                 }
       
   106                 else
       
   107                     break;
       
   108             }
       
   109         }
       
   110     }
       
   111     
       
   112     if (calledSetChanged)
       
   113         m_frame->document()->updateStyleIfNeeded();
       
   114     
       
   115     // If we want service immediately, we start a repeating timer to reduce the overhead of starting
       
   116     if (needsService == 0) {
       
   117         if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() == 0)
       
   118             m_animationTimer.startRepeating(cAnimationTimerDelay);
       
   119         return;
       
   120     }
       
   121     
       
   122     // If we don't need service, we want to make sure the timer is no longer running
       
   123     if (needsService < 0) {
       
   124         if (m_animationTimer.isActive())
       
   125             m_animationTimer.stop();
       
   126         return;
       
   127     }
       
   128     
       
   129     // Otherwise, we want to start a one-shot timer so we get here again
       
   130     if (m_animationTimer.isActive())
       
   131         m_animationTimer.stop();
       
   132     m_animationTimer.startOneShot(needsService);
       
   133 }
       
   134 
       
   135 void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*)
       
   136 {
       
   137     fireEventsAndUpdateStyle();
       
   138 }
       
   139 
       
   140 void AnimationControllerPrivate::fireEventsAndUpdateStyle()
       
   141 {
       
   142     // Protect the frame from getting destroyed in the event handler
       
   143     RefPtr<Frame> protector = m_frame;
       
   144 
       
   145     bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_nodeChangesToDispatch.isEmpty();
       
   146     
       
   147     // fire all the events
       
   148     Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end();
       
   149     for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
       
   150         if (it->eventType == eventNames().webkitTransitionEndEvent)
       
   151             it->element->dispatchEvent(WebKitTransitionEvent::create(it->eventType, it->name, it->elapsedTime));
       
   152         else
       
   153             it->element->dispatchEvent(WebKitAnimationEvent::create(it->eventType, it->name, it->elapsedTime));
       
   154     }
       
   155     
       
   156     m_eventsToDispatch.clear();
       
   157     
       
   158     // call setChanged on all the elements
       
   159     Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end();
       
   160     for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it)
       
   161         (*it)->setNeedsStyleRecalc(SyntheticStyleChange);
       
   162     
       
   163     m_nodeChangesToDispatch.clear();
       
   164     
       
   165     if (updateStyle && m_frame)
       
   166         m_frame->document()->updateStyleIfNeeded();
       
   167 }
       
   168 
       
   169 void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
       
   170 {
       
   171     if (!m_updateStyleIfNeededDispatcher.isActive())
       
   172         m_updateStyleIfNeededDispatcher.startOneShot(0);
       
   173 }
       
   174 
       
   175 void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime)
       
   176 {
       
   177     m_eventsToDispatch.grow(m_eventsToDispatch.size()+1);
       
   178     EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1];
       
   179     event.element = element;
       
   180     event.eventType = eventType;
       
   181     event.name = name;
       
   182     event.elapsedTime = elapsedTime;
       
   183     
       
   184     startUpdateStyleIfNeededDispatcher();
       
   185 }
       
   186 
       
   187 void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
       
   188 {
       
   189     ASSERT(!node || (node->document() && !node->document()->inPageCache()));
       
   190     if (!node)
       
   191         return;
       
   192 
       
   193     m_nodeChangesToDispatch.append(node);
       
   194     startUpdateStyleIfNeededDispatcher();
       
   195 }
       
   196 
       
   197 void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>*)
       
   198 {
       
   199     // Make sure animationUpdateTime is updated, so that it is current even if no
       
   200     // styleChange has happened (e.g. accelerated animations)
       
   201     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
       
   202 
       
   203     // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
       
   204     // updateStyleIfNeeded.  It will then call back to us with new information.
       
   205     updateAnimationTimer(true);
       
   206 
       
   207     // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before
       
   208     // the 'end' event fires.
       
   209     fireEventsAndUpdateStyle();
       
   210 }
       
   211 
       
   212 bool AnimationControllerPrivate::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
       
   213 {
       
   214     RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
       
   215     if (!animation)
       
   216         return false;
       
   217 
       
   218     return animation->isAnimatingProperty(property, false, isRunningNow);
       
   219 }
       
   220 
       
   221 bool AnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
       
   222 {
       
   223     RefPtr<CompositeAnimation> animation = m_compositeAnimations.get(renderer);
       
   224     if (!animation)
       
   225         return false;
       
   226 
       
   227     return animation->isAnimatingProperty(property, true, isRunningNow);
       
   228 }
       
   229 
       
   230 void AnimationControllerPrivate::suspendAnimations(Document* document)
       
   231 {
       
   232     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
       
   233     
       
   234     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
       
   235     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
       
   236         RenderObject* renderer = it->first;
       
   237         if (renderer->document() == document) {
       
   238             CompositeAnimation* compAnim = it->second.get();
       
   239             compAnim->suspendAnimations();
       
   240         }
       
   241     }
       
   242     
       
   243     updateAnimationTimer();
       
   244 }
       
   245 
       
   246 void AnimationControllerPrivate::resumeAnimations(Document* document)
       
   247 {
       
   248     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
       
   249     
       
   250     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
       
   251     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
       
   252         RenderObject* renderer = it->first;
       
   253         if (renderer->document() == document) {
       
   254             CompositeAnimation* compAnim = it->second.get();
       
   255             compAnim->resumeAnimations();
       
   256         }
       
   257     }
       
   258     
       
   259     updateAnimationTimer();
       
   260 }
       
   261 
       
   262 bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t)
       
   263 {
       
   264     if (!renderer)
       
   265         return false;
       
   266 
       
   267     RefPtr<CompositeAnimation> compAnim = accessCompositeAnimation(renderer);
       
   268     if (!compAnim)
       
   269         return false;
       
   270 
       
   271     if (compAnim->pauseAnimationAtTime(name, t)) {
       
   272         renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
       
   273         startUpdateStyleIfNeededDispatcher();
       
   274         return true;
       
   275     }
       
   276 
       
   277     return false;
       
   278 }
       
   279 
       
   280 bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, const String& property, double t)
       
   281 {
       
   282     if (!renderer)
       
   283         return false;
       
   284 
       
   285     RefPtr<CompositeAnimation> compAnim = accessCompositeAnimation(renderer);
       
   286     if (!compAnim)
       
   287         return false;
       
   288 
       
   289     if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) {
       
   290         renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
       
   291         startUpdateStyleIfNeededDispatcher();
       
   292         return true;
       
   293     }
       
   294 
       
   295     return false;
       
   296 }
       
   297 
       
   298 double AnimationControllerPrivate::beginAnimationUpdateTime()
       
   299 {
       
   300     if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
       
   301         m_beginAnimationUpdateTime = currentTime();
       
   302     return m_beginAnimationUpdateTime;
       
   303 }
       
   304 
       
   305 void AnimationControllerPrivate::endAnimationUpdate()
       
   306 {
       
   307     styleAvailable();
       
   308     if (!m_waitingForResponse)
       
   309         startTimeResponse(beginAnimationUpdateTime());
       
   310 }
       
   311 
       
   312 void AnimationControllerPrivate::receivedStartTimeResponse(double time)
       
   313 {
       
   314     m_waitingForResponse = false;
       
   315     startTimeResponse(time);
       
   316 }
       
   317 
       
   318 PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderObject* renderer)
       
   319 {
       
   320     if (!renderer)
       
   321         return 0;
       
   322 
       
   323     RefPtr<CompositeAnimation> rendererAnimations = m_compositeAnimations.get(renderer);
       
   324     if (!rendererAnimations)
       
   325         return renderer->style();
       
   326     
       
   327     // Make sure animationUpdateTime is updated, so that it is current even if no
       
   328     // styleChange has happened (e.g. accelerated animations).
       
   329     setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
       
   330     RefPtr<RenderStyle> animatingStyle = rendererAnimations->getAnimatedStyle();
       
   331     if (!animatingStyle)
       
   332         animatingStyle = renderer->style();
       
   333     
       
   334     return animatingStyle.release();
       
   335 }
       
   336 
       
   337 unsigned AnimationControllerPrivate::numberOfActiveAnimations() const
       
   338 {
       
   339     unsigned count = 0;
       
   340     
       
   341     RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
       
   342     for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
       
   343         CompositeAnimation* compAnim = it->second.get();
       
   344         count += compAnim->numberOfActiveAnimations();
       
   345     }
       
   346     
       
   347     return count;
       
   348 }
       
   349 
       
   350 void AnimationControllerPrivate::addToStyleAvailableWaitList(AnimationBase* animation)
       
   351 {
       
   352     ASSERT(!animation->next());
       
   353     
       
   354     if (m_styleAvailableWaiters)
       
   355         m_lastStyleAvailableWaiter->setNext(animation);
       
   356     else
       
   357         m_styleAvailableWaiters = animation;
       
   358         
       
   359     m_lastStyleAvailableWaiter = animation;
       
   360     animation->setNext(0);
       
   361 }
       
   362 
       
   363 void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase* animationToRemove)
       
   364 {
       
   365     AnimationBase* prevAnimation = 0;
       
   366     for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next()) {
       
   367         if (animation == animationToRemove) {
       
   368             if (prevAnimation)
       
   369                 prevAnimation->setNext(animation->next());
       
   370             else
       
   371                 m_styleAvailableWaiters = animation->next();
       
   372             
       
   373             if (m_lastStyleAvailableWaiter == animation)
       
   374                 m_lastStyleAvailableWaiter = prevAnimation;
       
   375                 
       
   376             animationToRemove->setNext(0);
       
   377         }
       
   378     }
       
   379 }
       
   380 
       
   381 void AnimationControllerPrivate::styleAvailable()
       
   382 {
       
   383     // Go through list of waiters and send them on their way
       
   384     for (AnimationBase* animation = m_styleAvailableWaiters; animation; ) {
       
   385         AnimationBase* nextAnimation = animation->next();
       
   386         animation->setNext(0);
       
   387         animation->styleAvailable();
       
   388         animation = nextAnimation;
       
   389     }
       
   390     
       
   391     m_styleAvailableWaiters = 0;
       
   392     m_lastStyleAvailableWaiter = 0;
       
   393 }
       
   394 
       
   395 void AnimationControllerPrivate::addToStartTimeResponseWaitList(AnimationBase* animation, bool willGetResponse)
       
   396 {
       
   397     // If willGetResponse is true, it means this animation is actually waiting for a response
       
   398     // (which will come in as a call to notifyAnimationStarted()).
       
   399     // In that case we don't need to add it to this list. We just set a waitingForAResponse flag 
       
   400     // which says we are waiting for the response. If willGetResponse is false, this animation 
       
   401     // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for 
       
   402     // another animation to which it will sync.
       
   403     //
       
   404     // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
       
   405     // true. If so, we just return and will do our work when the first notifyXXXStarted() call
       
   406     // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
       
   407     // do our work right away. In both cases we call the onAnimationStartResponse() method
       
   408     // on each animation. In the first case we send in the time we got from notifyXXXStarted().
       
   409     // In the second case, we just pass in the beginAnimationUpdateTime().
       
   410     //
       
   411     // This will synchronize all software and accelerated animations started in the same 
       
   412     // updateStyleIfNeeded cycle.
       
   413     //
       
   414     ASSERT(!animation->next());
       
   415     
       
   416     if (willGetResponse)
       
   417         m_waitingForResponse = true;
       
   418     
       
   419     if (m_responseWaiters)
       
   420         m_lastResponseWaiter->setNext(animation);
       
   421     else
       
   422         m_responseWaiters = animation;
       
   423         
       
   424     m_lastResponseWaiter = animation;
       
   425     animation->setNext(0);
       
   426 }
       
   427 
       
   428 void AnimationControllerPrivate::removeFromStartTimeResponseWaitList(AnimationBase* animationToRemove)
       
   429 {
       
   430     AnimationBase* prevAnimation = 0;
       
   431     for (AnimationBase* animation = m_responseWaiters; animation; animation = animation->next()) {
       
   432         if (animation == animationToRemove) {
       
   433             if (prevAnimation)
       
   434                 prevAnimation->setNext(animation->next());
       
   435             else
       
   436                 m_responseWaiters = animation->next();
       
   437             
       
   438             if (m_lastResponseWaiter == animation)
       
   439                 m_lastResponseWaiter = prevAnimation;
       
   440                 
       
   441             animationToRemove->setNext(0);
       
   442         }
       
   443         prevAnimation = animation;
       
   444     }
       
   445 }
       
   446 
       
   447 void AnimationControllerPrivate::startTimeResponse(double time)
       
   448 {
       
   449     // Go through list of waiters and send them on their way
       
   450     for (AnimationBase* animation = m_responseWaiters; animation; ) {
       
   451         AnimationBase* nextAnimation = animation->next();
       
   452         animation->setNext(0);
       
   453         animation->onAnimationStartResponse(time);
       
   454         animation = nextAnimation;
       
   455     }
       
   456     
       
   457     m_responseWaiters = 0;
       
   458     m_lastResponseWaiter = 0;
       
   459 }
       
   460 
       
   461 AnimationController::AnimationController(Frame* frame)
       
   462     : m_data(new AnimationControllerPrivate(frame))
       
   463 {
       
   464 }
       
   465 
       
   466 AnimationController::~AnimationController()
       
   467 {
       
   468     delete m_data;
       
   469 }
       
   470 
       
   471 void AnimationController::cancelAnimations(RenderObject* renderer)
       
   472 {
       
   473     if (!m_data->hasAnimations())
       
   474         return;
       
   475 
       
   476     if (m_data->clear(renderer)) {
       
   477         Node* node = renderer->node();
       
   478         ASSERT(!node || (node->document() && !node->document()->inPageCache()));
       
   479         node->setNeedsStyleRecalc(SyntheticStyleChange);
       
   480     }
       
   481 }
       
   482 
       
   483 PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* renderer, RenderStyle* newStyle)
       
   484 {
       
   485     // Don't do anything if we're in the cache
       
   486     if (!renderer->document() || renderer->document()->inPageCache())
       
   487         return newStyle;
       
   488 
       
   489     RenderStyle* oldStyle = renderer->style();
       
   490 
       
   491     if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle->animations() && !newStyle->transitions()))
       
   492         return newStyle;
       
   493 
       
   494     // Don't run transitions when printing.
       
   495     if (renderer->view()->printing())
       
   496         return newStyle;
       
   497 
       
   498     // Fetch our current set of implicit animations from a hashtable.  We then compare them
       
   499     // against the animations in the style and make sure we're in sync.  If destination values
       
   500     // have changed, we reset the animation.  We then do a blend to get new values and we return
       
   501     // a new style.
       
   502     ASSERT(renderer->node()); // FIXME: We do not animate generated content yet.
       
   503 
       
   504     RefPtr<CompositeAnimation> rendererAnimations = m_data->accessCompositeAnimation(renderer);
       
   505     RefPtr<RenderStyle> blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle);
       
   506 
       
   507     m_data->updateAnimationTimer();
       
   508 
       
   509     if (blendedStyle != newStyle) {
       
   510         // If the animations/transitions change opacity or transform, we need to update
       
   511         // the style to impose the stacking rules. Note that this is also
       
   512         // done in CSSStyleSelector::adjustRenderStyle().
       
   513         if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform()))
       
   514             blendedStyle->setZIndex(0);
       
   515     }
       
   516     return blendedStyle.release();
       
   517 }
       
   518 
       
   519 PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderObject* renderer)
       
   520 {
       
   521     return m_data->getAnimatedStyleForRenderer(renderer);
       
   522 }
       
   523 
       
   524 void AnimationController::notifyAnimationStarted(RenderObject*, double startTime)
       
   525 {
       
   526     m_data->receivedStartTimeResponse(startTime);
       
   527 }
       
   528 
       
   529 bool AnimationController::pauseAnimationAtTime(RenderObject* renderer, const String& name, double t)
       
   530 {
       
   531     return m_data->pauseAnimationAtTime(renderer, name, t);
       
   532 }
       
   533 
       
   534 unsigned AnimationController::numberOfActiveAnimations() const
       
   535 {
       
   536     return m_data->numberOfActiveAnimations();
       
   537 }
       
   538 
       
   539 bool AnimationController::pauseTransitionAtTime(RenderObject* renderer, const String& property, double t)
       
   540 {
       
   541     return m_data->pauseTransitionAtTime(renderer, property, t);
       
   542 }
       
   543 
       
   544 bool AnimationController::isRunningAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
       
   545 {
       
   546     return m_data->isRunningAnimationOnRenderer(renderer, property, isRunningNow);
       
   547 }
       
   548 
       
   549 bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderObject* renderer, CSSPropertyID property, bool isRunningNow) const
       
   550 {
       
   551     return m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, isRunningNow);
       
   552 }
       
   553 
       
   554 void AnimationController::suspendAnimations(Document* document)
       
   555 {
       
   556     m_data->suspendAnimations(document);
       
   557 }
       
   558 
       
   559 void AnimationController::resumeAnimations(Document* document)
       
   560 {
       
   561     m_data->resumeAnimations(document);
       
   562 }
       
   563 
       
   564 void AnimationController::beginAnimationUpdate()
       
   565 {
       
   566     m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
       
   567 }
       
   568 
       
   569 void AnimationController::endAnimationUpdate()
       
   570 {
       
   571     m_data->endAnimationUpdate();
       
   572 }
       
   573 
       
   574 bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
       
   575 {
       
   576 #if USE(ACCELERATED_COMPOSITING)
       
   577     return AnimationBase::animationOfPropertyIsAccelerated(property);
       
   578 #else
       
   579     UNUSED_PARAM(property);
       
   580     return false;
       
   581 #endif
       
   582 }
       
   583 
       
   584 } // namespace WebCore