layer_animation_controller.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/animation/layer_animation_controller.h" 6 7#include <algorithm> 8 9#include "cc/animation/animation.h" 10#include "cc/animation/animation_registrar.h" 11#include "cc/animation/keyframed_animation_curve.h" 12#include "cc/animation/layer_animation_value_observer.h" 13#include "cc/base/scoped_ptr_algorithm.h" 14#include "third_party/WebKit/Source/Platform/chromium/public/WebAnimationDelegate.h" 15#include "ui/gfx/transform.h" 16 17namespace cc { 18 19LayerAnimationController::LayerAnimationController(int id) 20 : force_sync_(false), 21 registrar_(0), 22 id_(id), 23 is_active_(false), 24 last_tick_time_(0), 25 layer_animation_delegate_(NULL) {} 26 27LayerAnimationController::~LayerAnimationController() { 28 if (registrar_) 29 registrar_->UnregisterAnimationController(this); 30} 31 32scoped_refptr<LayerAnimationController> LayerAnimationController::Create( 33 int id) { 34 return make_scoped_refptr(new LayerAnimationController(id)); 35} 36 37void LayerAnimationController::PauseAnimation(int animation_id, 38 double time_offset) { 39 for (size_t i = 0; i < active_animations_.size(); ++i) { 40 if (active_animations_[i]->id() == animation_id) { 41 active_animations_[i]->SetRunState( 42 Animation::Paused, time_offset + active_animations_[i]->start_time()); 43 } 44 } 45} 46 47struct HasAnimationId { 48 explicit HasAnimationId(int id) : id_(id) {} 49 bool operator()(Animation* animation) const { 50 return animation->id() == id_; 51 } 52 53 private: 54 int id_; 55}; 56 57void LayerAnimationController::RemoveAnimation(int animation_id) { 58 ScopedPtrVector<Animation>& animations = active_animations_; 59 animations.erase(cc::remove_if(&animations, 60 animations.begin(), 61 animations.end(), 62 HasAnimationId(animation_id)), 63 animations.end()); 64 UpdateActivation(NormalActivation); 65} 66 67struct HasAnimationIdAndProperty { 68 HasAnimationIdAndProperty(int id, Animation::TargetProperty target_property) 69 : id_(id), target_property_(target_property) {} 70 bool operator()(Animation* animation) const { 71 return animation->id() == id_ && 72 animation->target_property() == target_property_; 73 } 74 75 private: 76 int id_; 77 Animation::TargetProperty target_property_; 78}; 79 80void LayerAnimationController::RemoveAnimation( 81 int animation_id, 82 Animation::TargetProperty target_property) { 83 ScopedPtrVector<Animation>& animations = active_animations_; 84 animations.erase(cc::remove_if(&animations, 85 animations.begin(), 86 animations.end(), 87 HasAnimationIdAndProperty(animation_id, 88 target_property)), 89 animations.end()); 90 UpdateActivation(NormalActivation); 91} 92 93// According to render layer backing, these are for testing only. 94void LayerAnimationController::SuspendAnimations(double monotonic_time) { 95 for (size_t i = 0; i < active_animations_.size(); ++i) { 96 if (!active_animations_[i]->is_finished()) 97 active_animations_[i]->SetRunState(Animation::Paused, monotonic_time); 98 } 99} 100 101// Looking at GraphicsLayerCA, this appears to be the analog to 102// SuspendAnimations, which is for testing. 103void LayerAnimationController::ResumeAnimations(double monotonic_time) { 104 for (size_t i = 0; i < active_animations_.size(); ++i) { 105 if (active_animations_[i]->run_state() == Animation::Paused) 106 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); 107 } 108} 109 110// Ensures that the list of active animations on the main thread and the impl 111// thread are kept in sync. 112void LayerAnimationController::PushAnimationUpdatesTo( 113 LayerAnimationController* controller_impl) { 114 DCHECK(this != controller_impl); 115 if (force_sync_) { 116 ReplaceImplThreadAnimations(controller_impl); 117 force_sync_ = false; 118 } else { 119 PurgeAnimationsMarkedForDeletion(); 120 PushNewAnimationsToImplThread(controller_impl); 121 122 // Remove finished impl side animations only after pushing, 123 // and only after the animations are deleted on the main thread 124 // this insures we will never push an animation twice. 125 RemoveAnimationsCompletedOnMainThread(controller_impl); 126 127 PushPropertiesToImplThread(controller_impl); 128 } 129 controller_impl->UpdateActivation(NormalActivation); 130 UpdateActivation(NormalActivation); 131} 132 133void LayerAnimationController::TransferAnimationsTo( 134 LayerAnimationController* other_controller) { 135 other_controller->active_animations_.clear(); 136 active_animations_.swap(other_controller->active_animations_); 137 UpdateActivation(NormalActivation); 138 set_force_sync(); 139 other_controller->UpdateActivation(NormalActivation); 140 other_controller->set_force_sync(); 141 other_controller->SetAnimationRegistrar(registrar_); 142} 143 144void LayerAnimationController::Animate(double monotonic_time) { 145 if (!HasActiveValueObserver()) 146 return; 147 148 StartAnimationsWaitingForNextTick(monotonic_time); 149 StartAnimationsWaitingForStartTime(monotonic_time); 150 StartAnimationsWaitingForTargetAvailability(monotonic_time); 151 ResolveConflicts(monotonic_time); 152 TickAnimations(monotonic_time); 153 last_tick_time_ = monotonic_time; 154} 155 156void LayerAnimationController::AccumulatePropertyUpdates( 157 double monotonic_time, 158 AnimationEventsVector* events) { 159 if (!events) 160 return; 161 162 for (size_t i = 0; i < active_animations_.size(); ++i) { 163 Animation* animation = active_animations_[i]; 164 if (!animation->is_impl_only()) 165 continue; 166 167 if (animation->target_property() == Animation::Opacity) { 168 AnimationEvent event(AnimationEvent::PropertyUpdate, 169 id_, 170 animation->group(), 171 Animation::Opacity, 172 monotonic_time); 173 event.opacity = animation->curve()->ToFloatAnimationCurve()->GetValue( 174 monotonic_time); 175 event.is_impl_only = true; 176 events->push_back(event); 177 } else if (animation->target_property() == Animation::Transform) { 178 AnimationEvent event(AnimationEvent::PropertyUpdate, 179 id_, 180 animation->group(), 181 Animation::Transform, 182 monotonic_time); 183 event.transform = 184 animation->curve()->ToTransformAnimationCurve()->GetValue( 185 monotonic_time); 186 event.is_impl_only = true; 187 events->push_back(event); 188 } 189 } 190} 191 192void LayerAnimationController::UpdateState(bool start_ready_animations, 193 AnimationEventsVector* events) { 194 if (!HasActiveValueObserver()) 195 return; 196 197 if (start_ready_animations) 198 PromoteStartedAnimations(last_tick_time_, events); 199 200 MarkFinishedAnimations(last_tick_time_); 201 MarkAnimationsForDeletion(last_tick_time_, events); 202 203 if (start_ready_animations) { 204 StartAnimationsWaitingForTargetAvailability(last_tick_time_); 205 PromoteStartedAnimations(last_tick_time_, events); 206 } 207 208 AccumulatePropertyUpdates(last_tick_time_, events); 209 210 UpdateActivation(NormalActivation); 211} 212 213void LayerAnimationController::AddAnimation(scoped_ptr<Animation> animation) { 214 active_animations_.push_back(animation.Pass()); 215 UpdateActivation(NormalActivation); 216} 217 218Animation* LayerAnimationController::GetAnimation( 219 int group_id, 220 Animation::TargetProperty target_property) const { 221 for (size_t i = 0; i < active_animations_.size(); ++i) 222 if (active_animations_[i]->group() == group_id && 223 active_animations_[i]->target_property() == target_property) 224 return active_animations_[i]; 225 return 0; 226} 227 228Animation* LayerAnimationController::GetAnimation( 229 Animation::TargetProperty target_property) const { 230 for (size_t i = 0; i < active_animations_.size(); ++i) { 231 size_t index = active_animations_.size() - i - 1; 232 if (active_animations_[index]->target_property() == target_property) 233 return active_animations_[index]; 234 } 235 return 0; 236} 237 238bool LayerAnimationController::HasActiveAnimation() const { 239 for (size_t i = 0; i < active_animations_.size(); ++i) { 240 if (!active_animations_[i]->is_finished()) 241 return true; 242 } 243 return false; 244} 245 246bool LayerAnimationController::IsAnimatingProperty( 247 Animation::TargetProperty target_property) const { 248 for (size_t i = 0; i < active_animations_.size(); ++i) { 249 if (!active_animations_[i]->is_finished() && 250 active_animations_[i]->target_property() == target_property) 251 return true; 252 } 253 return false; 254} 255 256void LayerAnimationController::SetAnimationRegistrar( 257 AnimationRegistrar* registrar) { 258 if (registrar_ == registrar) 259 return; 260 261 if (registrar_) 262 registrar_->UnregisterAnimationController(this); 263 264 registrar_ = registrar; 265 if (registrar_) 266 registrar_->RegisterAnimationController(this); 267 268 UpdateActivation(ForceActivation); 269} 270 271void LayerAnimationController::NotifyAnimationStarted( 272 const AnimationEvent& event, 273 double wall_clock_time) { 274 if (event.is_impl_only) { 275 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_, 276 OnAnimationStarted(event)); 277 if (layer_animation_delegate_) 278 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time); 279 280 return; 281 } 282 283 for (size_t i = 0; i < active_animations_.size(); ++i) { 284 if (active_animations_[i]->group() == event.group_id && 285 active_animations_[i]->target_property() == event.target_property && 286 active_animations_[i]->needs_synchronized_start_time()) { 287 active_animations_[i]->set_needs_synchronized_start_time(false); 288 active_animations_[i]->set_start_time(event.monotonic_time); 289 290 FOR_EACH_OBSERVER(LayerAnimationEventObserver, event_observers_, 291 OnAnimationStarted(event)); 292 if (layer_animation_delegate_) 293 layer_animation_delegate_->notifyAnimationStarted(wall_clock_time); 294 295 return; 296 } 297 } 298} 299 300void LayerAnimationController::NotifyAnimationFinished( 301 const AnimationEvent& event, 302 double wall_clock_time) { 303 if (event.is_impl_only) { 304 if (layer_animation_delegate_) 305 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time); 306 return; 307 } 308 309 for (size_t i = 0; i < active_animations_.size(); ++i) { 310 if (active_animations_[i]->group() == event.group_id && 311 active_animations_[i]->target_property() == event.target_property) { 312 active_animations_[i]->set_received_finished_event(true); 313 if (layer_animation_delegate_) 314 layer_animation_delegate_->notifyAnimationFinished(wall_clock_time); 315 316 return; 317 } 318 } 319} 320 321void LayerAnimationController::NotifyAnimationPropertyUpdate( 322 const AnimationEvent& event) { 323 switch (event.target_property) { 324 case Animation::Opacity: 325 NotifyObserversOpacityAnimated(event.opacity); 326 break; 327 case Animation::Transform: 328 NotifyObserversTransformAnimated(event.transform); 329 break; 330 default: 331 NOTREACHED(); 332 } 333} 334 335void LayerAnimationController::AddValueObserver( 336 LayerAnimationValueObserver* observer) { 337 if (!value_observers_.HasObserver(observer)) 338 value_observers_.AddObserver(observer); 339} 340 341void LayerAnimationController::RemoveValueObserver( 342 LayerAnimationValueObserver* observer) { 343 value_observers_.RemoveObserver(observer); 344} 345 346void LayerAnimationController::AddEventObserver( 347 LayerAnimationEventObserver* observer) { 348 if (!event_observers_.HasObserver(observer)) 349 event_observers_.AddObserver(observer); 350} 351 352void LayerAnimationController::RemoveEventObserver( 353 LayerAnimationEventObserver* observer) { 354 event_observers_.RemoveObserver(observer); 355} 356 357void LayerAnimationController::PushNewAnimationsToImplThread( 358 LayerAnimationController* controller_impl) const { 359 // Any new animations owned by the main thread's controller are cloned and 360 // add to the impl thread's controller. 361 for (size_t i = 0; i < active_animations_.size(); ++i) { 362 // If the animation is already running on the impl thread, there is no 363 // need to copy it over. 364 if (controller_impl->GetAnimation(active_animations_[i]->group(), 365 active_animations_[i]->target_property())) 366 continue; 367 368 // If the animation is not running on the impl thread, it does not 369 // necessarily mean that it needs to be copied over and started; it may 370 // have already finished. In this case, the impl thread animation will 371 // have already notified that it has started and the main thread animation 372 // will no longer need 373 // a synchronized start time. 374 if (!active_animations_[i]->needs_synchronized_start_time()) 375 continue; 376 377 // The new animation should be set to run as soon as possible. 378 Animation::RunState initial_run_state = 379 Animation::WaitingForTargetAvailability; 380 double start_time = 0; 381 scoped_ptr<Animation> to_add(active_animations_[i]->CloneAndInitialize( 382 Animation::ControllingInstance, initial_run_state, start_time)); 383 DCHECK(!to_add->needs_synchronized_start_time()); 384 controller_impl->AddAnimation(to_add.Pass()); 385 } 386} 387 388struct IsCompleted { 389 explicit IsCompleted(const LayerAnimationController& main_thread_controller) 390 : main_thread_controller_(main_thread_controller) {} 391 bool operator()(Animation* animation) const { 392 if (animation->is_impl_only()) { 393 return (animation->run_state() == Animation::WaitingForDeletion); 394 } else { 395 return !main_thread_controller_.GetAnimation( 396 animation->group(), 397 animation->target_property()); 398 } 399 } 400 401 private: 402 const LayerAnimationController& main_thread_controller_; 403}; 404 405void LayerAnimationController::RemoveAnimationsCompletedOnMainThread( 406 LayerAnimationController* controller_impl) const { 407 // Delete all impl thread animations for which there is no corresponding 408 // main thread animation. Each iteration, 409 // controller->active_animations_.size() is decremented or i is incremented 410 // guaranteeing progress towards loop termination. 411 ScopedPtrVector<Animation>& animations = 412 controller_impl->active_animations_; 413 animations.erase(cc::remove_if(&animations, 414 animations.begin(), 415 animations.end(), 416 IsCompleted(*this)), 417 animations.end()); 418} 419 420void LayerAnimationController::PushPropertiesToImplThread( 421 LayerAnimationController* controller_impl) const { 422 for (size_t i = 0; i < active_animations_.size(); ++i) { 423 Animation* current_impl = 424 controller_impl->GetAnimation( 425 active_animations_[i]->group(), 426 active_animations_[i]->target_property()); 427 if (current_impl) 428 active_animations_[i]->PushPropertiesTo(current_impl); 429 } 430} 431 432void LayerAnimationController::StartAnimationsWaitingForNextTick( 433 double monotonic_time) { 434 for (size_t i = 0; i < active_animations_.size(); ++i) { 435 if (active_animations_[i]->run_state() == Animation::WaitingForNextTick) 436 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); 437 } 438} 439 440void LayerAnimationController::StartAnimationsWaitingForStartTime( 441 double monotonic_time) { 442 for (size_t i = 0; i < active_animations_.size(); ++i) { 443 if (active_animations_[i]->run_state() == Animation::WaitingForStartTime && 444 active_animations_[i]->start_time() <= monotonic_time) 445 active_animations_[i]->SetRunState(Animation::Starting, monotonic_time); 446 } 447} 448 449void LayerAnimationController::StartAnimationsWaitingForTargetAvailability( 450 double monotonic_time) { 451 // First collect running properties. 452 TargetProperties blocked_properties; 453 for (size_t i = 0; i < active_animations_.size(); ++i) { 454 if (active_animations_[i]->run_state() == Animation::Starting || 455 active_animations_[i]->run_state() == Animation::Running) 456 blocked_properties.insert(active_animations_[i]->target_property()); 457 } 458 459 for (size_t i = 0; i < active_animations_.size(); ++i) { 460 if (active_animations_[i]->run_state() == 461 Animation::WaitingForTargetAvailability) { 462 // Collect all properties for animations with the same group id (they 463 // should all also be in the list of animations). 464 TargetProperties enqueued_properties; 465 enqueued_properties.insert(active_animations_[i]->target_property()); 466 for (size_t j = i + 1; j < active_animations_.size(); ++j) { 467 if (active_animations_[i]->group() == active_animations_[j]->group()) 468 enqueued_properties.insert(active_animations_[j]->target_property()); 469 } 470 471 // Check to see if intersection of the list of properties affected by 472 // the group and the list of currently blocked properties is null. In 473 // any case, the group's target properties need to be added to the list 474 // of blocked properties. 475 bool null_intersection = true; 476 for (TargetProperties::iterator p_iter = enqueued_properties.begin(); 477 p_iter != enqueued_properties.end(); 478 ++p_iter) { 479 if (!blocked_properties.insert(*p_iter).second) 480 null_intersection = false; 481 } 482 483 // If the intersection is null, then we are free to start the animations 484 // in the group. 485 if (null_intersection) { 486 active_animations_[i]->SetRunState( 487 Animation::Starting, monotonic_time); 488 for (size_t j = i + 1; j < active_animations_.size(); ++j) { 489 if (active_animations_[i]->group() == 490 active_animations_[j]->group()) { 491 active_animations_[j]->SetRunState( 492 Animation::Starting, monotonic_time); 493 } 494 } 495 } 496 } 497 } 498} 499 500void LayerAnimationController::PromoteStartedAnimations( 501 double monotonic_time, 502 AnimationEventsVector* events) { 503 for (size_t i = 0; i < active_animations_.size(); ++i) { 504 if (active_animations_[i]->run_state() == Animation::Starting) { 505 active_animations_[i]->SetRunState(Animation::Running, monotonic_time); 506 if (!active_animations_[i]->has_set_start_time()) 507 active_animations_[i]->set_start_time(monotonic_time); 508 if (events) { 509 AnimationEvent started_event( 510 AnimationEvent::Started, 511 id_, 512 active_animations_[i]->group(), 513 active_animations_[i]->target_property(), 514 monotonic_time); 515 started_event.is_impl_only = active_animations_[i]->is_impl_only(); 516 events->push_back(started_event); 517 } 518 } 519 } 520} 521 522void LayerAnimationController::MarkFinishedAnimations(double monotonic_time) { 523 for (size_t i = 0; i < active_animations_.size(); ++i) { 524 if (active_animations_[i]->IsFinishedAt(monotonic_time) && 525 active_animations_[i]->run_state() != Animation::WaitingForDeletion) 526 active_animations_[i]->SetRunState(Animation::Finished, monotonic_time); 527 } 528} 529 530void LayerAnimationController::ResolveConflicts(double monotonic_time) { 531 // Find any animations that are animating the same property and resolve the 532 // confict. We could eventually blend, but for now we'll just abort the 533 // previous animation (where 'previous' means: (1) has a prior start time or 534 // (2) has an equal start time, but was added to the queue earlier, i.e., 535 // has a lower index in active_animations_). 536 for (size_t i = 0; i < active_animations_.size(); ++i) { 537 if (active_animations_[i]->run_state() == Animation::Starting || 538 active_animations_[i]->run_state() == Animation::Running) { 539 for (size_t j = i + 1; j < active_animations_.size(); ++j) { 540 if ((active_animations_[j]->run_state() == Animation::Starting || 541 active_animations_[j]->run_state() == Animation::Running) && 542 active_animations_[i]->target_property() == 543 active_animations_[j]->target_property()) { 544 if (active_animations_[i]->start_time() > 545 active_animations_[j]->start_time()) { 546 active_animations_[j]->SetRunState(Animation::Aborted, 547 monotonic_time); 548 } else { 549 active_animations_[i]->SetRunState(Animation::Aborted, 550 monotonic_time); 551 } 552 } 553 } 554 } 555 } 556} 557 558void LayerAnimationController::MarkAnimationsForDeletion( 559 double monotonic_time, AnimationEventsVector* events) { 560 // Non-aborted animations are marked for deletion after a corresponding 561 // AnimationEvent::Finished event is sent or received. This means that if 562 // we don't have an events vector, we must ensure that non-aborted animations 563 // have received a finished event before marking them for deletion. 564 for (size_t i = 0; i < active_animations_.size(); i++) { 565 int group_id = active_animations_[i]->group(); 566 bool all_anims_with_same_id_are_finished = false; 567 568 // Since deleting an animation on the main thread leads to its deletion 569 // on the impl thread, we only mark a Finished main thread animation for 570 // deletion once it has received a Finished event from the impl thread. 571 bool animation_i_will_send_or_has_received_finish_event = 572 events || active_animations_[i]->received_finished_event(); 573 // If an animation is finished, and not already marked for deletion, 574 // find out if all other animations in the same group are also finished. 575 if (active_animations_[i]->run_state() == Animation::Aborted || 576 (active_animations_[i]->run_state() == Animation::Finished && 577 animation_i_will_send_or_has_received_finish_event)) { 578 all_anims_with_same_id_are_finished = true; 579 for (size_t j = 0; j < active_animations_.size(); ++j) { 580 bool animation_j_will_send_or_has_received_finish_event = 581 events || active_animations_[j]->received_finished_event(); 582 if (group_id == active_animations_[j]->group() && 583 (!active_animations_[j]->is_finished() || 584 (active_animations_[j]->run_state() == Animation::Finished && 585 !animation_j_will_send_or_has_received_finish_event))) { 586 all_anims_with_same_id_are_finished = false; 587 break; 588 } 589 } 590 } 591 if (all_anims_with_same_id_are_finished) { 592 // We now need to remove all animations with the same group id as 593 // group_id (and send along animation finished notifications, if 594 // necessary). 595 for (size_t j = i; j < active_animations_.size(); j++) { 596 if (group_id == active_animations_[j]->group()) { 597 if (events) { 598 AnimationEvent finished_event( 599 AnimationEvent::Finished, 600 id_, 601 active_animations_[j]->group(), 602 active_animations_[j]->target_property(), 603 monotonic_time); 604 finished_event.is_impl_only = active_animations_[j]->is_impl_only(); 605 events->push_back(finished_event); 606 } 607 active_animations_[j]->SetRunState(Animation::WaitingForDeletion, 608 monotonic_time); 609 } 610 } 611 } 612 } 613} 614 615static bool IsWaitingForDeletion(Animation* animation) { 616 return animation->run_state() == Animation::WaitingForDeletion; 617} 618 619void LayerAnimationController::PurgeAnimationsMarkedForDeletion() { 620 ScopedPtrVector<Animation>& animations = active_animations_; 621 animations.erase(cc::remove_if(&animations, 622 animations.begin(), 623 animations.end(), 624 IsWaitingForDeletion), 625 animations.end()); 626} 627 628void LayerAnimationController::ReplaceImplThreadAnimations( 629 LayerAnimationController* controller_impl) const { 630 controller_impl->active_animations_.clear(); 631 for (size_t i = 0; i < active_animations_.size(); ++i) { 632 scoped_ptr<Animation> to_add; 633 if (active_animations_[i]->needs_synchronized_start_time()) { 634 // We haven't received an animation started notification yet, so it 635 // is important that we add it in a 'waiting' and not 'running' state. 636 Animation::RunState initial_run_state = 637 Animation::WaitingForTargetAvailability; 638 double start_time = 0; 639 to_add = active_animations_[i]->CloneAndInitialize( 640 Animation::ControllingInstance, 641 initial_run_state, start_time).Pass(); 642 } else { 643 to_add = active_animations_[i]->Clone( 644 Animation::ControllingInstance).Pass(); 645 } 646 647 controller_impl->AddAnimation(to_add.Pass()); 648 } 649} 650 651void LayerAnimationController::TickAnimations(double monotonic_time) { 652 for (size_t i = 0; i < active_animations_.size(); ++i) { 653 if (active_animations_[i]->run_state() == Animation::Starting || 654 active_animations_[i]->run_state() == Animation::Running || 655 active_animations_[i]->run_state() == Animation::Paused) { 656 double trimmed = 657 active_animations_[i]->TrimTimeToCurrentIteration(monotonic_time); 658 659 // Animation assumes its initial value until it gets the synchronized 660 // start time from the impl thread and can start ticking. 661 if (active_animations_[i]->needs_synchronized_start_time()) 662 trimmed = 0; 663 664 // A just-started animation assumes its initial value. 665 if (active_animations_[i]->run_state() == Animation::Starting && 666 !active_animations_[i]->has_set_start_time()) 667 trimmed = 0; 668 669 switch (active_animations_[i]->target_property()) { 670 case Animation::Transform: { 671 const TransformAnimationCurve* transform_animation_curve = 672 active_animations_[i]->curve()->ToTransformAnimationCurve(); 673 const gfx::Transform transform = 674 transform_animation_curve->GetValue(trimmed); 675 NotifyObserversTransformAnimated(transform); 676 break; 677 } 678 679 case Animation::Opacity: { 680 const FloatAnimationCurve* float_animation_curve = 681 active_animations_[i]->curve()->ToFloatAnimationCurve(); 682 const float opacity = float_animation_curve->GetValue(trimmed); 683 NotifyObserversOpacityAnimated(opacity); 684 break; 685 } 686 687 // Do nothing for sentinel value. 688 case Animation::TargetPropertyEnumSize: 689 NOTREACHED(); 690 } 691 } 692 } 693} 694 695void LayerAnimationController::UpdateActivation(UpdateActivationType type) { 696 bool force = type == ForceActivation; 697 if (registrar_) { 698 if (!active_animations_.empty() && (!is_active_ || force)) 699 registrar_->DidActivateAnimationController(this); 700 else if (active_animations_.empty() && (is_active_ || force)) 701 registrar_->DidDeactivateAnimationController(this); 702 is_active_ = !active_animations_.empty(); 703 } 704} 705 706void LayerAnimationController::NotifyObserversOpacityAnimated(float opacity) { 707 FOR_EACH_OBSERVER(LayerAnimationValueObserver, 708 value_observers_, 709 OnOpacityAnimated(opacity)); 710} 711 712void LayerAnimationController::NotifyObserversTransformAnimated( 713 const gfx::Transform& transform) { 714 FOR_EACH_OBSERVER(LayerAnimationValueObserver, 715 value_observers_, 716 OnTransformAnimated(transform)); 717} 718 719bool LayerAnimationController::HasActiveValueObserver() { 720 if (value_observers_.might_have_observers()) { 721 ObserverListBase<LayerAnimationValueObserver>::Iterator it( 722 value_observers_); 723 LayerAnimationValueObserver* obs; 724 while ((obs = it.GetNext()) != NULL) 725 if (obs->IsActive()) 726 return true; 727 } 728 return false; 729} 730 731} // namespace cc 732