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

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: Address comments Created 5 years, 11 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 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 return nullptr; 220 return nullptr;
221 } 221 }
222 222
223 CSSAnimations::CSSAnimations() 223 CSSAnimations::CSSAnimations()
224 { 224 {
225 } 225 }
226 226
227 const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPl ayer& player) 227 const AtomicString CSSAnimations::getAnimationNameForInspector(const AnimationPl ayer& player)
228 { 228 {
229 for (const auto& it : m_animations) { 229 for (const auto& it : m_animations) {
230 if (it.value->sequenceNumber() == player.sequenceNumber()) 230 if (it.value.player->sequenceNumber() == player.sequenceNumber())
231 return it.key; 231 return it.key;
232 } 232 }
233 return nullAtom; 233 return nullAtom;
234 } 234 }
235 235
236 PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(const Element* animatingElement, Element& element, const RenderStyle& style, RenderSty le* parentStyle, StyleResolver* resolver) 236 PassOwnPtrWillBeRawPtr<CSSAnimationUpdate> CSSAnimations::calculateUpdate(const Element* animatingElement, Element& element, const RenderStyle& style, RenderSty le* parentStyle, StyleResolver* resolver)
237 { 237 {
238 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = adoptPtrWillBeNoop(new CSSAn imationUpdate()); 238 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = adoptPtrWillBeNoop(new CSSAn imationUpdate());
239 calculateAnimationUpdate(update.get(), animatingElement, element, style, par entStyle, resolver); 239 calculateAnimationUpdate(update.get(), animatingElement, element, style, par entStyle, resolver);
240 calculateAnimationActiveInterpolations(update.get(), animatingElement, eleme nt.document().timeline().currentTimeInternal()); 240 calculateAnimationActiveInterpolations(update.get(), animatingElement, eleme nt.document().timeline().currentTimeInternal());
241 calculateTransitionUpdate(update.get(), animatingElement, style); 241 calculateTransitionUpdate(update.get(), animatingElement, style);
242 calculateTransitionActiveInterpolations(update.get(), animatingElement, elem ent.document().timeline().currentTimeInternal()); 242 calculateTransitionActiveInterpolations(update.get(), animatingElement, elem ent.document().timeline().currentTimeInternal());
243 return update->isEmpty() ? nullptr : update.release(); 243 return update->isEmpty() ? nullptr : update.release();
244 } 244 }
245 245
246 void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E lement* animatingElement, Element& element, const RenderStyle& style, RenderStyl e* parentStyle, StyleResolver* resolver) 246 void CSSAnimations::calculateAnimationUpdate(CSSAnimationUpdate* update, const E lement* animatingElement, Element& element, const RenderStyle& style, RenderStyl e* parentStyle, StyleResolver* resolver)
247 { 247 {
248 const ActiveAnimations* activeAnimations = animatingElement ? animatingEleme nt->activeAnimations() : nullptr; 248 const ActiveAnimations* activeAnimations = animatingElement ? animatingEleme nt->activeAnimations() : nullptr;
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
280 const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScoped KeyframesRule(resolver, elementForScoping, animationName.impl());
278 if (cssAnimations) { 281 if (cssAnimations) {
279 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName)); 282 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName));
280 if (existing != cssAnimations->m_animations.end()) { 283 if (existing != cssAnimations->m_animations.end()) {
281 inactive.remove(animationName); 284 inactive.remove(animationName);
282 285
283 AnimationPlayer* player = existing->value.get(); 286 const RunningAnimation& runningAnimation = existing->value;
287 AnimationPlayer* player = runningAnimation.player.get();
284 288
285 // FIXME: Should handle changes in the timing function. 289 ASSERT(keyframesRule);
286 if (timing != player->source()->specifiedTiming()) { 290 if (keyframesRule->styleChangeCounter() != runningAnimation. styleChangeCounter || runningAnimation.specifiedTiming != newTiming) {
287 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
288
289 AnimatableValueKeyframeVector resolvedKeyframes; 291 AnimatableValueKeyframeVector resolvedKeyframes;
290 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes ); 292 resolveKeyframes(resolver, animatingElement, element, st yle, parentStyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes );
291 293
292 update->updateAnimationTiming(player, InertAnimation::cr eate(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes), 294 update->updateAnimation(animationName, player, InertAnim ation::create(AnimatableValueKeyframeEffectModel::create(resolvedKeyframes),
293 timing, isPaused, player->currentTimeInternal()), ti ming); 295 timing, isPaused, player->currentTimeInternal()), ne wTiming, keyframesRule->styleChangeCounter());
294 } 296 }
295 297
296 if (isPaused != player->paused()) { 298 if (isPaused != player->paused()) {
297 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange()); 299 ASSERT(!activeAnimations || !activeAnimations->isAnimati onStyleChange());
298 update->toggleAnimationPaused(animationName); 300 update->toggleAnimationPaused(animationName);
299 } 301 }
300 302
301 continue; 303 continue;
302 } 304 }
303 } 305 }
304 306
305 AnimatableValueKeyframeVector resolvedKeyframes; 307 AnimatableValueKeyframeVector resolvedKeyframes;
306 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes); 308 resolveKeyframes(resolver, animatingElement, element, style, parentS tyle, animationName, keyframeTimingFunction.get(), resolvedKeyframes);
307 if (!resolvedKeyframes.isEmpty()) { 309 if (!resolvedKeyframes.isEmpty()) {
308 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange()); 310 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleC hange());
309 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) ); 311 unsigned styleChangeCounter = keyframesRule ? keyframesRule->sty leChangeCounter() : 0;
312 update->startAnimation(animationName, InertAnimation::create(Ani matableValueKeyframeEffectModel::create(resolvedKeyframes), timing, isPaused, 0) , newTiming, styleChangeCounter);
310 } 313 }
311 } 314 }
312 } 315 }
313 316
314 ASSERT(inactive.isEmpty() || cssAnimations); 317 ASSERT(inactive.isEmpty() || cssAnimations);
315 for (const AtomicString& animationName : inactive) { 318 for (const AtomicString& animationName : inactive) {
316 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ; 319 ASSERT(!activeAnimations || !activeAnimations->isAnimationStyleChange()) ;
317 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName)); 320 update->cancelAnimation(animationName, *cssAnimations->m_animations.get( animationName).player);
318 } 321 }
319 } 322 }
320 323
321 void CSSAnimations::maybeApplyPendingUpdate(Element* element) 324 void CSSAnimations::maybeApplyPendingUpdate(Element* element)
322 { 325 {
323 if (!m_pendingUpdate) { 326 if (!m_pendingUpdate) {
324 m_previousActiveInterpolationsForAnimations.clear(); 327 m_previousActiveInterpolationsForAnimations.clear();
325 return; 328 return;
326 } 329 }
327 330
328 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release(); 331 OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release();
329 332
330 m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolation sForAnimations()); 333 m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolation sForAnimations());
331 334
332 // FIXME: cancelling, pausing, unpausing animations all query compositingSta te, which is not necessarily up to date here 335 // FIXME: cancelling, pausing, unpausing animations all query compositingSta te, which is not necessarily up to date here
333 // since we call this from recalc style. 336 // since we call this from recalc style.
334 // https://code.google.com/p/chromium/issues/detail?id=339847 337 // https://code.google.com/p/chromium/issues/detail?id=339847
335 DisableCompositingQueryAsserts disabler; 338 DisableCompositingQueryAsserts disabler;
336 339
337 for (const AtomicString& animationName : update->cancelledAnimationNames()) { 340 for (const AtomicString& animationName : update->cancelledAnimationNames()) {
338 RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animation Name); 341 RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animation Name).player;
339 player->cancel(); 342 player->cancel();
340 player->update(TimingUpdateOnDemand); 343 player->update(TimingUpdateOnDemand);
341 } 344 }
342 345
343 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) { 346 for (const AtomicString& animationName : update->animationsWithPauseToggled( )) {
344 AnimationPlayer* player = m_animations.get(animationName); 347 AnimationPlayer* player = m_animations.get(animationName).player.get();
345 if (player->paused()) 348 if (player->paused())
346 player->unpause(); 349 player->unpause();
347 else 350 else
348 player->pause(); 351 player->pause();
349 if (player->outdated()) 352 if (player->outdated())
350 player->update(TimingUpdateOnDemand); 353 player->update(TimingUpdateOnDemand);
351 } 354 }
352 355
353 for (const auto& timingUpdate : update->animationsWithTimingUpdates()) { 356 for (const auto& entry : update->animationsWithUpdates()) {
354 timingUpdate.player->source()->updateSpecifiedTiming(timingUpdate.newTim ing); 357 ASSERT(entry.player->source()->isAnimation());
355 timingUpdate.player->update(TimingUpdateOnDemand); 358 Animation* animation = static_cast<Animation*>(entry.player->source());
dstockwell 2014/12/30 00:59:12 use toAnimation() and drop the assert
shend 2015/01/02 01:58:29 Done.
359
360 animation->setEffect(entry.animation->effect());
361 animation->updateSpecifiedTiming(entry.animation->specifiedTiming());
362
363 auto& runningAnimation = m_animations.find(entry.name)->value;
364 runningAnimation.styleChangeCounter = entry.styleChangeCounter;
365 runningAnimation.specifiedTiming = entry.newTiming;
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
378 RunningAnimation runningAnimation;
379 runningAnimation.player = player;
380 runningAnimation.specifiedTiming = entry.timing;
381 runningAnimation.styleChangeCounter = entry.styleChangeCounter;
382
383 m_animations.set(entry.name, runningAnimation);
368 } 384 }
369 385
370 // Transitions that are run on the compositor only update main-thread state 386 // 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 387 // 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 388 // be when transitions are retargeted. Instead of triggering complete style
373 // recalculation, we find these cases by searching for new transitions that 389 // recalculation, we find these cases by searching for new transitions that
374 // have matching cancelled animation property IDs on the compositor. 390 // have matching cancelled animation property IDs on the compositor.
375 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions; 391 WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, do uble>> retargetedCompositorTransitions;
376 for (CSSPropertyID id : update->cancelledTransitions()) { 392 for (CSSPropertyID id : update->cancelledTransitions()) {
377 ASSERT(m_transitions.contains(id)); 393 ASSERT(m_transitions.contains(id));
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 // ASSERT(player.finishedInternal() || !(activeAnimations && act iveAnimations->isAnimationStyleChange())); 563 // ASSERT(player.finishedInternal() || !(activeAnimations && act iveAnimations->isAnimationStyleChange()));
548 update->cancelTransition(id); 564 update->cancelTransition(id);
549 } 565 }
550 } 566 }
551 } 567 }
552 } 568 }
553 569
554 void CSSAnimations::cancel() 570 void CSSAnimations::cancel()
555 { 571 {
556 for (const auto& entry : m_animations) { 572 for (const auto& entry : m_animations) {
557 entry.value->cancel(); 573 entry.value.player->cancel();
558 entry.value->update(TimingUpdateOnDemand); 574 entry.value.player->update(TimingUpdateOnDemand);
559 } 575 }
560 576
561 for (const auto& entry : m_transitions) { 577 for (const auto& entry : m_transitions) {
562 entry.value.player->cancel(); 578 entry.value.player->cancel();
563 entry.value.player->update(TimingUpdateOnDemand); 579 entry.value.player->update(TimingUpdateOnDemand);
564 } 580 }
565 581
566 m_animations.clear(); 582 m_animations.clear();
567 m_transitions.clear(); 583 m_transitions.clear();
568 m_pendingUpdate = nullptr; 584 m_pendingUpdate = nullptr;
569 } 585 }
570 586
571 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u pdate, const Element* animatingElement, double timelineCurrentTime) 587 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate* u pdate, const Element* animatingElement, double timelineCurrentTime)
572 { 588 {
573 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr; 589 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr;
574 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr; 590 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr;
575 591
576 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) { 592 if (update->newAnimations().isEmpty() && update->suppressedAnimationAnimatio nPlayers().isEmpty()) {
577 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime)); 593 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> acti veInterpolationsForAnimations(AnimationStack::activeInterpolations(animationStac k, 0, 0, Animation::DefaultPriority, timelineCurrentTime));
578 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations); 594 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAn imations);
579 return; 595 return;
580 } 596 }
581 597
582 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations; 598 WillBeHeapVector<RawPtrWillBeMember<InertAnimation>> newAnimations;
583 for (const auto& newAnimation : update->newAnimations()) 599 for (const auto& newAnimation : update->newAnimations())
584 newAnimations.append(newAnimation.animation.get()); 600 newAnimations.append(newAnimation.animation.get());
585 for (const auto& updatedAnimation : update->animationsWithTimingUpdates()) 601 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. 602 newAnimations.append(updatedAnimation.animation.get()); // Animations wi th updates use a temporary InertAnimation for the current frame.
587 603
588 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime)); 604 WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation>> activeIn terpolationsForAnimations(AnimationStack::activeInterpolations(animationStack, & newAnimations, &update->suppressedAnimationAnimationPlayers(), Animation::Defaul tPriority, timelineCurrentTime));
589 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions); 605 update->adoptActiveInterpolationsForAnimations(activeInterpolationsForAnimat ions);
590 } 606 }
591 607
592 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime) 608 void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* animatingElement, double timelineCurrentTime)
593 { 609 {
594 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr; 610 ActiveAnimations* activeAnimations = animatingElement ? animatingElement->ac tiveAnimations() : nullptr;
595 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr; 611 AnimationStack* animationStack = activeAnimations ? &activeAnimations->defau ltStack() : nullptr;
596 612
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 } 778 }
763 779
764 void CSSAnimationUpdate::trace(Visitor* visitor) 780 void CSSAnimationUpdate::trace(Visitor* visitor)
765 { 781 {
766 #if ENABLE(OILPAN) 782 #if ENABLE(OILPAN)
767 visitor->trace(m_newTransitions); 783 visitor->trace(m_newTransitions);
768 visitor->trace(m_activeInterpolationsForAnimations); 784 visitor->trace(m_activeInterpolationsForAnimations);
769 visitor->trace(m_activeInterpolationsForTransitions); 785 visitor->trace(m_activeInterpolationsForTransitions);
770 visitor->trace(m_newAnimations); 786 visitor->trace(m_newAnimations);
771 visitor->trace(m_suppressedAnimationPlayers); 787 visitor->trace(m_suppressedAnimationPlayers);
772 visitor->trace(m_animationsWithTimingUpdates); 788 visitor->trace(m_animationsWithUpdates);
773 #endif 789 #endif
774 } 790 }
775 791
776 } // namespace blink 792 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698