| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 } | 184 } |
| 185 | 185 |
| 186 } // namespace | 186 } // namespace |
| 187 | 187 |
| 188 CSSAnimations::CSSAnimations() | 188 CSSAnimations::CSSAnimations() |
| 189 { | 189 { |
| 190 } | 190 } |
| 191 | 191 |
| 192 bool CSSAnimations::isAnimationForInspector(const Animation& animation) | 192 bool CSSAnimations::isAnimationForInspector(const Animation& animation) |
| 193 { | 193 { |
| 194 for (const auto& it : m_animations) { | 194 for (const auto& runningAnimation : m_runningAnimations) { |
| 195 if (it.value->animation->sequenceNumber() == animation.sequenceNumber()) | 195 if (runningAnimation->animation->sequenceNumber() == animation.sequenceN
umber()) |
| 196 return true; | 196 return true; |
| 197 } | 197 } |
| 198 return false; | 198 return false; |
| 199 } | 199 } |
| 200 | 200 |
| 201 bool CSSAnimations::isTransitionAnimationForInspector(const Animation& animation
) const | 201 bool CSSAnimations::isTransitionAnimationForInspector(const Animation& animation
) const |
| 202 { | 202 { |
| 203 for (const auto& it : m_transitions) { | 203 for (const auto& it : m_transitions) { |
| 204 if (it.value.animation->sequenceNumber() == animation.sequenceNumber()) | 204 if (it.value.animation->sequenceNumber() == animation.sequenceNumber()) |
| 205 return true; | 205 return true; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 225 return; | 225 return; |
| 226 | 226 |
| 227 if (!animatingElement->layoutObject() || !animatingElement->layoutObject()->
style()) | 227 if (!animatingElement->layoutObject() || !animatingElement->layoutObject()->
style()) |
| 228 return; | 228 return; |
| 229 | 229 |
| 230 const ComputedStyle& oldStyle = *animatingElement->layoutObject()->style(); | 230 const ComputedStyle& oldStyle = *animatingElement->layoutObject()->style(); |
| 231 if (!oldStyle.shouldCompositeForCurrentAnimations()) | 231 if (!oldStyle.shouldCompositeForCurrentAnimations()) |
| 232 return; | 232 return; |
| 233 | 233 |
| 234 CSSAnimations& cssAnimations = elementAnimations->cssAnimations(); | 234 CSSAnimations& cssAnimations = elementAnimations->cssAnimations(); |
| 235 for (auto& runningAnimation : cssAnimations.m_animations.values()) { | 235 for (auto& runningAnimation : cssAnimations.m_runningAnimations) { |
| 236 Animation& animation = *runningAnimation->animation; | 236 Animation& animation = *runningAnimation->animation; |
| 237 if (animation.effect() && animation.effect()->isKeyframeEffect()) { | 237 if (animation.effect() && animation.effect()->isKeyframeEffect()) { |
| 238 EffectModel* model = toKeyframeEffect(animation.effect())->model(); | 238 EffectModel* model = toKeyframeEffect(animation.effect())->model(); |
| 239 if (model && model->isKeyframeEffectModel()) { | 239 if (model && model->isKeyframeEffectModel()) { |
| 240 KeyframeEffectModelBase* keyframeEffect = toKeyframeEffectModelB
ase(model); | 240 KeyframeEffectModelBase* keyframeEffect = toKeyframeEffectModelB
ase(model); |
| 241 if (keyframeEffect->hasSyntheticKeyframes() && keyframeEffect->s
napshotNeutralCompositorKeyframes(element, oldStyle, style)) | 241 if (keyframeEffect->hasSyntheticKeyframes() && keyframeEffect->s
napshotNeutralCompositorKeyframes(element, oldStyle, style)) |
| 242 update.updateCompositorKeyframes(&animation); | 242 update.updateCompositorKeyframes(&animation); |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 } | 245 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 269 // If we're in an animation style change, no animations can have started, be
en cancelled or changed play state. | 269 // If we're in an animation style change, no animations can have started, be
en cancelled or changed play state. |
| 270 // When ASSERT is enabled, we verify this optimization. | 270 // When ASSERT is enabled, we verify this optimization. |
| 271 if (isAnimationStyleChange) | 271 if (isAnimationStyleChange) |
| 272 return; | 272 return; |
| 273 #endif | 273 #endif |
| 274 | 274 |
| 275 const CSSAnimationData* animationData = style.animations(); | 275 const CSSAnimationData* animationData = style.animations(); |
| 276 const CSSAnimations* cssAnimations = elementAnimations ? &elementAnimations-
>cssAnimations() : nullptr; | 276 const CSSAnimations* cssAnimations = elementAnimations ? &elementAnimations-
>cssAnimations() : nullptr; |
| 277 const Element* elementForScoping = animatingElement ? animatingElement : &el
ement; | 277 const Element* elementForScoping = animatingElement ? animatingElement : &el
ement; |
| 278 | 278 |
| 279 HashSet<AtomicString> inactive; | 279 Vector<bool> cancelRunningAnimationFlags(cssAnimations ? cssAnimations->m_ru
nningAnimations.size() : 0); |
| 280 if (cssAnimations) { | 280 for (bool& flag : cancelRunningAnimationFlags) |
| 281 for (const auto& entry : cssAnimations->m_animations) | 281 flag = true; |
| 282 inactive.add(entry.key); | |
| 283 } | |
| 284 | 282 |
| 285 if (style.display() != NONE) { | 283 if (animationData && style.display() != NONE) { |
| 286 for (size_t i = 0; animationData && i < animationData->nameList().size()
; ++i) { | 284 const Vector<AtomicString>& nameList = animationData->nameList(); |
| 287 AtomicString animationName(animationData->nameList()[i]); | 285 for (size_t i = 0; i < nameList.size(); ++i) { |
| 288 if (animationName == CSSAnimationData::initialName()) | 286 AtomicString name = nameList[i]; |
| 287 if (name == CSSAnimationData::initialName()) |
| 289 continue; | 288 continue; |
| 290 | 289 |
| 290 // Find n where this is the nth occurence of this animation name. |
| 291 size_t nameIndex = 0; |
| 292 for (size_t j = 0; j < i; j++) { |
| 293 if (nameList[j] == name) |
| 294 nameIndex++; |
| 295 } |
| 296 |
| 291 const bool isPaused = CSSTimingData::getRepeated(animationData->play
StateList(), i) == AnimPlayStatePaused; | 297 const bool isPaused = CSSTimingData::getRepeated(animationData->play
StateList(), i) == AnimPlayStatePaused; |
| 292 | 298 |
| 293 Timing timing = animationData->convertToTiming(i); | 299 Timing timing = animationData->convertToTiming(i); |
| 294 Timing specifiedTiming = timing; | 300 Timing specifiedTiming = timing; |
| 295 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio
n; | 301 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio
n; |
| 296 timing.timingFunction = Timing::defaults().timingFunction; | 302 timing.timingFunction = Timing::defaults().timingFunction; |
| 297 | 303 |
| 298 RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->fin
dKeyframesRule(elementForScoping, animationName); | 304 RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->fin
dKeyframesRule(elementForScoping, name); |
| 299 if (!keyframesRule) | 305 if (!keyframesRule) |
| 300 continue; // Cancel the animation if there's no style rule for i
t. | 306 continue; // Cancel the animation if there's no style rule for i
t. |
| 301 | 307 |
| 308 const RunningAnimation* existingAnimation = nullptr; |
| 309 size_t existingAnimationIndex = 0; |
| 310 |
| 302 if (cssAnimations) { | 311 if (cssAnimations) { |
| 303 AnimationMap::const_iterator existing(cssAnimations->m_animation
s.find(animationName)); | 312 for (size_t i = 0; i < cssAnimations->m_runningAnimations.size()
; i++) { |
| 304 if (existing != cssAnimations->m_animations.end()) { | 313 const RunningAnimation& runningAnimation = *cssAnimations->m
_runningAnimations[i]; |
| 305 inactive.remove(animationName); | 314 if (runningAnimation.name == name && runningAnimation.nameIn
dex == nameIndex) { |
| 306 | 315 existingAnimation = &runningAnimation; |
| 307 const RunningAnimation* runningAnimation = existing->value.g
et(); | 316 existingAnimationIndex = i; |
| 308 Animation* animation = runningAnimation->animation.get(); | 317 break; |
| 309 | |
| 310 if (keyframesRule != runningAnimation->styleRule || keyframe
sRule->version() != runningAnimation->styleRuleVersion || runningAnimation->spec
ifiedTiming != specifiedTiming) { | |
| 311 ASSERT(!isAnimationStyleChange); | |
| 312 update.updateAnimation(animationName, animation, InertEf
fect::create( | |
| 313 createKeyframeEffectModel(resolver, animatingElement
, element, &style, parentStyle, animationName, keyframeTimingFunction.get(), i), | |
| 314 timing, isPaused, animation->unlimitedCurrentTimeInt
ernal()), specifiedTiming, keyframesRule); | |
| 315 } | 318 } |
| 316 | |
| 317 if (isPaused != animation->paused()) { | |
| 318 ASSERT(!isAnimationStyleChange); | |
| 319 update.toggleAnimationPaused(animationName); | |
| 320 } | |
| 321 | |
| 322 continue; | |
| 323 } | 319 } |
| 324 } | 320 } |
| 325 | 321 |
| 326 ASSERT(!isAnimationStyleChange); | 322 if (existingAnimation) { |
| 327 update.startAnimation(animationName, InertEffect::create( | 323 cancelRunningAnimationFlags[existingAnimationIndex] = false; |
| 328 createKeyframeEffectModel(resolver, animatingElement, element, &
style, parentStyle, animationName, keyframeTimingFunction.get(), i), | 324 |
| 329 timing, isPaused, 0), specifiedTiming, keyframesRule); | 325 Animation* animation = existingAnimation->animation.get(); |
| 326 |
| 327 if (keyframesRule != existingAnimation->styleRule || keyframesRu
le->version() != existingAnimation->styleRuleVersion || existingAnimation->speci
fiedTiming != specifiedTiming) { |
| 328 ASSERT(!isAnimationStyleChange); |
| 329 update.updateAnimation(existingAnimationIndex, animation, In
ertEffect::create( |
| 330 createKeyframeEffectModel(resolver, animatingElement, el
ement, &style, parentStyle, name, keyframeTimingFunction.get(), i), |
| 331 timing, isPaused, animation->unlimitedCurrentTimeInterna
l()), specifiedTiming, keyframesRule); |
| 332 } |
| 333 |
| 334 if (isPaused != animation->paused()) { |
| 335 ASSERT(!isAnimationStyleChange); |
| 336 update.toggleAnimationIndexPaused(existingAnimationIndex); |
| 337 } |
| 338 } else { |
| 339 ASSERT(!isAnimationStyleChange); |
| 340 update.startAnimation(name, nameIndex, InertEffect::create( |
| 341 createKeyframeEffectModel(resolver, animatingElement, elemen
t, &style, parentStyle, name, keyframeTimingFunction.get(), i), |
| 342 timing, isPaused, 0), specifiedTiming, keyframesRule); |
| 343 } |
| 330 } | 344 } |
| 331 } | 345 } |
| 332 | 346 |
| 333 ASSERT(inactive.isEmpty() || cssAnimations); | 347 for (size_t i = 0; i < cancelRunningAnimationFlags.size(); i++) { |
| 334 for (const AtomicString& animationName : inactive) { | 348 if (cancelRunningAnimationFlags[i]) { |
| 335 ASSERT(!isAnimationStyleChange); | 349 ASSERT(cssAnimations && !isAnimationStyleChange); |
| 336 update.cancelAnimation(animationName, *cssAnimations->m_animations.get(a
nimationName)->animation); | 350 update.cancelAnimation(i, *cssAnimations->m_runningAnimations[i]->an
imation); |
| 351 } |
| 337 } | 352 } |
| 338 } | 353 } |
| 339 | 354 |
| 340 void CSSAnimations::maybeApplyPendingUpdate(Element* element) | 355 void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
| 341 { | 356 { |
| 342 m_previousActiveInterpolationsForAnimations.clear(); | 357 m_previousActiveInterpolationsForAnimations.clear(); |
| 343 if (m_pendingUpdate.isEmpty()) | 358 if (m_pendingUpdate.isEmpty()) |
| 344 return; | 359 return; |
| 345 | 360 |
| 346 m_previousActiveInterpolationsForAnimations.swap(m_pendingUpdate.activeInter
polationsForAnimations()); | 361 m_previousActiveInterpolationsForAnimations.swap(m_pendingUpdate.activeInter
polationsForAnimations()); |
| 347 | 362 |
| 348 // FIXME: cancelling, pausing, unpausing animations all query compositingSta
te, which is not necessarily up to date here | 363 // FIXME: cancelling, pausing, unpausing animations all query compositingSta
te, which is not necessarily up to date here |
| 349 // since we call this from recalc style. | 364 // since we call this from recalc style. |
| 350 // https://code.google.com/p/chromium/issues/detail?id=339847 | 365 // https://code.google.com/p/chromium/issues/detail?id=339847 |
| 351 DisableCompositingQueryAsserts disabler; | 366 DisableCompositingQueryAsserts disabler; |
| 352 | 367 |
| 353 for (const AtomicString& animationName : m_pendingUpdate.cancelledAnimationN
ames()) { | 368 const Vector<size_t>& cancelledIndices = m_pendingUpdate.cancelledAnimationI
ndices(); |
| 354 Animation* animation = m_animations.take(animationName)->animation; | 369 for (size_t i = cancelledIndices.size(); i-- > 0;) { |
| 355 animation->cancel(); | 370 ASSERT(i == cancelledIndices.size() - 1 || cancelledIndices[i] < cancell
edIndices[i + 1]); |
| 356 animation->update(TimingUpdateOnDemand); | 371 Animation& animation = *m_runningAnimations[cancelledIndices[i]]->animat
ion; |
| 372 animation.cancel(); |
| 373 animation.update(TimingUpdateOnDemand); |
| 374 m_runningAnimations.remove(cancelledIndices[i]); |
| 357 } | 375 } |
| 358 | 376 |
| 359 for (const AtomicString& animationName : m_pendingUpdate.animationsWithPause
Toggled()) { | 377 for (size_t pausedIndex : m_pendingUpdate.animationIndicesWithPauseToggled()
) { |
| 360 Animation* animation = m_animations.get(animationName)->animation.get(); | 378 Animation& animation = *m_runningAnimations[pausedIndex]->animation; |
| 361 if (animation->paused()) | 379 if (animation.paused()) |
| 362 animation->unpause(); | 380 animation.unpause(); |
| 363 else | 381 else |
| 364 animation->pause(); | 382 animation.pause(); |
| 365 if (animation->outdated()) | 383 if (animation.outdated()) |
| 366 animation->update(TimingUpdateOnDemand); | 384 animation.update(TimingUpdateOnDemand); |
| 367 } | 385 } |
| 368 | 386 |
| 369 for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) | 387 for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) |
| 370 animation->setCompositorPending(true); | 388 animation->setCompositorPending(true); |
| 371 | 389 |
| 372 for (const auto& entry : m_pendingUpdate.animationsWithUpdates()) { | 390 for (const auto& entry : m_pendingUpdate.animationsWithUpdates()) { |
| 373 KeyframeEffect* effect = toKeyframeEffect(entry.animation->effect()); | 391 KeyframeEffect* effect = toKeyframeEffect(entry.animation->effect()); |
| 374 | 392 |
| 375 effect->setModel(entry.effect->model()); | 393 effect->setModel(entry.effect->model()); |
| 376 effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); | 394 effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); |
| 377 | 395 |
| 378 m_animations.find(entry.name)->value->update(entry); | 396 m_runningAnimations[entry.index]->update(entry); |
| 379 } | 397 } |
| 380 | 398 |
| 381 for (const auto& entry : m_pendingUpdate.newAnimations()) { | 399 for (const auto& entry : m_pendingUpdate.newAnimations()) { |
| 382 const InertEffect* inertAnimation = entry.effect.get(); | 400 const InertEffect* inertAnimation = entry.effect.get(); |
| 383 AnimationEventDelegate* eventDelegate = new AnimationEventDelegate(eleme
nt, entry.name); | 401 AnimationEventDelegate* eventDelegate = new AnimationEventDelegate(eleme
nt, entry.name); |
| 384 KeyframeEffect* effect = KeyframeEffect::create(element, inertAnimation-
>model(), inertAnimation->specifiedTiming(), KeyframeEffect::DefaultPriority, ev
entDelegate); | 402 KeyframeEffect* effect = KeyframeEffect::create(element, inertAnimation-
>model(), inertAnimation->specifiedTiming(), KeyframeEffect::DefaultPriority, ev
entDelegate); |
| 385 effect->setName(inertAnimation->name()); | 403 effect->setName(inertAnimation->name()); |
| 386 Animation* animation = element->document().timeline().play(effect); | 404 Animation* animation = element->document().timeline().play(effect); |
| 387 if (inertAnimation->paused()) | 405 if (inertAnimation->paused()) |
| 388 animation->pause(); | 406 animation->pause(); |
| 389 animation->update(TimingUpdateOnDemand); | 407 animation->update(TimingUpdateOnDemand); |
| 390 | 408 |
| 391 m_animations.set(entry.name, new RunningAnimation(animation, entry)); | 409 m_runningAnimations.append(new RunningAnimation(animation, entry)); |
| 392 } | 410 } |
| 393 | 411 |
| 394 // Transitions that are run on the compositor only update main-thread state | 412 // Transitions that are run on the compositor only update main-thread state |
| 395 // lazily. However, we need the new state to know what the from state shoud | 413 // lazily. However, we need the new state to know what the from state shoud |
| 396 // be when transitions are retargeted. Instead of triggering complete style | 414 // be when transitions are retargeted. Instead of triggering complete style |
| 397 // recalculation, we find these cases by searching for new transitions that | 415 // recalculation, we find these cases by searching for new transitions that |
| 398 // have matching cancelled animation property IDs on the compositor. | 416 // have matching cancelled animation property IDs on the compositor. |
| 399 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffect>, double>> retarg
etedCompositorTransitions; | 417 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffect>, double>> retarg
etedCompositorTransitions; |
| 400 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { | 418 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { |
| 401 ASSERT(m_transitions.contains(id)); | 419 ASSERT(m_transitions.contains(id)); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 update.cancelTransition(id); | 624 update.cancelTransition(id); |
| 607 } else if (entry.value.animation->finishedInternal()) { | 625 } else if (entry.value.animation->finishedInternal()) { |
| 608 update.finishTransition(id); | 626 update.finishTransition(id); |
| 609 } | 627 } |
| 610 } | 628 } |
| 611 } | 629 } |
| 612 } | 630 } |
| 613 | 631 |
| 614 void CSSAnimations::cancel() | 632 void CSSAnimations::cancel() |
| 615 { | 633 { |
| 616 for (const auto& entry : m_animations) { | 634 for (const auto& runningAnimation : m_runningAnimations) { |
| 617 entry.value->animation->cancel(); | 635 runningAnimation->animation->cancel(); |
| 618 entry.value->animation->update(TimingUpdateOnDemand); | 636 runningAnimation->animation->update(TimingUpdateOnDemand); |
| 619 } | 637 } |
| 620 | 638 |
| 621 for (const auto& entry : m_transitions) { | 639 for (const auto& entry : m_transitions) { |
| 622 entry.value.animation->cancel(); | 640 entry.value.animation->cancel(); |
| 623 entry.value.animation->update(TimingUpdateOnDemand); | 641 entry.value.animation->update(TimingUpdateOnDemand); |
| 624 } | 642 } |
| 625 | 643 |
| 626 m_animations.clear(); | 644 m_runningAnimations.clear(); |
| 627 m_transitions.clear(); | 645 m_transitions.clear(); |
| 628 clearPendingUpdate(); | 646 clearPendingUpdate(); |
| 629 } | 647 } |
| 630 | 648 |
| 631 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& u
pdate, const Element* animatingElement, double timelineCurrentTime) | 649 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& u
pdate, const Element* animatingElement, double timelineCurrentTime) |
| 632 { | 650 { |
| 633 ElementAnimations* elementAnimations = animatingElement ? animatingElement->
elementAnimations() : nullptr; | 651 ElementAnimations* elementAnimations = animatingElement ? animatingElement->
elementAnimations() : nullptr; |
| 634 AnimationStack* animationStack = elementAnimations ? &elementAnimations->def
aultStack() : nullptr; | 652 AnimationStack* animationStack = elementAnimations ? &elementAnimations->def
aultStack() : nullptr; |
| 635 | 653 |
| 636 if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpt
y()) { | 654 if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpt
y()) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 return false; | 829 return false; |
| 812 default: | 830 default: |
| 813 return true; | 831 return true; |
| 814 } | 832 } |
| 815 } | 833 } |
| 816 | 834 |
| 817 DEFINE_TRACE(CSSAnimations) | 835 DEFINE_TRACE(CSSAnimations) |
| 818 { | 836 { |
| 819 visitor->trace(m_transitions); | 837 visitor->trace(m_transitions); |
| 820 visitor->trace(m_pendingUpdate); | 838 visitor->trace(m_pendingUpdate); |
| 821 visitor->trace(m_animations); | 839 visitor->trace(m_runningAnimations); |
| 822 } | 840 } |
| 823 | 841 |
| 824 } // namespace blink | 842 } // namespace blink |
| OLD | NEW |