summaryrefslogtreecommitdiffstats
path: root/WebCore/page/animation/KeyframeAnimation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/page/animation/KeyframeAnimation.cpp')
-rw-r--r--WebCore/page/animation/KeyframeAnimation.cpp180
1 files changed, 136 insertions, 44 deletions
diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp
index 2efa578..88a5f6a 100644
--- a/WebCore/page/animation/KeyframeAnimation.cpp
+++ b/WebCore/page/animation/KeyframeAnimation.cpp
@@ -29,12 +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 "RenderLayer.h"
+#include "RenderLayerBacking.h"
+#include <wtf/UnusedParam.h>
namespace WebCore {
@@ -45,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();
@@ -59,32 +61,8 @@ KeyframeAnimation::~KeyframeAnimation()
updateStateMachine(AnimationStateInputEndAnimation, -1);
}
-void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const RenderStyle*, const RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromStyle, const RenderStyle*& toStyle, double& prog) const
{
- // Fire the start timeout if needed
- fireAnimationEventsIfNeeded();
-
- // If we have not yet started, we will not have a valid start time, so just start the animation if needed.
- if (isNew() && m_animation->playState() == AnimPlayStatePlaying)
- updateStateMachine(AnimationStateInputStartAnimation, -1);
-
- // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
- // If so, we need to send back the targetStyle.
- if (postActive()) {
- if (!animatedStyle)
- animatedStyle = const_cast<RenderStyle*>(targetStyle);
- return;
- }
-
- // If we are waiting for the start timer, we don't want to change the style yet.
- // Special case - if the delay time is 0, then we do want to set the first frame of the
- // animation right away. This avoids a flash when the animation starts.
- if (waitingToStart() && m_animation->delay() > 0)
- return;
-
- // 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 = getElapsedTime();
@@ -94,8 +72,6 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
if (m_animation->direction() && (i & 1))
t = 1 - t;
- const RenderStyle* fromStyle = 0;
- const RenderStyle* toStyle = 0;
double scale = 1;
double offset = 0;
Vector<KeyframeValue>::const_iterator endKeyframes = m_keyframes.endKeyframes();
@@ -113,6 +89,48 @@ void KeyframeAnimation::animate(CompositeAnimation*, RenderObject*, const Render
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*, RenderStyle* targetStyle, RefPtr<RenderStyle>& animatedStyle)
+{
+ // Fire the start timeout if needed
+ fireAnimationEventsIfNeeded();
+
+ // If we have not yet started, we will not have a valid start time, so just start the animation if needed.
+ if (isNew() && m_animation->playState() == AnimPlayStatePlaying)
+ updateStateMachine(AnimationStateInputStartAnimation, -1);
+
+ // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
+ // If so, we need to send back the targetStyle.
+ if (postActive()) {
+ if (!animatedStyle)
+ animatedStyle = const_cast<RenderStyle*>(targetStyle);
+ return;
+ }
+
+ // If we are waiting for the start timer, we don't want to change the style yet.
+ // Special case - if the delay time is 0, then we do want to set the first frame of the
+ // animation right away. This avoids a flash when the animation starts.
+ if (waitingToStart() && m_animation->delay() > 0)
+ return;
+
+ // FIXME: we need to be more efficient about determining which keyframes we are animating between.
+ // We should cache the last pair or something.
+
+ // 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, just stop the animation.
if (!fromStyle || !toStyle) {
updateStateMachine(AnimationStateInputEndAnimation, -1);
@@ -124,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();
@@ -148,14 +189,38 @@ 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
+ setChanged(m_object->node());
+ }
}
-bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType)
+bool KeyframeAnimation::shouldSendEventForListener(Document::ListenerType listenerType) const
{
return m_object->document()->hasListenerType(listenerType);
}
@@ -201,7 +266,7 @@ bool KeyframeAnimation::sendAnimationEvent(const AtomicString& eventType, double
return false;
// Schedule event handling
- m_object->animation()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
+ m_compAnim->animationControllerPriv()->addEventToDispatch(element, eventType, m_keyframes.animationName(), elapsedTime);
// Restore the original (unanimated) style
if (eventType == eventNames().webkitAnimationEndEvent && element->renderer())
@@ -287,4 +352,31 @@ void KeyframeAnimation::validateTransformFunctionList()
m_transformFunctionListValid = true;
}
+double KeyframeAnimation::willNeedService()
+{
+ double t = AnimationBase::willNeedService();
+#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