summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp')
-rw-r--r--src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp190
1 files changed, 140 insertions, 50 deletions
diff --git a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp
index aae37a7..3f84de1 100644
--- a/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp
+++ b/src/3rdparty/webkit/WebCore/page/animation/KeyframeAnimation.cpp
@@ -29,13 +29,14 @@
#include "config.h"
#include "KeyframeAnimation.h"
-#include "AnimationController.h"
+#include "AnimationControllerPrivate.h"
#include "CSSPropertyNames.h"
#include "CSSStyleSelector.h"
#include "CompositeAnimation.h"
#include "EventNames.h"
-#include "RenderObject.h"
-#include "SystemTime.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -46,8 +47,8 @@ KeyframeAnimation::KeyframeAnimation(const Animation* animation, RenderObject* r
, m_unanimatedStyle(unanimatedStyle)
{
// Get the keyframe RenderStyles
- if (m_object && m_object->element() && m_object->element()->isElementNode())
- m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->element()), unanimatedStyle, m_keyframes);
+ if (m_object && m_object->node() && m_object->node()->isElementNode())
+ m_object->document()->styleSelector()->keyframeStylesForAnimation(static_cast<Element*>(m_object->node()), unanimatedStyle, m_keyframes);
// Update the m_transformFunctionListValid flag based on whether the function lists in the keyframes match.
validateTransformFunctionList();
@@ -55,12 +56,50 @@ KeyframeAnimation::KeyframeAnimation(const Animation* animation, RenderObject* r
KeyframeAnimation::~KeyframeAnimation()
{
- // Do the cleanup here instead of in the base class so the specialized methods get called
+ // Make sure to tell the renderer that we are ending. This will make sure any accelerated animations are removed.
if (!postActive())
- updateStateMachine(AnimationStateInputEndAnimation, -1);
+ endAnimation(true);
+}
+
+void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const
+{
+ // Find the first key
+ double elapsedTime = getElapsedTime();
+
+ double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1;
+ int i = static_cast<int>(t);
+ t -= i;
+ if (m_animation->direction() && (i & 1))
+ t = 1 - t;
+
+ double scale = 1;
+ double offset = 0;
+ Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes();
+ for (Vector<KeyframeValue>::const_iterator it = m_keyframes.beginKeyframes(); it != endKeyframes; ++it) {
+ if (t < it->key()) {
+ // The first key should always be 0, so we should never succeed on the first key
+ if (!fromStyle)
+ break;
+ scale = 1.0 / (it->key() - offset);
+ toStyle = it->style();
+ break;
+ }
+
+ offset = it->key();
+ fromStyle = it->style();
+ }
+
+ if (!fromStyle || !toStyle)
+ return;
+
+ const TimingFunction* timingFunction = 0;
+ if (fromStyle->animations() && fromStyle->animations()->size() > 0)
+ timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
+
+ prog = progress(scale, offset, timingFunction);
}
-void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
{
// Fire the start timeout if needed
fireAnimationEventsIfNeeded();
@@ -85,36 +124,12 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
// FIXME: we need to be more efficient about determining which keyframes we are animating between.
// We should cache the last pair or something.
-
- // Find the first key
- double elapsedTime = (m_startTime > 0 || m_pauseTime > 0) ? ((!paused() ? beginAnimationUpdateTime() : m_pauseTime) - m_startTime) : 0;
- if (elapsedTime < 0)
- elapsedTime = 0;
-
- double t = m_animation->duration() ? (elapsedTime / m_animation->duration()) : 1;
- int i = static_cast<int>(t);
- t -= i;
- if (m_animation->direction() && (i & 1))
- t = 1 - t;
-
+
+ // Get the from/to styles and progress between
const RenderStyle* fromStyle = 0;
const RenderStyle* toStyle = 0;
- double scale = 1;
- double offset = 0;
- Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes();
- for (Vector<KeyframeValue>::const_iterator it = m_keyframes.beginKeyframes(); it != endKeyframes; ++it) {
- if (t < it->key()) {
- // The first key should always be 0, so we should never succeed on the first key
- if (!fromStyle)
- break;
- scale = 1.0 / (it->key() - offset);
- toStyle = it->style();
- break;
- }
-
- offset = it->key();
- fromStyle = it->style();
- }
+ double progress;
+ getKeyframeAnimationInterval(fromStyle, toStyle, progress);
// If either style is 0 we have an invalid case, just stop the animation.
if (!fromStyle || !toStyle) {
@@ -127,19 +142,42 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
if (!animatedStyle)
animatedStyle = RenderStyle::clone(targetStyle);
- const TimingFunction* timingFunction = 0;
- if (fromStyle->animations() && fromStyle->animations()->size() > 0)
- timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
-
- double prog = progress(scale, offset, timingFunction);
-
HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
- if (blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, prog))
+ bool needsAnim = blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
+ if (needsAnim)
setAnimating();
+ else {
+#if USE(ACCELERATED_COMPOSITING)
+ // If we are running an accelerated animation, set a flag in the style
+ // to indicate it. This can be used to make sure we get an updated
+ // style for hit testing, etc.
+ animatedStyle->setIsRunningAcceleratedAnimation();
+#endif
+ }
}
}
+void KeyframeAnimation::getAnimatedStyle(RefPtr<RenderStyle>& animatedStyle)
+{
+ // Get the from/to styles and progress between
+ const RenderStyle* fromStyle = 0;
+ const RenderStyle* toStyle = 0;
+ double progress;
+ getKeyframeAnimationInterval(fromStyle, toStyle, progress);
+
+ // If either style is 0 we have an invalid case
+ if (!fromStyle || !toStyle)
+ return;
+
+ if (!animatedStyle)
+ animatedStyle = RenderStyle::clone(m_object->style());
+
+ HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
+ for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it)
+ blendProperties(this, *it, animatedStyle.get(), fromStyle, toStyle, progress);
+}
+
bool KeyframeAnimation::hasAnimationForProperty(int property) const
{
HashSet<int>::const_iterator end = m_keyframes.endProperties();
@@ -151,14 +189,39 @@ bool KeyframeAnimation::hasAnimationForProperty(int property) const
return false;
}
-void KeyframeAnimation::endAnimation(bool)
+bool KeyframeAnimation::startAnimation(double beginTime)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ return layer->backing()->startAnimation(beginTime, m_animation.get(), m_keyframes);
+ }
+#else
+ UNUSED_PARAM(beginTime);
+#endif
+ return false;
+}
+
+void KeyframeAnimation::endAnimation(bool reset)
{
- // Restore the original (unanimated) style
- if (m_object)
- setChanged(m_object->element());
+ if (m_object) {
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ layer->backing()->animationFinished(m_keyframes.animationName(), 0, reset);
+ }
+#else
+ UNUSED_PARAM(reset);
+#endif
+ // Restore the original (unanimated) style
+ if (!paused())
+ setNeedsStyleRecalc(m_object->node());
+ }
}
-bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType)
+bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const
{
return m_object->document()->hasListenerType(listenerType);
}
@@ -204,11 +267,11 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double
return false;
// Schedule event handling
- m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
+ m_compAnim->animationController()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
// Restore the original (unanimated) style
if (eventType == eventNames().webkitAnimationEndEvent && element->renderer())
- setChanged(element.get());
+ setNeedsStyleRecalc(element.get());
return true; // Did dispatch an event
}
@@ -290,4 +353,31 @@ void KeyframeAnimation::validateTransformFunctionList()
m_transformFunctionListValid = true;
}
+double KeyframeAnimation::timeToNextService()
+{
+ double t = AnimationBase::timeToNextService();
+#if USE(ACCELERATED_COMPOSITING)
+ if (t != 0 || preActive())
+ return t;
+
+ // A return value of 0 means we need service. But if we only have accelerated animations we
+ // only need service at the end of the transition
+ HashSet<int>::const_iterator endProperties = m_keyframes.endProperties();
+ bool acceleratedPropertiesOnly = true;
+
+ for (HashSet<int>::const_iterator it = m_keyframes.beginProperties(); it != endProperties; ++it) {
+ if (!animationOfPropertyIsAccelerated(*it) || isFallbackAnimating()) {
+ acceleratedPropertiesOnly = false;
+ break;
+ }
+ }
+
+ if (acceleratedPropertiesOnly) {
+ bool isLooping;
+ getTimeToNextEvent(t, isLooping);
+ }
+#endif
+ return t;
+}
+
} // namespace WebCore