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 = i; j > 0;) | |
293 nameIndex += (nameList[--j] == name); | |
dstockwell
2015/10/16 01:51:37
This code is a bit...smelly.
for (...)
if (...)
alancutter (OOO until 2018)
2015/10/16 01:56:19
Much better, done.
| |
294 | |
291 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused; | 295 const bool isPaused = CSSTimingData::getRepeated(animationData->play StateList(), i) == AnimPlayStatePaused; |
292 | 296 |
293 Timing timing = animationData->convertToTiming(i); | 297 Timing timing = animationData->convertToTiming(i); |
294 Timing specifiedTiming = timing; | 298 Timing specifiedTiming = timing; |
295 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n; | 299 RefPtr<TimingFunction> keyframeTimingFunction = timing.timingFunctio n; |
296 timing.timingFunction = Timing::defaults().timingFunction; | 300 timing.timingFunction = Timing::defaults().timingFunction; |
297 | 301 |
298 RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->fin dKeyframesRule(elementForScoping, animationName); | 302 RefPtrWillBeRawPtr<StyleRuleKeyframes> keyframesRule = resolver->fin dKeyframesRule(elementForScoping, name); |
299 if (!keyframesRule) | 303 if (!keyframesRule) |
300 continue; // Cancel the animation if there's no style rule for i t. | 304 continue; // Cancel the animation if there's no style rule for i t. |
301 | 305 |
306 const RunningAnimation* existingAnimation = nullptr; | |
307 size_t existingAnimationIndex = 0; | |
308 | |
302 if (cssAnimations) { | 309 if (cssAnimations) { |
303 AnimationMap::const_iterator existing(cssAnimations->m_animation s.find(animationName)); | 310 for (size_t i = 0; i < cssAnimations->m_runningAnimations.size() ; i++) { |
304 if (existing != cssAnimations->m_animations.end()) { | 311 const RunningAnimation& runningAnimation = *cssAnimations->m _runningAnimations[i]; |
305 inactive.remove(animationName); | 312 if (runningAnimation.name == name && runningAnimation.nameIn dex == nameIndex) { |
306 | 313 existingAnimation = &runningAnimation; |
307 const RunningAnimation* runningAnimation = existing->value.g et(); | 314 existingAnimationIndex = i; |
308 Animation* animation = runningAnimation->animation.get(); | 315 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 } | 316 } |
316 | |
317 if (isPaused != animation->paused()) { | |
318 ASSERT(!isAnimationStyleChange); | |
319 update.toggleAnimationPaused(animationName); | |
320 } | |
321 | |
322 continue; | |
323 } | 317 } |
324 } | 318 } |
325 | 319 |
326 ASSERT(!isAnimationStyleChange); | 320 if (existingAnimation) { |
327 update.startAnimation(animationName, InertEffect::create( | 321 cancelRunningAnimationFlags[existingAnimationIndex] = false; |
328 createKeyframeEffectModel(resolver, animatingElement, element, & style, parentStyle, animationName, keyframeTimingFunction.get(), i), | 322 |
329 timing, isPaused, 0), specifiedTiming, keyframesRule); | 323 Animation* animation = existingAnimation->animation.get(); |
324 | |
325 if (keyframesRule != existingAnimation->styleRule || keyframesRu le->version() != existingAnimation->styleRuleVersion || existingAnimation->speci fiedTiming != specifiedTiming) { | |
326 ASSERT(!isAnimationStyleChange); | |
327 update.updateAnimation(existingAnimationIndex, animation, In ertEffect::create( | |
328 createKeyframeEffectModel(resolver, animatingElement, el ement, &style, parentStyle, name, keyframeTimingFunction.get(), i), | |
329 timing, isPaused, animation->unlimitedCurrentTimeInterna l()), specifiedTiming, keyframesRule); | |
330 } | |
331 | |
332 if (isPaused != animation->paused()) { | |
333 ASSERT(!isAnimationStyleChange); | |
334 update.toggleAnimationIndexPaused(existingAnimationIndex); | |
335 } | |
336 } else { | |
337 ASSERT(!isAnimationStyleChange); | |
338 update.startAnimation(name, nameIndex, InertEffect::create( | |
339 createKeyframeEffectModel(resolver, animatingElement, elemen t, &style, parentStyle, name, keyframeTimingFunction.get(), i), | |
340 timing, isPaused, 0), specifiedTiming, keyframesRule); | |
341 } | |
330 } | 342 } |
331 } | 343 } |
332 | 344 |
333 ASSERT(inactive.isEmpty() || cssAnimations); | 345 for (size_t i = 0; i < cancelRunningAnimationFlags.size(); i++) { |
334 for (const AtomicString& animationName : inactive) { | 346 if (cancelRunningAnimationFlags[i]) { |
335 ASSERT(!isAnimationStyleChange); | 347 ASSERT(cssAnimations && !isAnimationStyleChange); |
336 update.cancelAnimation(animationName, *cssAnimations->m_animations.get(a nimationName)->animation); | 348 update.cancelAnimation(i, *cssAnimations->m_runningAnimations[i]->an imation); |
349 } | |
337 } | 350 } |
338 } | 351 } |
339 | 352 |
340 void CSSAnimations::maybeApplyPendingUpdate(Element* element) | 353 void CSSAnimations::maybeApplyPendingUpdate(Element* element) |
341 { | 354 { |
342 m_previousActiveInterpolationsForAnimations.clear(); | 355 m_previousActiveInterpolationsForAnimations.clear(); |
343 if (m_pendingUpdate.isEmpty()) | 356 if (m_pendingUpdate.isEmpty()) |
344 return; | 357 return; |
345 | 358 |
346 m_previousActiveInterpolationsForAnimations.swap(m_pendingUpdate.activeInter polationsForAnimations()); | 359 m_previousActiveInterpolationsForAnimations.swap(m_pendingUpdate.activeInter polationsForAnimations()); |
347 | 360 |
348 // FIXME: cancelling, pausing, unpausing animations all query compositingSta te, which is not necessarily up to date here | 361 // 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. | 362 // since we call this from recalc style. |
350 // https://code.google.com/p/chromium/issues/detail?id=339847 | 363 // https://code.google.com/p/chromium/issues/detail?id=339847 |
351 DisableCompositingQueryAsserts disabler; | 364 DisableCompositingQueryAsserts disabler; |
352 | 365 |
353 for (const AtomicString& animationName : m_pendingUpdate.cancelledAnimationN ames()) { | 366 const Vector<size_t>& cancelledIndices = m_pendingUpdate.cancelledAnimationI ndices(); |
354 Animation* animation = m_animations.take(animationName)->animation; | 367 for (size_t i = cancelledIndices.size(); i-- > 0;) { |
355 animation->cancel(); | 368 ASSERT(i == cancelledIndices.size() - 1 || cancelledIndices[i] < cancell edIndices[i + 1]); |
356 animation->update(TimingUpdateOnDemand); | 369 Animation& animation = *m_runningAnimations[cancelledIndices[i]]->animat ion; |
370 animation.cancel(); | |
371 animation.update(TimingUpdateOnDemand); | |
372 m_runningAnimations.remove(cancelledIndices[i]); | |
357 } | 373 } |
358 | 374 |
359 for (const AtomicString& animationName : m_pendingUpdate.animationsWithPause Toggled()) { | 375 for (size_t pausedIndex : m_pendingUpdate.animationIndicesWithPauseToggled() ) { |
360 Animation* animation = m_animations.get(animationName)->animation.get(); | 376 Animation& animation = *m_runningAnimations[pausedIndex]->animation; |
361 if (animation->paused()) | 377 if (animation.paused()) |
362 animation->unpause(); | 378 animation.unpause(); |
363 else | 379 else |
364 animation->pause(); | 380 animation.pause(); |
365 if (animation->outdated()) | 381 if (animation.outdated()) |
366 animation->update(TimingUpdateOnDemand); | 382 animation.update(TimingUpdateOnDemand); |
367 } | 383 } |
368 | 384 |
369 for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) | 385 for (const auto& animation : m_pendingUpdate.updatedCompositorKeyframes()) |
370 animation->setCompositorPending(true); | 386 animation->setCompositorPending(true); |
371 | 387 |
372 for (const auto& entry : m_pendingUpdate.animationsWithUpdates()) { | 388 for (const auto& entry : m_pendingUpdate.animationsWithUpdates()) { |
373 KeyframeEffect* effect = toKeyframeEffect(entry.animation->effect()); | 389 KeyframeEffect* effect = toKeyframeEffect(entry.animation->effect()); |
374 | 390 |
375 effect->setModel(entry.effect->model()); | 391 effect->setModel(entry.effect->model()); |
376 effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); | 392 effect->updateSpecifiedTiming(entry.effect->specifiedTiming()); |
377 | 393 |
378 m_animations.find(entry.name)->value->update(entry); | 394 m_runningAnimations[entry.index]->update(entry); |
379 } | 395 } |
380 | 396 |
381 for (const auto& entry : m_pendingUpdate.newAnimations()) { | 397 for (const auto& entry : m_pendingUpdate.newAnimations()) { |
382 const InertEffect* inertAnimation = entry.effect.get(); | 398 const InertEffect* inertAnimation = entry.effect.get(); |
383 AnimationEventDelegate* eventDelegate = new AnimationEventDelegate(eleme nt, entry.name); | 399 AnimationEventDelegate* eventDelegate = new AnimationEventDelegate(eleme nt, entry.name); |
384 KeyframeEffect* effect = KeyframeEffect::create(element, inertAnimation- >model(), inertAnimation->specifiedTiming(), KeyframeEffect::DefaultPriority, ev entDelegate); | 400 KeyframeEffect* effect = KeyframeEffect::create(element, inertAnimation- >model(), inertAnimation->specifiedTiming(), KeyframeEffect::DefaultPriority, ev entDelegate); |
385 effect->setName(inertAnimation->name()); | 401 effect->setName(inertAnimation->name()); |
386 Animation* animation = element->document().timeline().play(effect); | 402 Animation* animation = element->document().timeline().play(effect); |
387 if (inertAnimation->paused()) | 403 if (inertAnimation->paused()) |
388 animation->pause(); | 404 animation->pause(); |
389 animation->update(TimingUpdateOnDemand); | 405 animation->update(TimingUpdateOnDemand); |
390 | 406 |
391 m_animations.set(entry.name, new RunningAnimation(animation, entry)); | 407 m_runningAnimations.append(new RunningAnimation(animation, entry)); |
392 } | 408 } |
393 | 409 |
394 // Transitions that are run on the compositor only update main-thread state | 410 // 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 | 411 // 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 | 412 // be when transitions are retargeted. Instead of triggering complete style |
397 // recalculation, we find these cases by searching for new transitions that | 413 // recalculation, we find these cases by searching for new transitions that |
398 // have matching cancelled animation property IDs on the compositor. | 414 // have matching cancelled animation property IDs on the compositor. |
399 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffect>, double>> retarg etedCompositorTransitions; | 415 HeapHashMap<CSSPropertyID, std::pair<Member<KeyframeEffect>, double>> retarg etedCompositorTransitions; |
400 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { | 416 for (CSSPropertyID id : m_pendingUpdate.cancelledTransitions()) { |
401 ASSERT(m_transitions.contains(id)); | 417 ASSERT(m_transitions.contains(id)); |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 update.cancelTransition(id); | 622 update.cancelTransition(id); |
607 } else if (entry.value.animation->finishedInternal()) { | 623 } else if (entry.value.animation->finishedInternal()) { |
608 update.finishTransition(id); | 624 update.finishTransition(id); |
609 } | 625 } |
610 } | 626 } |
611 } | 627 } |
612 } | 628 } |
613 | 629 |
614 void CSSAnimations::cancel() | 630 void CSSAnimations::cancel() |
615 { | 631 { |
616 for (const auto& entry : m_animations) { | 632 for (const auto& runningAnimation : m_runningAnimations) { |
617 entry.value->animation->cancel(); | 633 runningAnimation->animation->cancel(); |
618 entry.value->animation->update(TimingUpdateOnDemand); | 634 runningAnimation->animation->update(TimingUpdateOnDemand); |
619 } | 635 } |
620 | 636 |
621 for (const auto& entry : m_transitions) { | 637 for (const auto& entry : m_transitions) { |
622 entry.value.animation->cancel(); | 638 entry.value.animation->cancel(); |
623 entry.value.animation->update(TimingUpdateOnDemand); | 639 entry.value.animation->update(TimingUpdateOnDemand); |
624 } | 640 } |
625 | 641 |
626 m_animations.clear(); | 642 m_runningAnimations.clear(); |
627 m_transitions.clear(); | 643 m_transitions.clear(); |
628 clearPendingUpdate(); | 644 clearPendingUpdate(); |
629 } | 645 } |
630 | 646 |
631 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& u pdate, const Element* animatingElement, double timelineCurrentTime) | 647 void CSSAnimations::calculateAnimationActiveInterpolations(CSSAnimationUpdate& u pdate, const Element* animatingElement, double timelineCurrentTime) |
632 { | 648 { |
633 ElementAnimations* elementAnimations = animatingElement ? animatingElement-> elementAnimations() : nullptr; | 649 ElementAnimations* elementAnimations = animatingElement ? animatingElement-> elementAnimations() : nullptr; |
634 AnimationStack* animationStack = elementAnimations ? &elementAnimations->def aultStack() : nullptr; | 650 AnimationStack* animationStack = elementAnimations ? &elementAnimations->def aultStack() : nullptr; |
635 | 651 |
636 if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpt y()) { | 652 if (update.newAnimations().isEmpty() && update.suppressedAnimations().isEmpt y()) { |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
811 return false; | 827 return false; |
812 default: | 828 default: |
813 return true; | 829 return true; |
814 } | 830 } |
815 } | 831 } |
816 | 832 |
817 DEFINE_TRACE(CSSAnimations) | 833 DEFINE_TRACE(CSSAnimations) |
818 { | 834 { |
819 visitor->trace(m_transitions); | 835 visitor->trace(m_transitions); |
820 visitor->trace(m_pendingUpdate); | 836 visitor->trace(m_pendingUpdate); |
821 visitor->trace(m_animations); | 837 visitor->trace(m_runningAnimations); |
822 } | 838 } |
823 | 839 |
824 } // namespace blink | 840 } // namespace blink |
OLD | NEW |