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

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: Add tests for changing timing function Created 5 years, 12 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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 249
250 #if !ENABLE(ASSERT) 250 #if !ENABLE(ASSERT)
251 // If we're in an animation style change, no animations can have started, be en cancelled or changed play state. 251 // If we're in an animation style change, no animations can have started, be en cancelled or changed play state.
252 // When ASSERT is enabled, we verify this optimization. 252 // When ASSERT is enabled, we verify this optimization.
253 if (activeAnimations && activeAnimations->isAnimationStyleChange()) 253 if (activeAnimations && activeAnimations->isAnimationStyleChange())
254 return; 254 return;
255 #endif 255 #endif
256 256
257 const CSSAnimationData* animationData = style.animations(); 257 const CSSAnimationData* animationData = style.animations();
258 const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->c ssAnimations() : nullptr; 258 const CSSAnimations* cssAnimations = activeAnimations ? &activeAnimations->c ssAnimations() : nullptr;
259 const Element* elementForScoping = animatingElement ? animatingElement : &el ement;
259 260
260 HashSet<AtomicString> inactive; 261 HashSet<AtomicString> inactive;
261 if (cssAnimations) { 262 if (cssAnimations) {
262 for (const auto& entry : cssAnimations->m_animations) 263 for (const auto& entry : cssAnimations->m_animations)
263 inactive.add(entry.key); 264 inactive.add(entry.key);
264 } 265 }
265 266
266 if (style.display() != NONE) { 267 if (style.display() != NONE) {
267 for (size_t i = 0; animationData && i < animationData->nameList().size() ; ++i) { 268 for (size_t i = 0; animationData && i < animationData->nameList().size() ; ++i) {
268 AtomicString animationName(animationData->nameList()[i]); 269 AtomicString animationName(animationData->nameList()[i]);
269 if (animationName == CSSAnimationData::initialName()) 270 if (animationName == CSSAnimationData::initialName())
270 continue; 271 continue;
271 272
272 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused; 273 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused;
273 274
274 Timing timing = animationData->convertToTiming(i); 275 Timing timing = animationData->convertToTiming(i);
276 Timing newTiming = timing;
275 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n; 277 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n;
276 timing.timingFunction = Timing::defaults().timingFunction; 278 timing.timingFunction = Timing::defaults().timingFunction;
277 279
278 if (cssAnimations) { 280 if (cssAnimations) {
279 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName)); 281 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName));
280 if (existing != cssAnimations->m_animations.end()) { 282 if (existing != cssAnimations->m_animations.end()) {
281 inactive.remove(animationName); 283 inactive.remove(animationName);
282 284
283 AnimationPlayer* player = existing->value.get(); 285 AnimationPlayer* player = existing->value.get();
284 286
285 // FIXME: Should handle changes in the timing function. 287 const StyleRuleKeyframes* keyframesRule = CSSAnimations::mat chScopedKeyframesRule(resolver, elementForScoping, animationName.impl());
286 if (timing != player->source()->specifiedTiming()) { 288 ASSERT(keyframesRule);
287 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
288 289
290 auto prevTiming = cssAnimations->m_timings.find(animationNam e);
291 ASSERT(prevTiming != cssAnimations->m_timings.end());
292
293 if (keyframesRule->styleChangeCounter() > player->source()-> styleChangeCounter() || prevTiming->value != newTiming) {
289 AnimatableValueKeyframeVector resolvedKeyframes; 294 AnimatableValueKeyframeVector resolvedKeyframes;
290 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes ); 295 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes );
291 296
292 update->updateAnimationTiming(player, InertAnimation::cr eate(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), 297 update->updateAnimation(player, InertAnimation::create(A nimatableValueKeyframeEffectModel::create(resolvedKeyframes),
293 timing, isPaused, player->currentTimeInternal()), ti ming); 298 timing, isPaused, player->currentTimeInternal()), ne wTiming, keyframesRule->styleChangeCounter());
294 } 299 }
295 300
296 if (isPaused != player->paused()) { 301 if (isPaused != player->paused()) {
297 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange()); 302 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
298 update->toggleAnimationPaused(animationName); 303 update->toggleAnimationPaused(animationName);
299 } 304 }
300 305
301 continue; 306 continue;
302 } 307 }
303 } 308 }
304 309
305 AnimatableValueKeyframeVector resolvedKeyframes; 310 AnimatableValueKeyframeVector resolvedKeyframes;
306 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); 311 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
307 if (!resolvedKeyframes.isEmpty()) { 312 if (!resolvedKeyframes.isEmpty()) {
308 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange()); 313 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange());
309 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) ); 314 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) , newTiming);
310 } 315 }
311 } 316 }
312 } 317 }
313 318
314 ASSERT(inactive.isEmpty() || cssAnimations); 319 ASSERT(inactive.isEmpty() || cssAnimations);
315 for (const AtomicString& animationName : inactive) { 320 for (const AtomicString& animationName : inactive) {
316 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ; 321 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ;
317 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName)); 322 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName));
318 } 323 }
319 } 324 }
(...skipping 23 matching lines...) Expand all
343 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) { 348 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) {
344 AnimationPlayer* player = m_animations.get(animationName); 349 AnimationPlayer* player = m_animations.get(animationName);
345 if (player->paused()) 350 if (player->paused())
346 player->unpause(); 351 player->unpause();
347 else 352 else
348 player->pause(); 353 player->pause();
349 if (player->outdated()) 354 if (player->outdated())
350 player->update(TimingUpdateOnDemand); 355 player->update(TimingUpdateOnDemand);
351 } 356 }
352 357
353 for (const auto& timingUpdate : update->animationsWithTimingUpdates()) { 358 for (const auto& entry : update->animationsWithUpdates()) {
354 timingUpdate.player->source()->updateSpecifiedTiming(timingUpdate.newTim ing); 359 ASSERT(entry.player->source()->isAnimation());
355 timingUpdate.player->update(TimingUpdateOnDemand); 360 Animation* animation = static_cast<Animation*>(entry.player->source());
361
362 animation->setEffect(entry.animation->effect());
363 animation->updateSpecifiedTiming(entry.animation->specifiedTiming());
364 animation->updateStyleChangeCounter(entry.styleChangeCounter);
365 m_timings.set(AtomicString(entry.player->source()->name()), entry.newTim ing);
356 } 366 }
357 367
358 for (const auto& entry : update->newAnimations()) { 368 for (const auto& entry : update->newAnimations()) {
359 const InertAnimation* inertAnimation = entry.animation.get(); 369 const InertAnimation* inertAnimation = entry.animation.get();
360 OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillB eNoop(new AnimationEventDelegate(element, entry.name)); 370 OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillB eNoop(new AnimationEventDelegate(element, entry.name));
361 RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, ine rtAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPrio rity, eventDelegate.release()); 371 RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, ine rtAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPrio rity, eventDelegate.release());
362 animation->setName(inertAnimation->name()); 372 animation->setName(inertAnimation->name());
363 RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timelin e().createAnimationPlayer(animation.get()); 373 RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timelin e().createAnimationPlayer(animation.get());
364 if (inertAnimation->paused()) 374 if (inertAnimation->paused())
365 player->pause(); 375 player->pause();
366 player->update(TimingUpdateOnDemand); 376 player->update(TimingUpdateOnDemand);
367 m_animations.set(entry.name, player.get()); 377 m_animations.set(entry.name, player.get());
378 m_timings.set(entry.name, entry.newTiming);
368 } 379 }
369 380
370 // Transitions that are run on the compositor only update main-thread state 381 // Transitions that are run on the compositor only update main-thread state
371 // lazily. However, we need the new state to know what the from state shoud 382 // lazily. However, we need the new state to know what the from state shoud
372 // be when transitions are retargeted. Instead of triggering complete style 383 // be when transitions are retargeted. Instead of triggering complete style
373 // recalculation, we find these cases by searching for new transitions that 384 // recalculation, we find these cases by searching for new transitions that
374 // have matching cancelled animation property IDs on the compositor. 385 // have matching cancelled animation property IDs on the compositor.
375 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions; 386 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions;
376 for (CSSPropertyID id : update->cancelledTransitions()) { 387 for (CSSPropertyID id : update->cancelledTransitions()) {
377 ASSERT(m_transitions.contains(id)); 388 ASSERT(m_transitions.contains(id));
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 586
576 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) { 587 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) {
577 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime)); 588 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime));
578 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations); 589 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations);
579 return; 590 return;
580 } 591 }
581 592
582 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations; 593 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations;
583 for (const auto& newAnimation : update->newAnimations()) 594 for (const auto& newAnimation : update->newAnimations())
584 newAnimations.append(newAnimation.animation.get()); 595 newAnimations.append(newAnimation.animation.get());
585 for (const auto& updatedAnimation : update->animationsWithTimingUpdates()) 596 for (const auto& updatedAnimation : update->animationsWithUpdates())
586 newAnimations.append(updatedAnimation.animation.get()); // Animations wi th timing updates use a temporary InertAnimation for the current frame. 597 newAnimations.append(updatedAnimation.animation.get()); // Animations wi th updates use a temporary InertAnimation for the current frame.
587 598
588 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime)); 599 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime));
589 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions); 600 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions);
590 } 601 }
591 602
592 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime) 603 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime)
593 { 604 {
594 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr; 605 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr;
595 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr; 606 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr;
596 607
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 } 773 }
763 774
764 void CSSAnimationUpdate::trace(Visitor* visitor) 775 void CSSAnimationUpdate::trace(Visitor* visitor)
765 { 776 {
766 #if ENABLE(OILPAN) 777 #if ENABLE(OILPAN)
767 visitor->trace(m_newTransitions); 778 visitor->trace(m_newTransitions);
768 visitor->trace(m_activeInterpolationsForAnimations); 779 visitor->trace(m_activeInterpolationsForAnimations);
769 visitor->trace(m_activeInterpolationsForTransitions); 780 visitor->trace(m_activeInterpolationsForTransitions);
770 visitor->trace(m_newAnimations); 781 visitor->trace(m_newAnimations);
771 visitor->trace(m_suppressedAnimationPlayers); 782 visitor->trace(m_suppressedAnimationPlayers);
772 visitor->trace(m_animationsWithTimingUpdates); 783 visitor->trace(m_animationsWithUpdates);
773 #endif 784 #endif
774 } 785 }
775 786
776 } // namespace blink 787 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698