6452a895e531f03bd049fcedc5a0948fea99c99d
[WebKit-https.git] / Source / WebCore / page / animation / AnimationController.cpp
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 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 "AnimationEvent.h"
35 #include "CSSParser.h"
36 #include "CSSPropertyAnimation.h"
37 #include "CompositeAnimation.h"
38 #include "EventNames.h"
39 #include "Frame.h"
40 #include "FrameView.h"
41 #include "Logging.h"
42 #include "PseudoElement.h"
43 #include "RenderView.h"
44 #include "TransitionEvent.h"
45 #include "WebKitAnimationEvent.h"
46 #include "WebKitTransitionEvent.h"
47 #include <wtf/CurrentTime.h>
48
49 namespace WebCore {
50
51 static const double cAnimationTimerDelay = 0.025;
52 static const double cBeginAnimationUpdateTimeNotSet = -1;
53
54 class AnimationPrivateUpdateBlock {
55 public:
56     AnimationPrivateUpdateBlock(AnimationControllerPrivate& animationController)
57         : m_animationController(animationController)
58     {
59         m_animationController.beginAnimationUpdate();
60     }
61     
62     ~AnimationPrivateUpdateBlock()
63     {
64         m_animationController.endAnimationUpdate();
65     }
66     
67     AnimationControllerPrivate& m_animationController;
68 };
69
70 AnimationControllerPrivate::AnimationControllerPrivate(Frame& frame)
71     : m_animationTimer(*this, &AnimationControllerPrivate::animationTimerFired)
72     , m_updateStyleIfNeededDispatcher(*this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired)
73     , m_frame(frame)
74     , m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
75     , m_animationsWaitingForStyle()
76     , m_animationsWaitingForStartTimeResponse()
77     , m_beginAnimationUpdateCount(0)
78     , m_waitingForAsyncStartNotification(false)
79     , m_isSuspended(false)
80     , m_allowsNewAnimationsWhileSuspended(false)
81 {
82 }
83
84 AnimationControllerPrivate::~AnimationControllerPrivate()
85 {
86 }
87
88 CompositeAnimation& AnimationControllerPrivate::ensureCompositeAnimation(RenderElement& renderer)
89 {
90     auto result = m_compositeAnimations.add(&renderer, nullptr);
91     if (result.isNewEntry) {
92         result.iterator->value = CompositeAnimation::create(this);
93         renderer.setIsCSSAnimating(true);
94     }
95
96     return *result.iterator->value;
97 }
98
99 bool AnimationControllerPrivate::clear(RenderElement& renderer)
100 {
101     ASSERT(renderer.isCSSAnimating());
102     ASSERT(m_compositeAnimations.contains(&renderer));
103     // Return false if we didn't do anything OR we are suspended (so we don't try to
104     // do a setNeedsStyleRecalc() when suspended).
105     RefPtr<CompositeAnimation> animation = m_compositeAnimations.take(&renderer);
106     ASSERT(animation);
107     renderer.setIsCSSAnimating(false);
108     animation->clearRenderer();
109     return animation->isSuspended();
110 }
111
112 double AnimationControllerPrivate::updateAnimations(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
113 {
114     double timeToNextService = -1;
115     bool calledSetChanged = false;
116
117     auto end = m_compositeAnimations.end();
118     for (auto it = m_compositeAnimations.begin(); it != end; ++it) {
119         CompositeAnimation& animation = *it->value;
120         if (!animation.isSuspended() && animation.hasAnimations()) {
121             double t = animation.timeToNextService();
122             if (t != -1 && (t < timeToNextService || timeToNextService == -1))
123                 timeToNextService = t;
124             if (!timeToNextService) {
125                 if (callSetChanged != CallSetChanged)
126                     break;
127                 Element* element = it->key->element();
128                 ASSERT(element);
129                 ASSERT(!element->document().inPageCache());
130                 element->setNeedsStyleRecalc(SyntheticStyleChange);
131                 calledSetChanged = true;
132             }
133         }
134     }
135
136     if (calledSetChanged)
137         m_frame.document()->updateStyleIfNeeded();
138
139     return timeToNextService;
140 }
141
142 void AnimationControllerPrivate::updateAnimationTimerForRenderer(RenderElement& renderer)
143 {
144     double timeToNextService = 0;
145
146     const CompositeAnimation* compositeAnimation = m_compositeAnimations.get(&renderer);
147     if (!compositeAnimation->isSuspended() && compositeAnimation->hasAnimations())
148         timeToNextService = compositeAnimation->timeToNextService();
149
150     if (m_animationTimer.isActive() && (m_animationTimer.repeatInterval() || m_animationTimer.nextFireInterval() <= timeToNextService))
151         return;
152
153     m_animationTimer.startOneShot(timeToNextService);
154 }
155
156 void AnimationControllerPrivate::updateAnimationTimer(SetChanged callSetChanged/* = DoNotCallSetChanged*/)
157 {
158     double timeToNextService = updateAnimations(callSetChanged);
159
160     LOG(Animations, "updateAnimationTimer: timeToNextService is %.2f", timeToNextService);
161
162     // If we want service immediately, we start a repeating timer to reduce the overhead of starting
163     if (!timeToNextService) {
164         if (!m_animationTimer.isActive() || m_animationTimer.repeatInterval() == 0)
165             m_animationTimer.startRepeating(cAnimationTimerDelay);
166         return;
167     }
168
169     // If we don't need service, we want to make sure the timer is no longer running
170     if (timeToNextService < 0) {
171         if (m_animationTimer.isActive())
172             m_animationTimer.stop();
173         return;
174     }
175
176     // Otherwise, we want to start a one-shot timer so we get here again
177     m_animationTimer.startOneShot(timeToNextService);
178 }
179
180 void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired()
181 {
182     fireEventsAndUpdateStyle();
183 }
184
185 void AnimationControllerPrivate::fireEventsAndUpdateStyle()
186 {
187     // Protect the frame from getting destroyed in the event handler
188     Ref<Frame> protector(m_frame);
189
190     bool updateStyle = !m_eventsToDispatch.isEmpty() || !m_elementChangesToDispatch.isEmpty();
191
192     // fire all the events
193     Vector<EventToDispatch> eventsToDispatch = WTF::move(m_eventsToDispatch);
194     Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = eventsToDispatch.end();
195     for (Vector<EventToDispatch>::const_iterator it = eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
196         Element* element = it->element.get();
197         if (it->eventType == eventNames().transitionendEvent)
198             element->dispatchEvent(TransitionEvent::create(it->eventType, it->name, it->elapsedTime, PseudoElement::pseudoElementNameForEvents(element->pseudoId())));
199         else
200             element->dispatchEvent(AnimationEvent::create(it->eventType, it->name, it->elapsedTime));
201     }
202
203     for (unsigned i = 0, size = m_elementChangesToDispatch.size(); i < size; ++i)
204         m_elementChangesToDispatch[i]->setNeedsStyleRecalc(SyntheticStyleChange);
205
206     m_elementChangesToDispatch.clear();
207
208     if (updateStyle)
209         m_frame.document()->updateStyleIfNeeded();
210 }
211
212 void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
213 {
214     if (!m_updateStyleIfNeededDispatcher.isActive())
215         m_updateStyleIfNeededDispatcher.startOneShot(0);
216 }
217
218 void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime)
219 {
220     m_eventsToDispatch.grow(m_eventsToDispatch.size()+1);
221     EventToDispatch& event = m_eventsToDispatch[m_eventsToDispatch.size()-1];
222     event.element = element;
223     event.eventType = eventType;
224     event.name = name;
225     event.elapsedTime = elapsedTime;
226     
227     startUpdateStyleIfNeededDispatcher();
228 }
229
230 void AnimationControllerPrivate::addElementChangeToDispatch(Ref<Element>&& element)
231 {
232     m_elementChangesToDispatch.append(WTF::move(element));
233     ASSERT(!m_elementChangesToDispatch.last()->document().inPageCache());
234     startUpdateStyleIfNeededDispatcher();
235 }
236
237 #if ENABLE(REQUEST_ANIMATION_FRAME)
238 void AnimationControllerPrivate::animationFrameCallbackFired()
239 {
240     double timeToNextService = updateAnimations(CallSetChanged);
241
242     if (timeToNextService >= 0)
243         m_frame.document()->view()->scheduleAnimation();
244 }
245 #endif
246
247 void AnimationControllerPrivate::animationTimerFired()
248 {
249     // We need to keep the frame alive, since it owns us.
250     Ref<Frame> protector(m_frame);
251
252     // Make sure animationUpdateTime is updated, so that it is current even if no
253     // styleChange has happened (e.g. accelerated animations)
254     AnimationPrivateUpdateBlock updateBlock(*this);
255
256     // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
257     // updateStyleIfNeeded.  It will then call back to us with new information.
258     updateAnimationTimer(CallSetChanged);
259
260     // Fire events right away, to avoid a flash of unanimated style after an animation completes, and before
261     // the 'end' event fires.
262     fireEventsAndUpdateStyle();
263 }
264
265 bool AnimationControllerPrivate::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
266 {
267     ASSERT(renderer.isCSSAnimating());
268     ASSERT(m_compositeAnimations.contains(&renderer));
269     const CompositeAnimation& animation = *m_compositeAnimations.get(&renderer);
270     return animation.isAnimatingProperty(property, false, runningState);
271 }
272
273 bool AnimationControllerPrivate::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
274 {
275     ASSERT(renderer.isCSSAnimating());
276     ASSERT(m_compositeAnimations.contains(&renderer));
277     const CompositeAnimation& animation = *m_compositeAnimations.get(&renderer);
278     return animation.isAnimatingProperty(property, true, runningState);
279 }
280
281 void AnimationControllerPrivate::suspendAnimations()
282 {
283     if (isSuspended())
284         return;
285
286     suspendAnimationsForDocument(m_frame.document());
287
288     // Traverse subframes
289     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
290         child->animation().suspendAnimations();
291
292     m_isSuspended = true;
293 }
294
295 void AnimationControllerPrivate::resumeAnimations()
296 {
297     if (!isSuspended())
298         return;
299
300     resumeAnimationsForDocument(m_frame.document());
301
302     // Traverse subframes
303     for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
304         child->animation().resumeAnimations();
305
306     m_isSuspended = false;
307 }
308
309 void AnimationControllerPrivate::suspendAnimationsForDocument(Document* document)
310 {
311     AnimationPrivateUpdateBlock updateBlock(*this);
312
313     for (auto it = m_compositeAnimations.begin(), end = m_compositeAnimations.end(); it != end; ++it) {
314         if (&it->key->document() == document)
315             it->value->suspendAnimations();
316     }
317
318     updateAnimationTimer();
319 }
320
321 void AnimationControllerPrivate::resumeAnimationsForDocument(Document* document)
322 {
323     AnimationPrivateUpdateBlock updateBlock(*this);
324
325     for (auto it = m_compositeAnimations.begin(), end = m_compositeAnimations.end(); it != end; ++it) {
326         if (&it->key->document() == document)
327             it->value->resumeAnimations();
328     }
329
330     updateAnimationTimer();
331 }
332
333 void AnimationControllerPrivate::startAnimationsIfNotSuspended(Document* document)
334 {
335     if (!isSuspended() || allowsNewAnimationsWhileSuspended())
336         resumeAnimationsForDocument(document);
337 }
338
339 void AnimationControllerPrivate::setAllowsNewAnimationsWhileSuspended(bool allowed)
340 {
341     m_allowsNewAnimationsWhileSuspended = allowed;
342 }
343
344 bool AnimationControllerPrivate::pauseAnimationAtTime(RenderElement* renderer, const AtomicString& name, double t)
345 {
346     if (!renderer)
347         return false;
348
349     CompositeAnimation& compositeAnimation = ensureCompositeAnimation(*renderer);
350     if (compositeAnimation.pauseAnimationAtTime(name, t)) {
351         renderer->element()->setNeedsStyleRecalc(SyntheticStyleChange);
352         startUpdateStyleIfNeededDispatcher();
353         return true;
354     }
355
356     return false;
357 }
358
359 bool AnimationControllerPrivate::pauseTransitionAtTime(RenderElement* renderer, const String& property, double t)
360 {
361     if (!renderer)
362         return false;
363
364     CompositeAnimation& compositeAnimation = ensureCompositeAnimation(*renderer);
365     if (compositeAnimation.pauseTransitionAtTime(cssPropertyID(property), t)) {
366         renderer->element()->setNeedsStyleRecalc(SyntheticStyleChange);
367         startUpdateStyleIfNeededDispatcher();
368         return true;
369     }
370
371     return false;
372 }
373
374 double AnimationControllerPrivate::beginAnimationUpdateTime()
375 {
376     ASSERT(m_beginAnimationUpdateCount);
377     if (m_beginAnimationUpdateTime == cBeginAnimationUpdateTimeNotSet)
378         m_beginAnimationUpdateTime = monotonicallyIncreasingTime();
379
380     return m_beginAnimationUpdateTime;
381 }
382
383 void AnimationControllerPrivate::beginAnimationUpdate()
384 {
385     if (!m_beginAnimationUpdateCount)
386         setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
387     ++m_beginAnimationUpdateCount;
388 }
389
390 void AnimationControllerPrivate::endAnimationUpdate()
391 {
392     ASSERT(m_beginAnimationUpdateCount > 0);
393     if (m_beginAnimationUpdateCount == 1) {
394         styleAvailable();
395         if (!m_waitingForAsyncStartNotification)
396             startTimeResponse(beginAnimationUpdateTime());
397     }
398     --m_beginAnimationUpdateCount;
399 }
400
401 void AnimationControllerPrivate::receivedStartTimeResponse(double time)
402 {
403     m_waitingForAsyncStartNotification = false;
404     startTimeResponse(time);
405 }
406
407 PassRefPtr<RenderStyle> AnimationControllerPrivate::getAnimatedStyleForRenderer(RenderElement& renderer)
408 {
409     AnimationPrivateUpdateBlock animationUpdateBlock(*this);
410
411     ASSERT(renderer.isCSSAnimating());
412     ASSERT(m_compositeAnimations.contains(&renderer));
413     const CompositeAnimation& rendererAnimations = *m_compositeAnimations.get(&renderer);
414     RefPtr<RenderStyle> animatingStyle = rendererAnimations.getAnimatedStyle();
415     if (!animatingStyle)
416         animatingStyle = &renderer.style();
417     
418     return animatingStyle.release();
419 }
420
421 bool AnimationControllerPrivate::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const
422 {
423     ASSERT(renderer.isCSSAnimating());
424     ASSERT(m_compositeAnimations.contains(&renderer));
425
426     const CompositeAnimation& rendererAnimations = *m_compositeAnimations.get(&renderer);
427     if (!rendererAnimations.isAnimatingProperty(CSSPropertyWebkitTransform, false, AnimationBase::Running | AnimationBase::Paused))
428         return true;
429
430     return rendererAnimations.computeExtentOfTransformAnimation(bounds);
431 }
432
433 unsigned AnimationControllerPrivate::numberOfActiveAnimations(Document* document) const
434 {
435     unsigned count = 0;
436     
437     for (auto it = m_compositeAnimations.begin(), end = m_compositeAnimations.end(); it != end; ++it) {
438         if (&it->key->document() == document)
439             count += it->value->numberOfActiveAnimations();
440     }
441
442     return count;
443 }
444
445 void AnimationControllerPrivate::addToAnimationsWaitingForStyle(AnimationBase* animation)
446 {
447     // Make sure this animation is not in the start time waiters
448     m_animationsWaitingForStartTimeResponse.remove(animation);
449
450     m_animationsWaitingForStyle.add(animation);
451 }
452
453 void AnimationControllerPrivate::removeFromAnimationsWaitingForStyle(AnimationBase* animationToRemove)
454 {
455     m_animationsWaitingForStyle.remove(animationToRemove);
456 }
457
458 void AnimationControllerPrivate::styleAvailable()
459 {
460     // Go through list of waiters and send them on their way
461     for (const auto& waitingAnimation : m_animationsWaitingForStyle)
462         waitingAnimation->styleAvailable();
463
464     m_animationsWaitingForStyle.clear();
465 }
466
467 void AnimationControllerPrivate::addToAnimationsWaitingForStartTimeResponse(AnimationBase* animation, bool willGetResponse)
468 {
469     // If willGetResponse is true, it means this animation is actually waiting for a response
470     // (which will come in as a call to notifyAnimationStarted()).
471     // In that case we don't need to add it to this list. We just set a waitingForAResponse flag 
472     // which says we are waiting for the response. If willGetResponse is false, this animation 
473     // is not waiting for a response for itself, but rather for a notifyXXXStarted() call for 
474     // another animation to which it will sync.
475     //
476     // When endAnimationUpdate() is called we check to see if the waitingForAResponse flag is
477     // true. If so, we just return and will do our work when the first notifyXXXStarted() call
478     // comes in. If it is false, we will not be getting a notifyXXXStarted() call, so we will
479     // do our work right away. In both cases we call the onAnimationStartResponse() method
480     // on each animation. In the first case we send in the time we got from notifyXXXStarted().
481     // In the second case, we just pass in the beginAnimationUpdateTime().
482     //
483     // This will synchronize all software and accelerated animations started in the same 
484     // updateStyleIfNeeded cycle.
485     //
486     
487     if (willGetResponse)
488         m_waitingForAsyncStartNotification = true;
489     
490     m_animationsWaitingForStartTimeResponse.add(animation);
491 }
492
493 void AnimationControllerPrivate::removeFromAnimationsWaitingForStartTimeResponse(AnimationBase* animationToRemove)
494 {
495     m_animationsWaitingForStartTimeResponse.remove(animationToRemove);
496     
497     if (m_animationsWaitingForStartTimeResponse.isEmpty())
498         m_waitingForAsyncStartNotification = false;
499 }
500
501 void AnimationControllerPrivate::startTimeResponse(double time)
502 {
503     // Go through list of waiters and send them on their way
504
505     for (const auto& animation : m_animationsWaitingForStartTimeResponse)
506         animation->onAnimationStartResponse(time);
507     
508     m_animationsWaitingForStartTimeResponse.clear();
509     m_waitingForAsyncStartNotification = false;
510 }
511
512 void AnimationControllerPrivate::animationWillBeRemoved(AnimationBase* animation)
513 {
514     removeFromAnimationsWaitingForStyle(animation);
515     removeFromAnimationsWaitingForStartTimeResponse(animation);
516 }
517
518 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
519 void AnimationControllerPrivate::scrollWasUpdated()
520 {
521     updateAnimations(CallSetChanged);
522 }
523 #endif
524
525 AnimationController::AnimationController(Frame& frame)
526     : m_data(std::make_unique<AnimationControllerPrivate>(frame))
527 {
528 }
529
530 AnimationController::~AnimationController()
531 {
532 }
533
534 void AnimationController::cancelAnimations(RenderElement& renderer)
535 {
536     if (!renderer.isCSSAnimating())
537         return;
538
539     if (!m_data->clear(renderer))
540         return;
541
542     Element* element = renderer.element();
543     ASSERT(!element || !element->document().inPageCache());
544     if (element)
545         element->setNeedsStyleRecalc(SyntheticStyleChange);
546 }
547
548 Ref<RenderStyle> AnimationController::updateAnimations(RenderElement& renderer, Ref<RenderStyle>&& newStyle)
549 {
550     // Don't do anything if we're in the cache
551     if (renderer.document().inPageCache())
552         return WTF::move(newStyle);
553
554     RenderStyle* oldStyle = renderer.hasInitializedStyle() ? &renderer.style() : nullptr;
555
556     if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle.get().animations() && !newStyle.get().transitions()))
557         return WTF::move(newStyle);
558
559     // Don't run transitions when printing.
560     if (renderer.view().printing())
561         return WTF::move(newStyle);
562
563     // Fetch our current set of implicit animations from a hashtable.  We then compare them
564     // against the animations in the style and make sure we're in sync.  If destination values
565     // have changed, we reset the animation.  We then do a blend to get new values and we return
566     // a new style.
567
568     // We don't support anonymous pseudo elements like :first-line or :first-letter.
569     ASSERT(renderer.element());
570
571     Ref<RenderStyle> newStyleBeforeAnimation(WTF::move(newStyle));
572
573     CompositeAnimation& rendererAnimations = m_data->ensureCompositeAnimation(renderer);
574     auto blendedStyle = rendererAnimations.animate(renderer, oldStyle, newStyleBeforeAnimation);
575
576     if (renderer.parent() || newStyleBeforeAnimation->animations() || (oldStyle && oldStyle->animations())) {
577         m_data->updateAnimationTimerForRenderer(renderer);
578 #if ENABLE(REQUEST_ANIMATION_FRAME)
579         renderer.view().frameView().scheduleAnimation();
580 #endif
581     }
582
583     if (blendedStyle.ptr() != newStyleBeforeAnimation.ptr()) {
584         // If the animations/transitions change opacity or transform, we need to update
585         // the style to impose the stacking rules. Note that this is also
586         // done in StyleResolver::adjustRenderStyle().
587         if (blendedStyle.get().hasAutoZIndex() && (blendedStyle.get().opacity() < 1.0f || blendedStyle.get().hasTransform()))
588             blendedStyle.get().setZIndex(0);
589     }
590     return blendedStyle;
591 }
592
593 PassRefPtr<RenderStyle> AnimationController::getAnimatedStyleForRenderer(RenderElement& renderer)
594 {
595     if (!renderer.isCSSAnimating())
596         return &renderer.style();
597     return m_data->getAnimatedStyleForRenderer(renderer);
598 }
599
600 bool AnimationController::computeExtentOfAnimation(RenderElement& renderer, LayoutRect& bounds) const
601 {
602     if (!renderer.isCSSAnimating())
603         return true;
604
605     return m_data->computeExtentOfAnimation(renderer, bounds);
606 }
607
608 void AnimationController::notifyAnimationStarted(RenderElement&, double startTime)
609 {
610     AnimationUpdateBlock animationUpdateBlock(this);
611     m_data->receivedStartTimeResponse(startTime);
612 }
613
614 bool AnimationController::pauseAnimationAtTime(RenderElement* renderer, const AtomicString& name, double t)
615 {
616     AnimationUpdateBlock animationUpdateBlock(this);
617     return m_data->pauseAnimationAtTime(renderer, name, t);
618 }
619
620 unsigned AnimationController::numberOfActiveAnimations(Document* document) const
621 {
622     return m_data->numberOfActiveAnimations(document);
623 }
624
625 bool AnimationController::pauseTransitionAtTime(RenderElement* renderer, const String& property, double t)
626 {
627     AnimationUpdateBlock animationUpdateBlock(this);
628     return m_data->pauseTransitionAtTime(renderer, property, t);
629 }
630
631 bool AnimationController::isRunningAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
632 {
633     return renderer.isCSSAnimating() && m_data->isRunningAnimationOnRenderer(renderer, property, runningState);
634 }
635
636 bool AnimationController::isRunningAcceleratedAnimationOnRenderer(RenderElement& renderer, CSSPropertyID property, AnimationBase::RunningState runningState) const
637 {
638     return renderer.isCSSAnimating() && m_data->isRunningAcceleratedAnimationOnRenderer(renderer, property, runningState);
639 }
640
641 bool AnimationController::isSuspended() const
642 {
643     return m_data->isSuspended();
644 }
645
646 void AnimationController::suspendAnimations()
647 {
648     LOG(Animations, "controller is suspending animations");
649     m_data->suspendAnimations();
650 }
651
652 void AnimationController::resumeAnimations()
653 {
654     LOG(Animations, "controller is resuming animations");
655     m_data->resumeAnimations();
656 }
657
658 bool AnimationController::allowsNewAnimationsWhileSuspended() const
659 {
660     return m_data->allowsNewAnimationsWhileSuspended();
661 }
662
663 void AnimationController::setAllowsNewAnimationsWhileSuspended(bool allowed)
664 {
665     m_data->setAllowsNewAnimationsWhileSuspended(allowed);
666 }
667
668 #if ENABLE(REQUEST_ANIMATION_FRAME)
669 void AnimationController::serviceAnimations()
670 {
671     m_data->animationFrameCallbackFired();
672 }
673 #endif
674
675 void AnimationController::suspendAnimationsForDocument(Document* document)
676 {
677     LOG(Animations, "suspending animations for document %p", document);
678     m_data->suspendAnimationsForDocument(document);
679 }
680
681 void AnimationController::resumeAnimationsForDocument(Document* document)
682 {
683     LOG(Animations, "resuming animations for document %p", document);
684     AnimationUpdateBlock animationUpdateBlock(this);
685     m_data->resumeAnimationsForDocument(document);
686 }
687
688 void AnimationController::startAnimationsIfNotSuspended(Document* document)
689 {
690     LOG(Animations, "animations may start for document %p", document);
691
692     AnimationUpdateBlock animationUpdateBlock(this);
693     m_data->startAnimationsIfNotSuspended(document);
694 }
695
696 void AnimationController::beginAnimationUpdate()
697 {
698     m_data->beginAnimationUpdate();
699 }
700
701 void AnimationController::endAnimationUpdate()
702 {
703     m_data->endAnimationUpdate();
704 }
705
706 bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
707 {
708     return CSSPropertyAnimation::animationOfPropertyIsAccelerated(property);
709 }
710
711 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
712 void AnimationController::scrollWasUpdated()
713 {
714     m_data->scrollWasUpdated();
715 }
716 #endif
717
718 } // namespace WebCore