Index: third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp |
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp |
index 13865e96a6d705387f532d75ab2c4596ec075594..4070218f25fbcd596104b5a527a24db72819643d 100644 |
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp |
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp |
@@ -191,8 +191,8 @@ CSSAnimations::CSSAnimations() |
bool CSSAnimations::isAnimationForInspector(const Animation& animation) |
{ |
- for (const auto& it : m_animations) { |
- if (it.value->animation->sequenceNumber() == animation.sequenceNumber()) |
+ for (const auto& runningAnimation : m_runningAnimations) { |
+ if (runningAnimation->animation->sequenceNumber() == animation.sequenceNumber()) |
return true; |
} |
return false; |
@@ -232,7 +232,7 @@ void CSSAnimations::calculateCompositorAnimationUpdate(CSSAnimationUpdate& updat |
return; |
CSSAnimations& cssAnimations = elementAnimations->cssAnimations(); |
- for (auto& runningAnimation : cssAnimations.m_animations.values()) { |
+ for (auto& runningAnimation : cssAnimations.m_runningAnimations) { |
Animation& animation = *runningAnimation->animation; |
if (animation.effect() && animation.effect()->isKeyframeEffect()) { |
EffectModel* model = toKeyframeEffect(animation.effect())->model(); |
@@ -276,18 +276,24 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate& update, const E |
const CSSAnimations* cssAnimations = elementAnimations ? &elementAnimations->cssAnimations() : nullptr; |
const Element* elementForScoping = animatingElement ? animatingElement : &element; |
- HashSet<AtomicString> inactive; |
- if (cssAnimations) { |
- for (const auto& entry : cssAnimations->m_animations) |
- inactive.add(entry.key); |
- } |
+ Vector<bool> cancelRunningAnimationFlags(cssAnimations ? cssAnimations->m_runningAnimations.size() : 0); |
+ for (bool& flag : cancelRunningAnimationFlags) |
+ flag = true; |
- if (style.display() != NONE) { |
- for (size_t i = 0; animationData && i < animationData->nameList().size(); ++i) { |
- AtomicString animationName(animationData->nameList()[i]); |
- if (animationName == CSSAnimationData::initialName()) |
+ if (animationData && style.display() != NONE) { |
+ const Vector<AtomicString>& nameList = animationData->nameList(); |
+ for (size_t i = 0; i < nameList.size(); ++i) { |
+ AtomicString name = nameList[i]; |
+ if (name == CSSAnimationData::initialName()) |
continue; |
+ // Find n where this is the nth occurence of this animation name. |
+ size_t nameIndex = 0; |
+ for (size_t j = 0; j < i; j++) { |
+ if (nameList[j] == name) |
+ nameIndex++; |
+ } |
+ |
const bool isPaused = CSSTimingData::getRepeated(animationData->playStateList(), i) == AnimPlayStatePaused; |
Timing timing = animationData->convertToTiming(i); |
@@ -295,45 +301,54 @@ void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate& update, const E |
RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunction; |
timing.timingFunction = Timing::defaults().timingFunction; |
- RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->findKeyframesRule(elementForScoping, animationName); |
+ RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->findKeyframesRule(elementForScoping, name); |
if (!keyframesRule) |
continue; // Cancel the animation if there's no style rule for it. |
+ const RunningAnimation* existingAnimation = nullptr; |
+ size_t existingAnimationIndex = 0; |
+ |
if (cssAnimations) { |
- AnimationMap::const_iterator existing(cssAnimations->m_animations.find(animationName)); |
- if (existing != cssAnimations->m_animations.end()) { |
- inactive.remove(animationName); |
- |
- const RunningAnimation* runningAnimation = existing->value.get(); |
- Animation* animation = runningAnimation->animation.get(); |
- |
- if (keyframesRule != runningAnimation->styleRule || keyframesRule->version() != runningAnimation->styleRuleVersion || runningAnimation->specifiedTiming != specifiedTiming) { |
- ASSERT(!isAnimationStyleChange); |
- update.updateAnimation(animationName, animation, InertEffect::create( |
- createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, animationName, keyframeTimingFunction.get(), i), |
- timing, isPaused, animation->unlimitedCurrentTimeInternal()), specifiedTiming, keyframesRule); |
+ for (size_t i = 0; i < cssAnimations->m_runningAnimations.size(); i++) { |
+ const RunningAnimation& runningAnimation = *cssAnimations->m_runningAnimations[i]; |
+ if (runningAnimation.name == name && runningAnimation.nameIndex == nameIndex) { |
+ existingAnimation = &runningAnimation; |
+ existingAnimationIndex = i; |
+ break; |
} |
+ } |
+ } |
- if (isPaused != animation->paused()) { |
- ASSERT(!isAnimationStyleChange); |
- update.toggleAnimationPaused(animationName); |
- } |
+ if (existingAnimation) { |
+ cancelRunningAnimationFlags[existingAnimationIndex] = false; |
+ |
+ Animation* animation = existingAnimation->animation.get(); |
- continue; |
+ if (keyframesRule != existingAnimation->styleRule || keyframesRule->version() != existingAnimation->styleRuleVersion || existingAnimation->specifiedTiming != specifiedTiming) { |
+ ASSERT(!isAnimationStyleChange); |
+ update.updateAnimation(existingAnimationIndex, animation, InertEffect::create( |
+ createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i), |
+ timing, isPaused, animation->unlimitedCurrentTimeInternal()), specifiedTiming, keyframesRule); |
} |
- } |
- ASSERT(!isAnimationStyleChange); |
- update.startAnimation(animationName, InertEffect::create( |
- createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, animationName, keyframeTimingFunction.get(), i), |
- timing, isPaused, 0), specifiedTiming, keyframesRule); |
+ if (isPaused != animation->paused()) { |
+ ASSERT(!isAnimationStyleChange); |
+ update.toggleAnimationIndexPaused(existingAnimationIndex); |
+ } |
+ } else { |
+ ASSERT(!isAnimationStyleChange); |
+ update.startAnimation(name, nameIndex, InertEffect::create( |
+ createKeyframeEffectModel(resolver, animatingElement, element, &style, parentStyle, name, keyframeTimingFunction.get(), i), |
+ timing, isPaused, 0), specifiedTiming, keyframesRule); |
+ } |
} |
} |
- ASSERT(inactive.isEmpty() || cssAnimations); |
- for (const AtomicString& animationName : inactive) { |
- ASSERT(!isAnimationStyleChange); |
- update.cancelAnimation(animationName, *cssAnimations->m_animations.get(animationName)->animation); |
+ for (size_t i = 0; i < cancelRunningAnimationFlags.size(); i++) { |
+ if (cancelRunningAnimationFlags[i]) { |
+ ASSERT(cssAnimations && !isAnimationStyleChange); |
+ update.cancelAnimation(i, *cssAnimations->m_runningAnimations[i]->animation); |
+ } |
} |
} |
@@ -350,20 +365,23 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
// https://code.google.com/p/chromium/issues/detail?id=339847 |
DisableCompositingQueryAsserts disabler; |
- for (const AtomicString& animationName : m_pendingUpdate.cancelledAnimationNames()) { |
- Animation* animation = m_animations.take(animationName)->animation; |
- animation->cancel(); |
- animation->update(TimingUpdateOnDemand); |
+ const Vector<size_t>& cancelledIndices = m_pendingUpdate.cancelledAnimationIndices(); |
+ for (size_t i = cancelledIndices.size(); i-- > 0;) { |
+ ASSERT(i == cancelledIndices.size() - 1 || cancelledIndices[i] < cancelledIndices[i + 1]); |
+ Animation& animation = *m_runningAnimations[cancelledIndices[i]]->animation; |
+ animation.cancel(); |
+ animation.update(TimingUpdateOnDemand); |
+ m_runningAnimations.remove(cancelledIndices[i]); |
} |
- for (const AtomicString& animationName : m_pendingUpdate.animationsWithPauseToggled()) { |
- Animation* animation = m_animations.get(animationName)->animation.get(); |
- if (animation->paused()) |
- animation->unpause(); |
+ for (size_t pausedIndex : m_pendingUpdate.animationIndicesWithPauseToggled()) { |
+ Animation& animation = *m_runningAnimations[pausedIndex]->animation; |
+ if (animation.paused()) |
+ animation.unpause(); |
else |
- animation->pause(); |
- if (animation->outdated()) |
- animation->update(TimingUpdateOnDemand); |
+ animation.pause(); |
+ if (animation.outdated()) |
+ animation.update(TimingUpdateOnDemand); |
} |
for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) |
@@ -375,7 +393,7 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
effect->setModel(entry.effect->model()); |
effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); |
- m_animations.find(entry.name)->value->update(entry); |
+ m_runningAnimations[entry.index]->update(entry); |
} |
for (const auto& entry : m_pendingUpdate.newAnimations()) { |
@@ -388,7 +406,7 @@ void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
animation->pause(); |
animation->update(TimingUpdateOnDemand); |
- m_animations.set(entry.name, new RunningAnimation(animation, entry)); |
+ m_runningAnimations.append(new RunningAnimation(animation, entry)); |
} |
// Transitions that are run on the compositor only update main-thread state |
@@ -613,9 +631,9 @@ void CSSAnimations::calculateTransitionUpdate(CSSAnimationUpdate& update, const |
void CSSAnimations::cancel() |
{ |
- for (const auto& entry : m_animations) { |
- entry.value->animation->cancel(); |
- entry.value->animation->update(TimingUpdateOnDemand); |
+ for (const auto& runningAnimation : m_runningAnimations) { |
+ runningAnimation->animation->cancel(); |
+ runningAnimation->animation->update(TimingUpdateOnDemand); |
} |
for (const auto& entry : m_transitions) { |
@@ -623,7 +641,7 @@ void CSSAnimations::cancel() |
entry.value.animation->update(TimingUpdateOnDemand); |
} |
- m_animations.clear(); |
+ m_runningAnimations.clear(); |
m_transitions.clear(); |
clearPendingUpdate(); |
} |
@@ -818,7 +836,7 @@ DEFINE_TRACE(CSSAnimations) |
{ |
visitor->trace(m_transitions); |
visitor->trace(m_pendingUpdate); |
- visitor->trace(m_animations); |
+ visitor->trace(m_runningAnimations); |
} |
} // namespace blink |