Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(767)

Side by Side Diff: Source/core/animation/css/CSSAnimations.cpp

Issue 814083003: Update animation when changes in animation keyframes are detected. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Rebase and address comments Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 203
204 } // namespace 204 } // namespace
205 205
206 CSSAnimations::CSSAnimations() 206 CSSAnimations::CSSAnimations()
207 { 207 {
208 } 208 }
209 209
210 const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPl ayer& player) 210 const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPl ayer& player)
211 { 211 {
212 for (const auto& it : m_animations) { 212 for (const auto& it : m_animations) {
213 if (it.value->sequenceNumber() == player.sequenceNumber()) 213 if (it.value.player->sequenceNumber() == player.sequenceNumber())
214 return it.key; 214 return it.key;
215 } 215 }
216 return nullAtom; 216 return nullAtom;
217 } 217 }
218 218
219 bool CSSAnimations::isTransitionAnimationForInspector(const AnimationPlayer& pla yer) const 219 bool CSSAnimations::isTransitionAnimationForInspector(const AnimationPlayer& pla yer) const
220 { 220 {
221 for (const auto& it : m_transitions) { 221 for (const auto& it : m_transitions) {
222 if (it.value.player->sequenceNumber() == player.sequenceNumber()) 222 if (it.value.player->sequenceNumber() == player.sequenceNumber())
223 return true; 223 return true;
(...skipping 17 matching lines...) Expand all
241 241
242 #if !ENABLE(ASSERT) 242 #if !ENABLE(ASSERT)
243 // If we're in an animation style change, no animations can have started, be en cancelled or changed play state. 243 // If we're in an animation style change, no animations can have started, be en cancelled or changed play state.
244 // When ASSERT is enabled, we verify this optimization. 244 // When ASSERT is enabled, we verify this optimization.
245 if (activeAnimations && activeAnimations->isAnimationStyleChange()) 245 if (activeAnimations && activeAnimations->isAnimationStyleChange())
246 return; 246 return;
247 #endif 247 #endif
248 248
249 const CSSAnimationData* animationData = style.animations(); 249 const CSSAnimationData* animationData = style.animations();
250 const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->c ssAnimations() : nullptr; 250 const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->c ssAnimations() : nullptr;
251 const Element* elementForScoping = animatingElement ? animatingElement : &el ement;
251 252
252 HashSet<AtomicString> inactive; 253 HashSet<AtomicString> inactive;
253 if (cssAnimations) { 254 if (cssAnimations) {
254 for (const auto& entry : cssAnimations->m_animations) 255 for (const auto& entry : cssAnimations->m_animations)
255 inactive.add(entry.key); 256 inactive.add(entry.key);
256 } 257 }
257 258
258 if (style.display() != NONE) { 259 if (style.display() != NONE) {
259 for (size_t i = 0; animationData && i < animationData->nameList().size() ; ++i) { 260 for (size_t i = 0; animationData && i < animationData->nameList().size() ; ++i) {
260 AtomicString animationName(animationData->nameList()[i]); 261 AtomicString animationName(animationData->nameList()[i]);
261 if (animationName == CSSAnimationData::initialName()) 262 if (animationName == CSSAnimationData::initialName())
262 continue; 263 continue;
263 264
264 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused; 265 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused;
265 266
266 Timing timing = animationData->convertToTiming(i); 267 Timing timing = animationData->convertToTiming(i);
268 Timing specifiedTiming = timing;
267 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n; 269 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n;
268 timing.timingFunction = Timing::defaults().timingFunction; 270 timing.timingFunction = Timing::defaults().timingFunction;
269 271
272 RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->fin dKeyframesRule(elementForScoping, animationName);
273 if (!keyframesRule)
274 continue; // Cancel the animation if there's no style rule for i t.
275
270 if (cssAnimations) { 276 if (cssAnimations) {
271 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName)); 277 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName));
272 if (existing != cssAnimations->m_animations.end()) { 278 if (existing != cssAnimations->m_animations.end()) {
273 inactive.remove(animationName); 279 inactive.remove(animationName);
274 280
275 AnimationPlayer* player = existing->value.get(); 281 const RunningAnimation& runningAnimation = existing->value;
282 AnimationPlayer* player = runningAnimation.player.get();
276 283
277 // FIXME: Should handle changes in the timing function. 284 ASSERT(keyframesRule);
278 if (timing != player->source()->specifiedTiming()) { 285 if (keyframesRule != runningAnimation.styleRule || keyframes Rule->version() != runningAnimation.styleRuleVersion || runningAnimation.specifi edTiming != specifiedTiming) {
279 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
280
281 AnimatableValueKeyframeVector resolvedKeyframes; 286 AnimatableValueKeyframeVector resolvedKeyframes;
282 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes ); 287 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes );
283 288
284 update->updateAnimationTiming(player, InertAnimation::cr eate(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), 289 update->updateAnimation(animationName, player, InertAnim ation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes),
285 timing, isPaused, player->currentTimeInternal()), ti ming); 290 timing, isPaused, player->currentTimeInternal()), sp ecifiedTiming, keyframesRule);
286 } 291 }
287 292
288 if (isPaused != player->paused()) { 293 if (isPaused != player->paused()) {
289 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange()); 294 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
290 update->toggleAnimationPaused(animationName); 295 update->toggleAnimationPaused(animationName);
291 } 296 }
292 297
293 continue; 298 continue;
294 } 299 }
295 } 300 }
296 301
297 AnimatableValueKeyframeVector resolvedKeyframes; 302 AnimatableValueKeyframeVector resolvedKeyframes;
298 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); 303 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
299 if (!resolvedKeyframes.isEmpty()) { 304 if (!resolvedKeyframes.isEmpty()) {
300 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange()); 305 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange());
301 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) ); 306 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) , specifiedTiming, keyframesRule);
302 } 307 }
303 } 308 }
304 } 309 }
305 310
306 ASSERT(inactive.isEmpty() || cssAnimations); 311 ASSERT(inactive.isEmpty() || cssAnimations);
307 for (const AtomicString& animationName : inactive) { 312 for (const AtomicString& animationName : inactive) {
308 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ; 313 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ;
309 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName)); 314 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName).player);
310 } 315 }
311 } 316 }
312 317
313 void CSSAnimations::maybeApplyPendingUpdate(Element* element) 318 void CSSAnimations::maybeApplyPendingUpdate(Element* element)
314 { 319 {
315 if (!m_pendingUpdate) { 320 if (!m_pendingUpdate) {
316 m_previousActiveInterpolationsForAnimations.clear(); 321 m_previousActiveInterpolationsForAnimations.clear();
317 return; 322 return;
318 } 323 }
319 324
320 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release(); 325 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();
321 326
322 m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolation sForAnimations()); 327 m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolation sForAnimations());
323 328
324 // FIXME: cancelling, pausing, unpausing animations all query compositingSta te, which is not necessarily up to date here 329 // FIXME: cancelling, pausing, unpausing animations all query compositingSta te, which is not necessarily up to date here
325 // since we call this from recalc style. 330 // since we call this from recalc style.
326 // https://code.google.com/p/chromium/issues/detail?id=339847 331 // https://code.google.com/p/chromium/issues/detail?id=339847
327 DisableCompositingQueryAsserts disabler; 332 DisableCompositingQueryAsserts disabler;
328 333
329 for (const AtomicString& animationName : update->cancelledAnimationNames()) { 334 for (const AtomicString& animationName : update->cancelledAnimationNames()) {
330 RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animation Name); 335 RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animation Name).player;
331 player->cancel(); 336 player->cancel();
332 player->update(TimingUpdateOnDemand); 337 player->update(TimingUpdateOnDemand);
333 } 338 }
334 339
335 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) { 340 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) {
336 AnimationPlayer* player = m_animations.get(animationName); 341 AnimationPlayer* player = m_animations.get(animationName).player.get();
337 if (player->paused()) 342 if (player->paused())
338 player->unpause(); 343 player->unpause();
339 else 344 else
340 player->pause(); 345 player->pause();
341 if (player->outdated()) 346 if (player->outdated())
342 player->update(TimingUpdateOnDemand); 347 player->update(TimingUpdateOnDemand);
343 } 348 }
344 349
345 for (const auto& timingUpdate : update->animationsWithTimingUpdates()) { 350 for (const auto& entry : update->animationsWithUpdates()) {
346 timingUpdate.player->source()->updateSpecifiedTiming(timingUpdate.newTim ing); 351 Animation* animation = toAnimation(entry.player->source());
347 timingUpdate.player->update(TimingUpdateOnDemand); 352
353 animation->setEffect(entry.animation->effect());
354 animation->updateSpecifiedTiming(entry.animation->specifiedTiming());
355
356 m_animations.find(entry.name)->value.update(entry);
348 } 357 }
349 358
350 for (const auto& entry : update->newAnimations()) { 359 for (const auto& entry : update->newAnimations()) {
351 const InertAnimation* inertAnimation = entry.animation.get(); 360 const InertAnimation* inertAnimation = entry.animation.get();
352 OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillB eNoop(new AnimationEventDelegate(element, entry.name)); 361 OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillB eNoop(new AnimationEventDelegate(element, entry.name));
353 RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, ine rtAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPrio rity, eventDelegate.release()); 362 RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, ine rtAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPrio rity, eventDelegate.release());
354 animation->setName(inertAnimation->name()); 363 animation->setName(inertAnimation->name());
355 RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timelin e().play(animation.get()); 364 RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timelin e().play(animation.get());
356 if (inertAnimation->paused()) 365 if (inertAnimation->paused())
357 player->pause(); 366 player->pause();
358 player->update(TimingUpdateOnDemand); 367 player->update(TimingUpdateOnDemand);
359 m_animations.set(entry.name, player.get()); 368
369 m_animations.set(entry.name, RunningAnimation(player, entry));
esprehn 2015/01/30 02:50:28 We should probably store pointers to RunningAnimat
shend 2015/02/01 23:49:13 Done.
360 } 370 }
361 371
362 // Transitions that are run on the compositor only update main-thread state 372 // Transitions that are run on the compositor only update main-thread state
363 // lazily. However, we need the new state to know what the from state shoud 373 // lazily. However, we need the new state to know what the from state shoud
364 // be when transitions are retargeted. Instead of triggering complete style 374 // be when transitions are retargeted. Instead of triggering complete style
365 // recalculation, we find these cases by searching for new transitions that 375 // recalculation, we find these cases by searching for new transitions that
366 // have matching cancelled animation property IDs on the compositor. 376 // have matching cancelled animation property IDs on the compositor.
367 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions; 377 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions;
368 for (CSSPropertyID id : update->cancelledTransitions()) { 378 for (CSSPropertyID id : update->cancelledTransitions()) {
369 ASSERT(m_transitions.contains(id)); 379 ASSERT(m_transitions.contains(id));
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 // ASSERT(player.playStateInternal() == AnimationPlayer::Finishe d || !(activeAnimations && activeAnimations->isAnimationStyleChange())); 567 // ASSERT(player.playStateInternal() == AnimationPlayer::Finishe d || !(activeAnimations && activeAnimations->isAnimationStyleChange()));
558 update->cancelTransition(id); 568 update->cancelTransition(id);
559 } 569 }
560 } 570 }
561 } 571 }
562 } 572 }
563 573
564 void CSSAnimations::cancel() 574 void CSSAnimations::cancel()
565 { 575 {
566 for (const auto& entry : m_animations) { 576 for (const auto& entry : m_animations) {
567 entry.value->cancel(); 577 entry.value.player->cancel();
568 entry.value->update(TimingUpdateOnDemand); 578 entry.value.player->update(TimingUpdateOnDemand);
569 } 579 }
570 580
571 for (const auto& entry : m_transitions) { 581 for (const auto& entry : m_transitions) {
572 entry.value.player->cancel(); 582 entry.value.player->cancel();
573 entry.value.player->update(TimingUpdateOnDemand); 583 entry.value.player->update(TimingUpdateOnDemand);
574 } 584 }
575 585
576 m_animations.clear(); 586 m_animations.clear();
577 m_transitions.clear(); 587 m_transitions.clear();
578 m_pendingUpdate = nullptr; 588 m_pendingUpdate = nullptr;
579 } 589 }
580 590
581 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u pdate, const Element* animatingElement, double timelineCurrentTime) 591 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u pdate, const Element* animatingElement, double timelineCurrentTime)
582 { 592 {
583 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr; 593 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr;
584 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr; 594 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr;
585 595
586 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) { 596 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) {
587 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime)); 597 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime));
588 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations); 598 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations);
589 return; 599 return;
590 } 600 }
591 601
592 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations; 602 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations;
593 for (const auto& newAnimation : update->newAnimations()) 603 for (const auto& newAnimation : update->newAnimations())
594 newAnimations.append(newAnimation.animation.get()); 604 newAnimations.append(newAnimation.animation.get());
595 for (const auto& updatedAnimation : update->animationsWithTimingUpdates()) 605 for (const auto& updatedAnimation : update->animationsWithUpdates())
596 newAnimations.append(updatedAnimation.animation.get()); // Animations wi th timing updates use a temporary InertAnimation for the current frame. 606 newAnimations.append(updatedAnimation.animation.get()); // Animations wi th updates use a temporary InertAnimation for the current frame.
597 607
598 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime)); 608 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime));
599 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions); 609 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions);
600 } 610 }
601 611
602 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime) 612 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime)
603 { 613 {
604 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr; 614 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr;
605 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr; 615 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr;
606 616
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 } 782 }
773 783
774 void CSSAnimationUpdate::trace(Visitor* visitor) 784 void CSSAnimationUpdate::trace(Visitor* visitor)
775 { 785 {
776 #if ENABLE(OILPAN) 786 #if ENABLE(OILPAN)
777 visitor->trace(m_newTransitions); 787 visitor->trace(m_newTransitions);
778 visitor->trace(m_activeInterpolationsForAnimations); 788 visitor->trace(m_activeInterpolationsForAnimations);
779 visitor->trace(m_activeInterpolationsForTransitions); 789 visitor->trace(m_activeInterpolationsForTransitions);
780 visitor->trace(m_newAnimations); 790 visitor->trace(m_newAnimations);
781 visitor->trace(m_suppressedAnimationPlayers); 791 visitor->trace(m_suppressedAnimationPlayers);
782 visitor->trace(m_animationsWithTimingUpdates); 792 visitor->trace(m_animationsWithUpdates);
783 #endif 793 #endif
784 } 794 }
785 795
786 } // namespace blink 796 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698