summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp')
-rw-r--r--src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp379
1 files changed, 239 insertions, 140 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp
index 3b6cfcc..58a1f5b 100644
--- a/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp
+++ b/src/3rdparty/webkit/WebCore/page/animation/AnimationController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,81 +28,32 @@
#include "config.h"
#include "AnimationController.h"
-#include "CompositeAnimation.h"
+
+#include "AnimationBase.h"
+#include "AnimationControllerPrivate.h"
#include "CSSParser.h"
+#include "CompositeAnimation.h"
#include "EventNames.h"
#include "Frame.h"
-#include "SystemTime.h"
-#include "Timer.h"
+#include "RenderView.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);
-
- 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; }
-
-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;
-
- double m_beginAnimationUpdateTime;
-};
-
AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
: m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired)
- , m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired)
+ , m_updateStyleIfNeededDispatcher(this, &AnimationControllerPrivate::updateStyleIfNeededDispatcherFired)
, m_frame(frame)
, m_beginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet)
+ , m_styleAvailableWaiters(0)
+ , m_lastStyleAvailableWaiter(0)
+ , m_responseWaiters(0)
+ , m_lastResponseWaiter(0)
+ , m_waitingForAResponse(false)
{
}
@@ -114,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;
@@ -123,7 +74,7 @@ PassRefPtr<CompositeAnimation> AnimationControllerPrivate::accessCompositeAnimat
bool AnimationControllerPrivate::clear(RenderObject* renderer)
{
// Return false if we didn't do anything OR we are suspended (so we don't try to
- // do a setChanged() when suspended).
+ // do a setNeedsStyleRecalc() when suspended).
PassRefPtr<CompositeAnimation> animation = m_compositeAnimations.take(renderer);
if (!animation)
return false;
@@ -131,23 +82,6 @@ bool AnimationControllerPrivate::clear(RenderObject* renderer)
return animation->isSuspended();
}
-void AnimationControllerPrivate::styleAvailable()
-{
- // styleAvailable() can call event handlers which would ultimately delete a CompositeAnimation
- // from the m_compositeAnimations table. So we can't iterate it directly. We will instead build
- // a list of CompositeAnimations which need the styleAvailable() call iterate over that.
- Vector<RefPtr<CompositeAnimation> > list;
-
- RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
- for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it)
- if (it->second->isWaitingForStyleAvailable())
- list.append(it->second);
-
- Vector<RefPtr<CompositeAnimation> >::const_iterator listEnd = list.end();
- for (Vector<RefPtr<CompositeAnimation> >::const_iterator it = list.begin(); it != listEnd; ++it)
- (*it)->styleAvailable();
-}
-
void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = false*/)
{
double needsService = -1;
@@ -155,16 +89,16 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa
RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
- RefPtr<CompositeAnimation> compAnim = it->second;
- if (!compAnim->isSuspended()) {
- double t = compAnim->willNeedService();
+ CompositeAnimation* compAnim = it->second.get();
+ if (!compAnim->isSuspended() && compAnim->hasAnimations()) {
+ double t = compAnim->timeToNextService();
if (t != -1 && (t < needsService || needsService == -1))
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);
+ node->setNeedsStyleRecalc(AnimationStyleChange);
calledSetChanged = true;
}
else
@@ -174,7 +108,7 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa
}
if (calledSetChanged)
- m_frame->document()->updateRendering();
+ m_frame->document()->updateStyleIfNeeded();
// If we want service immediately, we start a repeating timer to reduce the overhead of starting
if (needsService == 0) {
@@ -196,11 +130,11 @@ void AnimationControllerPrivate::updateAnimationTimer(bool callSetChanged/* = fa
m_animationTimer.startOneShot(needsService);
}
-void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*)
+void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<AnimationControllerPrivate>*)
{
// fire all the events
- Vector<EventToDispatch>::const_iterator end = m_eventsToDispatch.end();
- for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != end; ++it) {
+ Vector<EventToDispatch>::const_iterator eventsToDispatchEnd = m_eventsToDispatch.end();
+ for (Vector<EventToDispatch>::const_iterator it = m_eventsToDispatch.begin(); it != eventsToDispatchEnd; ++it) {
if (it->eventType == eventNames().webkitTransitionEndEvent)
it->element->dispatchWebKitTransitionEvent(it->eventType,it->name, it->elapsedTime);
else
@@ -209,14 +143,35 @@ void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationC
m_eventsToDispatch.clear();
- if (m_frame && m_frame->document())
- m_frame->document()->updateRendering();
+ // call setChanged on all the elements
+ Vector<RefPtr<Node> >::const_iterator nodeChangesToDispatchEnd = m_nodeChangesToDispatch.end();
+ for (Vector<RefPtr<Node> >::const_iterator it = m_nodeChangesToDispatch.begin(); it != nodeChangesToDispatchEnd; ++it)
+ (*it)->setNeedsStyleRecalc(AnimationStyleChange);
+
+ m_nodeChangesToDispatch.clear();
+
+ if (m_frame)
+ m_frame->document()->updateStyleIfNeeded();
+
+ // We can now safely remove any animations or transitions that are finished.
+ // We can't remove them any earlier because we might get a false restart of
+ // a transition. This can happen because we have not yet set the final property
+ // value until we call the rendering dispatcher. So this can make the current
+ // style slightly different from the desired final style (because our last
+ // animation step was, say 0.9999 or something). And we need to remove them
+ // here because if there are no more animations running we'll never get back
+ // into the animation code to clean them up.
+ RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
+ for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
+ CompositeAnimation* compAnim = it->second.get();
+ compAnim->cleanupFinishedAnimations(); // will not modify m_compositeAnimations, so OK to call while iterating
+ }
}
-void AnimationControllerPrivate::startUpdateRenderingDispatcher()
+void AnimationControllerPrivate::startUpdateStyleIfNeededDispatcher()
{
- if (!m_updateRenderingDispatcher.isActive())
- m_updateRenderingDispatcher.startOneShot(0);
+ if (!m_updateStyleIfNeededDispatcher.isActive())
+ m_updateStyleIfNeededDispatcher.startOneShot(0);
}
void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element, const AtomicString& eventType, const String& name, double elapsedTime)
@@ -228,21 +183,31 @@ void AnimationControllerPrivate::addEventToDispatch(PassRefPtr<Element> element,
event.name = name;
event.elapsedTime = elapsedTime;
- startUpdateRenderingDispatcher();
+ startUpdateStyleIfNeededDispatcher();
+}
+
+void AnimationControllerPrivate::addNodeChangeToDispatch(PassRefPtr<Node> node)
+{
+ ASSERT(!node || (node->document() && !node->document()->inPageCache()));
+ if (!node)
+ return;
+
+ m_nodeChangesToDispatch.append(node);
+ startUpdateStyleIfNeededDispatcher();
}
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
- // updateRendering. It will then call back to us with new information.
+ // updateStyleIfNeeded. It will then call back to us with new information.
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)
@@ -253,12 +218,15 @@ bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* ren
void AnimationControllerPrivate::suspendAnimations(Document* document)
{
+ setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
+
RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
RenderObject* renderer = it->first;
- RefPtr<CompositeAnimation> compAnim = it->second;
- if (renderer->document() == document)
+ if (renderer->document() == document) {
+ CompositeAnimation* compAnim = it->second.get();
compAnim->suspendAnimations();
+ }
}
updateAnimationTimer();
@@ -266,12 +234,15 @@ void AnimationControllerPrivate::suspendAnimations(Document* document)
void AnimationControllerPrivate::resumeAnimations(Document* document)
{
+ setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
+
RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end();
for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) {
RenderObject* renderer = it->first;
- RefPtr<CompositeAnimation> compAnim = it->second;
- if (renderer->document() == document)
+ if (renderer->document() == document) {
+ CompositeAnimation* compAnim = it->second.get();
compAnim->resumeAnimations();
+ }
}
updateAnimationTimer();
@@ -287,7 +258,8 @@ bool AnimationControllerPrivate::pauseAnimationAtTime(RenderObject* renderer, co
return false;
if (compAnim->pauseAnimationAtTime(name, t)) {
- renderer->node()->setChanged(AnimationStyleChange);
+ renderer->node()->setNeedsStyleRecalc(AnimationStyleChange);
+ startUpdateStyleIfNeededDispatcher();
return true;
}
@@ -304,13 +276,40 @@ bool AnimationControllerPrivate::pauseTransitionAtTime(RenderObject* renderer, c
return false;
if (compAnim->pauseTransitionAtTime(cssPropertyID(property), t)) {
- renderer->node()->setChanged(AnimationStyleChange);
+ renderer->node()->setNeedsStyleRecalc(AnimationStyleChange);
+ startUpdateStyleIfNeededDispatcher();
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;
@@ -324,9 +323,119 @@ unsigned AnimationControllerPrivate::numberOfActiveAnimations() const
return count;
}
+void AnimationControllerPrivate::addToStyleAvailableWaitList(AnimationBase* animation)
+{
+ ASSERT(!animation->next());
+
+ if (m_styleAvailableWaiters)
+ m_lastStyleAvailableWaiter->setNext(animation);
+ else
+ m_styleAvailableWaiters = animation;
+
+ m_lastStyleAvailableWaiter = animation;
+ animation->setNext(0);
+}
+
+void AnimationControllerPrivate::removeFromStyleAvailableWaitList(AnimationBase* animationToRemove)
+{
+ AnimationBase* prevAnimation = 0;
+ for (AnimationBase* animation = m_styleAvailableWaiters; animation; animation = animation->next()) {
+ if (animation == animationToRemove) {
+ if (prevAnimation)
+ prevAnimation->setNext(animation->next());
+ else
+ m_styleAvailableWaiters = animation->next();
+
+ if (m_lastStyleAvailableWaiter == animation)
+ m_lastStyleAvailableWaiter = prevAnimation;
+
+ animationToRemove->setNext(0);
+ }
+ }
+}
+
+void AnimationControllerPrivate::styleAvailable()
+{
+ // Go through list of waiters and send them on their way
+ 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
+ // updateStyleIfNeeded 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))
- , m_numStyleAvailableWaiters(0)
{
}
@@ -341,9 +450,9 @@ 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);
+ node->setNeedsStyleRecalc(AnimationStyleChange);
}
}
@@ -358,11 +467,15 @@ PassRefPtr<RenderStyle> AnimationController::updateAnimations(RenderObject* rend
if ((!oldStyle || (!oldStyle->animations() && !oldStyle->transitions())) && (!newStyle->animations() && !newStyle->transitions()))
return newStyle;
+ // Don't run transitions when printing.
+ if (renderer->view()->printing())
+ return newStyle;
+
// Fetch our current set of implicit animations from a hashtable. We then compare them
// 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);
@@ -379,16 +492,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)
@@ -406,7 +517,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);
}
@@ -421,29 +532,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::styleAvailable()
-{
- if (!m_numStyleAvailableWaiters)
- return;
-
- m_data->styleAvailable();
-}
-
-double AnimationController::beginAnimationUpdateTime()
-{
- return m_data->beginAnimationUpdateTime();
-}
-
void AnimationController::beginAnimationUpdate()
{
m_data->setBeginAnimationUpdateTime(cBeginAnimationUpdateTimeNotSet);
@@ -451,6 +539,17 @@ void AnimationController::beginAnimationUpdate()
void AnimationController::endAnimationUpdate()
{
+ m_data->endAnimationUpdate();
+}
+
+bool AnimationController::supportsAcceleratedAnimationOfProperty(CSSPropertyID property)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ return AnimationBase::animationOfPropertyIsAccelerated(property);
+#else
+ UNUSED_PARAM(property);
+ return false;
+#endif
}
} // namespace WebCore