summaryrefslogtreecommitdiffstats
path: root/WebCore/page/animation
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/page/animation
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/page/animation')
-rw-r--r--WebCore/page/animation/AnimationBase.cpp55
-rw-r--r--WebCore/page/animation/AnimationBase.h3
-rw-r--r--WebCore/page/animation/AnimationController.cpp18
-rw-r--r--WebCore/page/animation/CompositeAnimation.cpp316
-rw-r--r--WebCore/page/animation/CompositeAnimation.h2
-rw-r--r--WebCore/page/animation/ImplicitAnimation.cpp5
-rw-r--r--WebCore/page/animation/ImplicitAnimation.h4
-rw-r--r--WebCore/page/animation/KeyframeAnimation.cpp12
8 files changed, 216 insertions, 199 deletions
diff --git a/WebCore/page/animation/AnimationBase.cpp b/WebCore/page/animation/AnimationBase.cpp
index 7b8a189..7503f0a 100644
--- a/WebCore/page/animation/AnimationBase.cpp
+++ b/WebCore/page/animation/AnimationBase.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
@@ -45,6 +45,8 @@
#include "MatrixTransformOperation.h"
#include "Matrix3DTransformOperation.h"
#include "RenderBox.h"
+#include "RenderLayer.h"
+#include "RenderLayerBacking.h"
#include "RenderStyle.h"
#include "UnitBezier.h"
@@ -113,11 +115,23 @@ static inline IntSize blendFunc(const AnimationBase* anim, const IntSize& from,
blendFunc(anim, from.height(), to.height(), progress));
}
+static inline ShadowStyle blendFunc(const AnimationBase* anim, ShadowStyle from, ShadowStyle to, double progress)
+{
+ if (from == to)
+ return to;
+
+ double fromVal = from == Normal ? 1 : 0;
+ double toVal = to == Normal ? 1 : 0;
+ double result = blendFunc(anim, fromVal, toVal, progress);
+ return result > 0 ? Normal : Inset;
+}
+
static inline ShadowData* blendFunc(const AnimationBase* anim, const ShadowData* from, const ShadowData* to, double progress)
{
ASSERT(from && to);
return new ShadowData(blendFunc(anim, from->x, to->x, progress), blendFunc(anim, from->y, to->y, progress),
- blendFunc(anim, from->blur, to->blur, progress), blendFunc(anim, from->color, to->color, progress));
+ blendFunc(anim, from->blur, to->blur, progress), blendFunc(anim, from->spread, to->spread, progress),
+ blendFunc(anim, from->style, to->style, progress), blendFunc(anim, from->color, to->color, progress));
}
static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress)
@@ -300,7 +314,7 @@ public:
{
ShadowData* shadowA = (a->*m_getter)();
ShadowData* shadowB = (b->*m_getter)();
- ShadowData defaultShadowData(0, 0, 0, Color::transparent);
+ ShadowData defaultShadowData(0, 0, 0, 0, Normal, Color::transparent);
if (!shadowA)
shadowA = &defaultShadowData;
@@ -404,8 +418,15 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom));
+
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth));
+
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight));
+
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth));
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth));
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth));
@@ -442,16 +463,18 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing));
gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing));
+ gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent));
+
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX));
gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
- gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius));
+ gPropertyWrappers->append(new PropertyWrapper<const IntSize&>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius));
gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility));
gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom));
@@ -473,7 +496,7 @@ static void ensurePropertyMap()
gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyOutlineColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor));
// These are for shadows
- gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
+ gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow));
gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow));
#if ENABLE(SVG)
@@ -484,8 +507,6 @@ static void ensurePropertyMap()
// TODO:
//
- // CSSPropertyMinWidth, CSSPropertyMaxWidth, CSSPropertyMinHeight, CSSPropertyMaxHeight
- // CSSPropertyTextIndent
// CSSPropertyVerticalAlign
//
// Compound properties that have components that should be animatable:
@@ -1041,7 +1062,7 @@ void AnimationBase::getTimeToNextEvent(double& time, bool& isLooping) const
double nextIterationTime = m_totalDuration;
if (m_totalDuration < 0 || elapsedDuration < m_totalDuration) {
- durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration());
+ durationLeft = m_animation->duration() > 0 ? (m_animation->duration() - fmod(elapsedDuration, m_animation->duration())) : 0;
nextIterationTime = elapsedDuration + durationLeft;
}
@@ -1065,10 +1086,18 @@ void AnimationBase::goIntoEndingOrLoopingState()
m_animState = isLooping ? AnimationStateLooping : AnimationStateEnding;
}
-void AnimationBase::pauseAtTime(double t)
+void AnimationBase::freezeAtTime(double t)
{
- updatePlayState(false);
+ ASSERT(m_startTime); // if m_startTime is zero, we haven't started yet, so we'll get a bad pause time.
m_pauseTime = m_startTime + t - m_animation->delay();
+
+#if USE(ACCELERATED_COMPOSITING)
+ if (m_object && m_object->hasLayer()) {
+ RenderLayer* layer = toRenderBoxModelObject(m_object)->layer();
+ if (layer->isComposited())
+ layer->backing()->suspendAnimations(m_pauseTime);
+ }
+#endif
}
double AnimationBase::beginAnimationUpdateTime() const
diff --git a/WebCore/page/animation/AnimationBase.h b/WebCore/page/animation/AnimationBase.h
index 8f55a8e..3482f65 100644
--- a/WebCore/page/animation/AnimationBase.h
+++ b/WebCore/page/animation/AnimationBase.h
@@ -156,7 +156,8 @@ public:
bool isTransformFunctionListValid() const { return m_transformFunctionListValid; }
- void pauseAtTime(double t);
+ // Freeze the animation; used by DumpRenderTree.
+ void freezeAtTime(double t);
double beginAnimationUpdateTime() const;
diff --git a/WebCore/page/animation/AnimationController.cpp b/WebCore/page/animation/AnimationController.cpp
index 58a1f5b..ed241e1 100644
--- a/WebCore/page/animation/AnimationController.cpp
+++ b/WebCore/page/animation/AnimationController.cpp
@@ -136,9 +136,9 @@ void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<Animat
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);
+ it->element->dispatchWebKitTransitionEvent(it->eventType, it->name, it->elapsedTime);
else
- it->element->dispatchWebKitAnimationEvent(it->eventType,it->name, it->elapsedTime);
+ it->element->dispatchWebKitAnimationEvent(it->eventType, it->name, it->elapsedTime);
}
m_eventsToDispatch.clear();
@@ -152,20 +152,6 @@ void AnimationControllerPrivate::updateStyleIfNeededDispatcherFired(Timer<Animat
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::startUpdateStyleIfNeededDispatcher()
diff --git a/WebCore/page/animation/CompositeAnimation.cpp b/WebCore/page/animation/CompositeAnimation.cpp
index d60455a..8946d80 100644
--- a/WebCore/page/animation/CompositeAnimation.cpp
+++ b/WebCore/page/animation/CompositeAnimation.cpp
@@ -67,91 +67,117 @@ void CompositeAnimation::clearRenderer()
void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
{
- RefPtr<RenderStyle> modifiedCurrentStyle;
-
- // If currentStyle is null, we don't do transitions
- if (!currentStyle || !targetStyle->transitions())
+ // If currentStyle is null or there are no old or new transitions, just skip it
+ if (!currentStyle || (!targetStyle->transitions() && m_transitions.isEmpty()))
return;
+ // Mark all existing transitions as no longer active. We will mark the still active ones
+ // in the next loop and then toss the ones that didn't get marked.
+ CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
+ for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it)
+ it->second->setActive(false);
+
+ RefPtr<RenderStyle> modifiedCurrentStyle;
+
// Check to see if we need to update the active transitions
- for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) {
- const Animation* anim = targetStyle->transitions()->animation(i);
- bool isActiveTransition = anim->duration() || anim->delay() > 0;
+ if (targetStyle->transitions()) {
+ for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) {
+ const Animation* anim = targetStyle->transitions()->animation(i);
+ bool isActiveTransition = anim->duration() || anim->delay() > 0;
- int prop = anim->property();
+ int prop = anim->property();
- if (prop == cAnimateNone)
- continue;
-
- bool all = prop == cAnimateAll;
+ if (prop == cAnimateNone)
+ continue;
- // Handle both the 'all' and single property cases. For the single prop case, we make only one pass
- // through the loop.
- for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) {
- if (all) {
- // Get the next property which is not a shorthand.
- bool isShorthand;
- prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand);
- if (isShorthand)
- continue;
- }
+ bool all = prop == cAnimateAll;
+
+ // Handle both the 'all' and single property cases. For the single prop case, we make only one pass
+ // through the loop.
+ for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) {
+ if (all) {
+ // Get the next property which is not a shorthand.
+ bool isShorthand;
+ prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand);
+ if (isShorthand)
+ continue;
+ }
- // ImplicitAnimations are always hashed by actual properties, never cAnimateAll
- ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
-
- // If there is a running animation for this property, the transition is overridden
- // and we have to use the unanimatedStyle from the animation. We do the test
- // against the unanimated style here, but we "override" the transition later.
- RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop);
- RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle;
-
- // See if there is a current transition for this prop
- ImplicitAnimation* implAnim = m_transitions.get(prop).get();
- bool equal = true;
-
- if (implAnim) {
- // This might be a transition that is just finishing. That would be the case
- // if it were postActive. But we still need to check for equality because
- // it could be just finishing AND changing to a new goal state.
- //
- // This implAnim might also not be an already running transition. It might be
- // newly added to the list in a previous iteration. This would happen if
- // you have both an explicit transition-property and 'all' in the same
- // list. In this case, the latter one overrides the earlier one, so we
- // behave as though this is a running animation being replaced.
- if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
-#if USE(ACCELERATED_COMPOSITING)
- // For accelerated animations we need to return a new RenderStyle with the _current_ value
- // of the property, so that restarted transitions use the correct starting point.
- if (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) {
- if (!modifiedCurrentStyle)
- modifiedCurrentStyle = RenderStyle::clone(currentStyle);
-
- implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get());
+ // ImplicitAnimations are always hashed by actual properties, never cAnimateAll
+ ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
+
+ // If there is a running animation for this property, the transition is overridden
+ // and we have to use the unanimatedStyle from the animation. We do the test
+ // against the unanimated style here, but we "override" the transition later.
+ RefPtr<KeyframeAnimation> keyframeAnim = getAnimationForProperty(prop);
+ RenderStyle* fromStyle = keyframeAnim ? keyframeAnim->unanimatedStyle() : currentStyle;
+
+ // See if there is a current transition for this prop
+ ImplicitAnimation* implAnim = m_transitions.get(prop).get();
+ bool equal = true;
+
+ if (implAnim) {
+ // If we are post active don't bother setting the active flag. This will cause
+ // this animation to get removed at the end of this function.
+ if (!implAnim->postActive())
+ implAnim->setActive(true);
+
+ // This might be a transition that is just finishing. That would be the case
+ // if it were postActive. But we still need to check for equality because
+ // it could be just finishing AND changing to a new goal state.
+ //
+ // This implAnim might also not be an already running transition. It might be
+ // newly added to the list in a previous iteration. This would happen if
+ // you have both an explicit transition-property and 'all' in the same
+ // list. In this case, the latter one overrides the earlier one, so we
+ // behave as though this is a running animation being replaced.
+ if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
+ #if USE(ACCELERATED_COMPOSITING)
+ // For accelerated animations we need to return a new RenderStyle with the _current_ value
+ // of the property, so that restarted transitions use the correct starting point.
+ if (AnimationBase::animationOfPropertyIsAccelerated(prop) && !implAnim->isFallbackAnimating()) {
+ if (!modifiedCurrentStyle)
+ modifiedCurrentStyle = RenderStyle::clone(currentStyle);
+
+ implAnim->blendPropertyValueInStyle(prop, modifiedCurrentStyle.get());
+ }
+ #endif
+ m_transitions.remove(prop);
+ equal = false;
}
-#endif
- m_transitions.remove(prop);
- equal = false;
+ } else {
+ // We need to start a transition if it is active and the properties don't match
+ equal = !isActiveTransition || AnimationBase::propertiesEqual(prop, fromStyle, targetStyle);
}
- } else {
- // We need to start a transition if it is active and the properties don't match
- equal = !isActiveTransition || AnimationBase::propertiesEqual(prop, fromStyle, targetStyle);
- }
- // We can be in this loop with an inactive transition (!isActiveTransition). We need
- // to do that to check to see if we are canceling a transition. But we don't want to
- // start one of the inactive transitions. So short circuit that here. (See
- // <https://bugs.webkit.org/show_bug.cgi?id=24787>
- if (!equal && isActiveTransition) {
- // Add the new transition
- m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle));
+ // We can be in this loop with an inactive transition (!isActiveTransition). We need
+ // to do that to check to see if we are canceling a transition. But we don't want to
+ // start one of the inactive transitions. So short circuit that here. (See
+ // <https://bugs.webkit.org/show_bug.cgi?id=24787>
+ if (!equal && isActiveTransition) {
+ // Add the new transition
+ m_transitions.set(prop, ImplicitAnimation::create(const_cast<Animation*>(anim), prop, renderer, this, modifiedCurrentStyle ? modifiedCurrentStyle.get() : fromStyle));
+ }
+
+ // We only need one pass for the single prop case
+ if (!all)
+ break;
}
-
- // We only need one pass for the single prop case
- if (!all)
- break;
}
}
+
+ // Make a list of transitions to be removed
+ Vector<int> toBeRemoved;
+ end = m_transitions.end();
+ for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
+ ImplicitAnimation* anim = it->second.get();
+ if (!anim->active())
+ toBeRemoved.append(anim->animatingProperty());
+ }
+
+ // Now remove the transitions from the list
+ for (size_t j = 0; j < toBeRemoved.size(); ++j)
+ m_transitions.remove(toBeRemoved[j]);
}
void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
@@ -160,52 +186,62 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render
if (m_keyframeAnimations.isEmpty() && !targetStyle->hasAnimations())
return;
- // Nothing to do if the current and target animations are the same
- if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations()))
- return;
-
- // Mark all existing animations as no longer active
AnimationNameMap::const_iterator kfend = m_keyframeAnimations.end();
- for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
- it->second->setIndex(-1);
-
- // Toss the animation order map
- m_keyframeAnimationOrderMap.clear();
- // Now mark any still active animations as active and add any new animations
- if (targetStyle->animations()) {
- int numAnims = targetStyle->animations()->size();
- for (int i = 0; i < numAnims; ++i) {
- const Animation* anim = targetStyle->animations()->animation(i);
- AtomicString animationName(anim->name());
-
- if (!anim->isValidAnimation())
- continue;
+ if (currentStyle && currentStyle->hasAnimations() && targetStyle->hasAnimations() && *(currentStyle->animations()) == *(targetStyle->animations())) {
+ // The current and target animations are the same so we just need to toss any
+ // animation which is finished (postActive).
+ for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) {
+ if (it->second->postActive())
+ it->second->setIndex(-1);
+ }
+ } else {
+ // Mark all existing animations as no longer active.
+ for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it)
+ it->second->setIndex(-1);
- // See if there is a current animation for this name
- RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());
+ // Toss the animation order map.
+ m_keyframeAnimationOrderMap.clear();
+
+ // Now mark any still active animations as active and add any new animations.
+ if (targetStyle->animations()) {
+ int numAnims = targetStyle->animations()->size();
+ for (int i = 0; i < numAnims; ++i) {
+ const Animation* anim = targetStyle->animations()->animation(i);
+ AtomicString animationName(anim->name());
+
+ if (!anim->isValidAnimation())
+ continue;
+
+ // See if there is a current animation for this name.
+ RefPtr<KeyframeAnimation> keyframeAnim = m_keyframeAnimations.get(animationName.impl());
- if (keyframeAnim) {
- // There is one so it is still active
-
- // Animations match, but play states may differ. update if needed
- keyframeAnim->updatePlayState(anim->playState() == AnimPlayStatePlaying);
-
- // Set the saved animation to this new one, just in case the play state has changed
- keyframeAnim->setAnimation(anim);
- keyframeAnim->setIndex(i);
- } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) {
- keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, currentStyle ? currentStyle : targetStyle);
- m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
+ if (keyframeAnim) {
+ // If this animation is postActive, skip it so it gets removed at the end of this function.
+ if (keyframeAnim->postActive())
+ continue;
+
+ // This one is still active.
+
+ // Animations match, but play states may differ. Update if needed.
+ keyframeAnim->updatePlayState(anim->playState() == AnimPlayStatePlaying);
+
+ // Set the saved animation to this new one, just in case the play state has changed.
+ keyframeAnim->setAnimation(anim);
+ keyframeAnim->setIndex(i);
+ } else if ((anim->duration() || anim->delay()) && anim->iterationCount()) {
+ keyframeAnim = KeyframeAnimation::create(const_cast<Animation*>(anim), renderer, i, this, currentStyle ? currentStyle : targetStyle);
+ m_keyframeAnimations.set(keyframeAnim->name().impl(), keyframeAnim);
+ }
+
+ // Add this to the animation order map.
+ if (keyframeAnim)
+ m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl());
}
-
- // Add this to the animation order map
- if (keyframeAnim)
- m_keyframeAnimationOrderMap.append(keyframeAnim->name().impl());
}
}
-
- // Make a list of animations to be removed
+
+ // Make a list of animations to be removed.
Vector<AtomicStringImpl*> animsToBeRemoved;
kfend = m_keyframeAnimations.end();
for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != kfend; ++it) {
@@ -214,7 +250,7 @@ void CompositeAnimation::updateKeyframeAnimations(RenderObject* renderer, Render
animsToBeRemoved.append(keyframeAnim->name().impl());
}
- // Now remove the animations from the list
+ // Now remove the animations from the list.
for (size_t j = 0; j < animsToBeRemoved.size(); ++j)
m_keyframeAnimations.remove(animsToBeRemoved[j]);
}
@@ -223,11 +259,9 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend
{
RefPtr<RenderStyle> resultStyle;
- // Update animations first so we can see if any transitions are overridden
- updateKeyframeAnimations(renderer, currentStyle, targetStyle);
-
- // We don't do any transitions if we don't have a currentStyle (on startup)
+ // We don't do any transitions if we don't have a currentStyle (on startup).
updateTransitions(renderer, currentStyle, targetStyle);
+ updateKeyframeAnimations(renderer, currentStyle, targetStyle);
if (currentStyle) {
// Now that we have transition objects ready, let them know about the new goal state. We want them
@@ -249,8 +283,6 @@ PassRefPtr<RenderStyle> CompositeAnimation::animate(RenderObject* renderer, Rend
keyframeAnim->animate(this, renderer, currentStyle, targetStyle, resultStyle);
}
- cleanupFinishedAnimations();
-
return resultStyle ? resultStyle.release() : targetStyle;
}
@@ -341,50 +373,6 @@ PassRefPtr<KeyframeAnimation> CompositeAnimation::getAnimationForProperty(int pr
return retval;
}
-void CompositeAnimation::cleanupFinishedAnimations()
-{
- if (isSuspended())
- return;
-
- // Make a list of transitions to be deleted
- Vector<int> finishedTransitions;
- if (!m_transitions.isEmpty()) {
- CSSPropertyTransitionsMap::const_iterator transitionsEnd = m_transitions.end();
-
- for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != transitionsEnd; ++it) {
- ImplicitAnimation* anim = it->second.get();
- if (!anim)
- continue;
- if (anim->postActive())
- finishedTransitions.append(anim->animatingProperty());
- }
-
- // Delete them
- size_t finishedTransitionCount = finishedTransitions.size();
- for (size_t i = 0; i < finishedTransitionCount; ++i)
- m_transitions.remove(finishedTransitions[i]);
- }
-
- // Make a list of animations to be deleted
- Vector<AtomicStringImpl*> finishedAnimations;
- if (!m_keyframeAnimations.isEmpty()) {
- AnimationNameMap::const_iterator animationsEnd = m_keyframeAnimations.end();
-
- for (AnimationNameMap::const_iterator it = m_keyframeAnimations.begin(); it != animationsEnd; ++it) {
- KeyframeAnimation* anim = it->second.get();
- if (!anim)
- continue;
- if (anim->postActive())
- finishedAnimations.append(anim->name().impl());
- }
-
- // Delete them
- size_t finishedAnimationCount = finishedAnimations.size();
- for (size_t i = 0; i < finishedAnimationCount; ++i)
- m_keyframeAnimations.remove(finishedAnimations[i]);
- }
-}
-
void CompositeAnimation::suspendAnimations()
{
if (m_isSuspended)
@@ -492,7 +480,7 @@ bool CompositeAnimation::pauseAnimationAtTime(const AtomicString& name, double t
int count = keyframeAnim->m_animation->iterationCount();
if ((t >= 0.0) && (!count || (t <= count * keyframeAnim->duration()))) {
- keyframeAnim->pauseAtTime(t);
+ keyframeAnim->freezeAtTime(t);
return true;
}
@@ -509,7 +497,7 @@ bool CompositeAnimation::pauseTransitionAtTime(int property, double t)
return false;
if ((t >= 0.0) && (t <= implAnim->duration())) {
- implAnim->pauseAtTime(t);
+ implAnim->freezeAtTime(t);
return true;
}
diff --git a/WebCore/page/animation/CompositeAnimation.h b/WebCore/page/animation/CompositeAnimation.h
index 739cfdc..b7db442 100644
--- a/WebCore/page/animation/CompositeAnimation.h
+++ b/WebCore/page/animation/CompositeAnimation.h
@@ -74,8 +74,6 @@ public:
PassRefPtr<KeyframeAnimation> getAnimationForProperty(int property) const;
- void cleanupFinishedAnimations();
-
void overrideImplicitAnimations(int property);
void resumeOverriddenImplicitAnimations(int property);
diff --git a/WebCore/page/animation/ImplicitAnimation.cpp b/WebCore/page/animation/ImplicitAnimation.cpp
index e93fee4..8e6349d 100644
--- a/WebCore/page/animation/ImplicitAnimation.cpp
+++ b/WebCore/page/animation/ImplicitAnimation.cpp
@@ -45,6 +45,7 @@ ImplicitAnimation::ImplicitAnimation(const Animation* transition, int animatingP
, m_transitionProperty(transition->property())
, m_animatingProperty(animatingProperty)
, m_overridden(false)
+ , m_active(true)
, m_fromStyle(fromStyle)
{
ASSERT(animatingProperty != cAnimateAll);
@@ -211,6 +212,10 @@ bool ImplicitAnimation::affectsProperty(int property) const
bool ImplicitAnimation::isTargetPropertyEqual(int prop, const RenderStyle* targetStyle)
{
+ // We can get here for a transition that has not started yet. This would make m_toStyle unset and null.
+ // So we check that here (see <https://bugs.webkit.org/show_bug.cgi?id=26706>)
+ if (!m_toStyle)
+ return false;
return propertiesEqual(prop, m_toStyle.get(), targetStyle);
}
diff --git a/WebCore/page/animation/ImplicitAnimation.h b/WebCore/page/animation/ImplicitAnimation.h
index 33fe4e4..7e286d2 100644
--- a/WebCore/page/animation/ImplicitAnimation.h
+++ b/WebCore/page/animation/ImplicitAnimation.h
@@ -66,6 +66,9 @@ public:
void blendPropertyValueInStyle(int, RenderStyle* currentStyle);
virtual double timeToNextService();
+
+ bool active() const { return m_active; }
+ void setActive(bool b) { m_active = b; }
protected:
bool shouldSendEventForListener(Document::ListenerType) const;
@@ -80,6 +83,7 @@ private:
int m_transitionProperty; // Transition property as specified in the RenderStyle. May be cAnimateAll
int m_animatingProperty; // Specific property for this ImplicitAnimation
bool m_overridden; // true when there is a keyframe animation that overrides the transitioning property
+ bool m_active; // used for culling the list of transitions
// The two styles that we are blending.
RefPtr<RenderStyle> m_fromStyle;
diff --git a/WebCore/page/animation/KeyframeAnimation.cpp b/WebCore/page/animation/KeyframeAnimation.cpp
index 3f84de1..39ae1e7 100644
--- a/WebCore/page/animation/KeyframeAnimation.cpp
+++ b/WebCore/page/animation/KeyframeAnimation.cpp
@@ -93,8 +93,10 @@ void KeyframeAnimation::getKeyframeAnimationInterval(const RenderStyle*& fromSty
return;
const TimingFunction* timingFunction = 0;
- if (fromStyle->animations() && fromStyle->animations()->size() > 0)
+ if (fromStyle->animations() && fromStyle->animations()->size() > 0) {
+ // We get the timing function from the first animation, because we've synthesized a RenderStyle for each keyframe.
timingFunction = &(fromStyle->animations()->animation(0)->timingFunction());
+ }
prog = progress(scale, offset, timingFunction);
}
@@ -209,8 +211,12 @@ void KeyframeAnimation::endAnimation(bool reset)
#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);
+ if (layer->isComposited()) {
+ if (reset)
+ layer->backing()->animationFinished(m_keyframes.animationName());
+ else
+ layer->backing()->animationPaused(m_keyframes.animationName());
+ }
}
#else
UNUSED_PARAM(reset);