Index: Source/core/animation/css/CSSAnimations.cpp |
diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp |
index 8efea0573bac83ebd72943d9ad76f1d501539ce0..7c937283c4689ff5ad9555b030942d06628a7cb1 100644 |
--- a/Source/core/animation/css/CSSAnimations.cpp |
+++ b/Source/core/animation/css/CSSAnimations.cpp |
@@ -88,7 +88,7 @@ static void resolveKeyframes(StyleResolver* resolver, const Element* animatingEl |
{ |
// When the animating element is null, use its parent for scoping purposes. |
const Element* elementForScoping = animatingElement ? animatingElement : &element; |
- const StyleRuleKeyframes* keyframesRule = resolver->findKeyframesRule(elementForScoping, name); |
+ const StyleRuleKeyframes* keyframesRule = resolver->findKeyframesRule(elementForScoping, name).get(); |
if (!keyframesRule) |
return; |
@@ -206,7 +206,7 @@ CSSAnimations::CSSAnimations() |
const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPlayer& player) |
{ |
for (const auto& it : m_animations) { |
- if (it.value->sequenceNumber() == player.sequenceNumber()) |
+ if (it.value.player->sequenceNumber() == player.sequenceNumber()) |
return it.key; |
} |
return nullAtom; |
@@ -235,6 +235,7 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
const CSSAnimationData* animationData = style.animations(); |
const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->cssAnimations() : nullptr; |
+ const Element* elementForScoping = animatingElement ? animatingElement : &element; |
HashSet<AtomicString> inactive; |
if (cssAnimations) { |
@@ -251,25 +252,29 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
const bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused; |
Timing timing = animationData->convertToTiming(i); |
+ Timing specifiedTiming = timing; |
RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction; |
timing.timingFunction = Timing::defaults().timingFunction; |
+ RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->findKeyframesRule(elementForScoping, animationName); |
+ if (!keyframesRule) |
+ continue; // Cancel the animation if there's no style rule for it. |
+ |
if (cssAnimations) { |
AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName)); |
if (existing != cssAnimations->m_animations.end()) { |
inactive.remove(animationName); |
- AnimationPlayer* player = existing->value.get(); |
- |
- // FIXME: Should handle changes in the timing function. |
- if (timing != player->source()->specifiedTiming()) { |
- ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
+ const RunningAnimation& runningAnimation = existing->value; |
+ AnimationPlayer* player = runningAnimation.player.get(); |
+ ASSERT(keyframesRule); |
+ if (keyframesRule != runningAnimation.styleRule || keyframesRule->styleChangeCounter() != runningAnimation.styleChangeCounter || runningAnimation.specifiedTiming != specifiedTiming) { |
AnimatableValueKeyframeVector resolvedKeyframes; |
resolveKeyframes(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); |
- update->updateAnimationTiming(player, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), |
- timing, isPaused, player->currentTimeInternal()), timing); |
+ update->updateAnimation(animationName, player, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), |
+ timing, isPaused, player->currentTimeInternal()), specifiedTiming, keyframesRule); |
} |
if (isPaused != player->paused()) { |
@@ -285,7 +290,7 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
resolveKeyframes(resolver, animatingElement, element, style, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); |
if (!resolvedKeyframes.isEmpty()) { |
ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
- update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0)); |
+ update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0), specifiedTiming, keyframesRule); |
} |
} |
} |
@@ -293,7 +298,7 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E |
ASSERT(inactive.isEmpty() || cssAnimations); |
for (const AtomicString& animationName : inactive) { |
ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()); |
- update->cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName)); |
+ update->cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName).player); |
} |
} |
@@ -314,13 +319,13 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
DisableCompositingQueryAsserts disabler; |
for (const AtomicString& animationName : update->cancelledAnimationNames()) { |
- RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animationName); |
+ RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animationName).player; |
player->cancel(); |
player->update(TimingUpdateOnDemand); |
} |
for (const AtomicString& animationName : update->animationsWithPauseToggled()) { |
- AnimationPlayer* player = m_animations.get(animationName); |
+ AnimationPlayer* player = m_animations.get(animationName).player.get(); |
if (player->paused()) |
player->unpause(); |
else |
@@ -329,9 +334,16 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
player->update(TimingUpdateOnDemand); |
} |
- for (const auto& timingUpdate : update->animationsWithTimingUpdates()) { |
- timingUpdate.player->source()->updateSpecifiedTiming(timingUpdate.newTiming); |
- timingUpdate.player->update(TimingUpdateOnDemand); |
+ for (const auto& entry : update->animationsWithUpdates()) { |
+ Animation* animation = toAnimation(entry.player->source()); |
+ |
+ animation->setEffect(entry.animation->effect()); |
+ animation->updateSpecifiedTiming(entry.animation->specifiedTiming()); |
+ |
+ auto& runningAnimation = m_animations.find(entry.name)->value; |
+ runningAnimation.styleRule = entry.styleRule; |
+ runningAnimation.styleChangeCounter = entry.styleChangeCounter; |
+ runningAnimation.specifiedTiming = entry.specifiedTiming; |
} |
for (const auto& entry : update->newAnimations()) { |
@@ -343,7 +355,14 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
if (inertAnimation->paused()) |
player->pause(); |
player->update(TimingUpdateOnDemand); |
- m_animations.set(entry.name, player.get()); |
+ |
+ RunningAnimation runningAnimation; |
+ runningAnimation.player = player; |
+ runningAnimation.specifiedTiming = entry.timing; |
+ runningAnimation.styleRule = entry.styleRule; |
+ runningAnimation.styleChangeCounter = entry.styleChangeCounter; |
+ |
+ m_animations.set(entry.name, runningAnimation); |
} |
// Transitions that are run on the compositor only update main-thread state |
@@ -533,8 +552,8 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate* update, const |
void CSSAnimations::cancel() |
{ |
for (const auto& entry : m_animations) { |
- entry.value->cancel(); |
- entry.value->update(TimingUpdateOnDemand); |
+ entry.value.player->cancel(); |
+ entry.value.player->update(TimingUpdateOnDemand); |
} |
for (const auto& entry : m_transitions) { |
@@ -561,8 +580,8 @@ void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u |
WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations; |
for (const auto& newAnimation : update->newAnimations()) |
newAnimations.append(newAnimation.animation.get()); |
- for (const auto& updatedAnimation : update->animationsWithTimingUpdates()) |
- newAnimations.append(updatedAnimation.animation.get()); // Animations with timing updates use a temporary InertAnimation for the current frame. |
+ for (const auto& updatedAnimation : update->animationsWithUpdates()) |
+ newAnimations.append(updatedAnimation.animation.get()); // Animations with updates use a temporary InertAnimation for the current frame. |
WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, &newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::DefaultPriority, timelineCurrentTime)); |
update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimations); |
@@ -748,7 +767,7 @@ void CSSAnimationUpdate::trace(Visitor* visitor) |
visitor->trace(m_activeInterpolationsForTransitions); |
visitor->trace(m_newAnimations); |
visitor->trace(m_suppressedAnimationPlayers); |
- visitor->trace(m_animationsWithTimingUpdates); |
+ visitor->trace(m_animationsWithUpdates); |
#endif |
} |