| Index: Source/core/animation/css/CSSAnimations.cpp
|
| diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp
|
| index 06d8a0d827b0d8413413ee81c2f9c5e69aa88305..8bd077dc6cd97bbd0e5b93bc4429b6e4dcd6b993 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, keyframesRule->styleChangeCounter());
|
| }
|
|
|
| if (isPaused != player->paused()) {
|
| @@ -285,7 +290,8 @@ 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));
|
| + unsigned styleChangeCounter = keyframesRule ? keyframesRule->styleChangeCounter() : 0;
|
| + update->startAnimation(animationName, InertAnimation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0), specifiedTiming, keyframesRule, styleChangeCounter);
|
| }
|
| }
|
| }
|
| @@ -293,7 +299,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 +320,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 +335,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 +356,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 +553,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 +581,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 +768,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
|
| }
|
|
|
|
|