Chromium Code Reviews| Index: Source/core/animation/css/CSSAnimations.cpp |
| diff --git a/Source/core/animation/css/CSSAnimations.cpp b/Source/core/animation/css/CSSAnimations.cpp |
| index b939225cd17653f7374ed69412efb330717f3058..cf8c6982824facff902b7aab585a85b744819462 100644 |
| --- a/Source/core/animation/css/CSSAnimations.cpp |
| +++ b/Source/core/animation/css/CSSAnimations.cpp |
| @@ -90,7 +90,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; |
| @@ -210,7 +210,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; |
| @@ -239,6 +239,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) { |
| @@ -255,25 +256,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()) { |
| @@ -289,7 +294,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); |
| } |
| } |
| } |
| @@ -297,7 +302,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); |
| } |
| } |
| @@ -318,13 +323,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 |
| @@ -333,9 +338,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; |
|
esprehn
2015/01/29 04:23:19
maybe a method on RunningAnimation like update(ent
shend
2015/01/30 00:03:10
Done.
|
| + runningAnimation.styleChangeCounter = entry.styleChangeCounter; |
| + runningAnimation.specifiedTiming = entry.specifiedTiming; |
| } |
| for (const auto& entry : update->newAnimations()) { |
| @@ -347,7 +359,14 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
| if (inertAnimation->paused()) |
| player->pause(); |
| player->update(TimingUpdateOnDemand); |
| - m_animations.set(entry.name, player.get()); |
| + |
| + RunningAnimation runningAnimation; |
|
esprehn
2015/01/29 04:23:19
RunningAnimation runningAnimation(player, entry) a
shend
2015/01/30 00:03:10
Done.
|
| + 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 |
| @@ -537,8 +556,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) { |
| @@ -565,8 +584,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); |
| @@ -752,7 +771,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 |
| } |