| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 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 "ui/compositor/layer.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/command_line.h" | |
| 10 #include "base/debug/trace_event.h" | |
| 11 #include "base/json/json_writer.h" | |
| 12 #include "base/lazy_instance.h" | |
| 13 #include "base/logging.h" | |
| 14 #include "base/memory/scoped_ptr.h" | |
| 15 #include "cc/base/scoped_ptr_algorithm.h" | |
| 16 #include "cc/layers/content_layer.h" | |
| 17 #include "cc/layers/delegated_renderer_layer.h" | |
| 18 #include "cc/layers/nine_patch_layer.h" | |
| 19 #include "cc/layers/picture_layer.h" | |
| 20 #include "cc/layers/solid_color_layer.h" | |
| 21 #include "cc/layers/surface_layer.h" | |
| 22 #include "cc/layers/texture_layer.h" | |
| 23 #include "cc/output/copy_output_request.h" | |
| 24 #include "cc/output/delegated_frame_data.h" | |
| 25 #include "cc/output/filter_operation.h" | |
| 26 #include "cc/output/filter_operations.h" | |
| 27 #include "cc/resources/transferable_resource.h" | |
| 28 #include "ui/compositor/compositor_switches.h" | |
| 29 #include "ui/compositor/dip_util.h" | |
| 30 #include "ui/compositor/layer_animator.h" | |
| 31 #include "ui/gfx/animation/animation.h" | |
| 32 #include "ui/gfx/canvas.h" | |
| 33 #include "ui/gfx/display.h" | |
| 34 #include "ui/gfx/interpolated_transform.h" | |
| 35 #include "ui/gfx/point3_f.h" | |
| 36 #include "ui/gfx/point_conversions.h" | |
| 37 #include "ui/gfx/size_conversions.h" | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 const ui::Layer* GetRoot(const ui::Layer* layer) { | |
| 42 while (layer->parent()) | |
| 43 layer = layer->parent(); | |
| 44 return layer; | |
| 45 } | |
| 46 | |
| 47 struct UIImplSidePaintingStatus { | |
| 48 UIImplSidePaintingStatus() | |
| 49 : enabled(ui::IsUIImplSidePaintingEnabled()) { | |
| 50 } | |
| 51 bool enabled; | |
| 52 }; | |
| 53 base::LazyInstance<UIImplSidePaintingStatus> g_ui_impl_side_painting_status = | |
| 54 LAZY_INSTANCE_INITIALIZER; | |
| 55 | |
| 56 } // namespace | |
| 57 | |
| 58 namespace ui { | |
| 59 | |
| 60 Layer::Layer() | |
| 61 : type_(LAYER_TEXTURED), | |
| 62 compositor_(NULL), | |
| 63 parent_(NULL), | |
| 64 visible_(true), | |
| 65 force_render_surface_(false), | |
| 66 fills_bounds_opaquely_(true), | |
| 67 fills_bounds_completely_(false), | |
| 68 background_blur_radius_(0), | |
| 69 layer_saturation_(0.0f), | |
| 70 layer_brightness_(0.0f), | |
| 71 layer_grayscale_(0.0f), | |
| 72 layer_inverted_(false), | |
| 73 layer_mask_(NULL), | |
| 74 layer_mask_back_link_(NULL), | |
| 75 zoom_(1), | |
| 76 zoom_inset_(0), | |
| 77 delegate_(NULL), | |
| 78 owner_(NULL), | |
| 79 cc_layer_(NULL), | |
| 80 device_scale_factor_(1.0f) { | |
| 81 CreateCcLayer(); | |
| 82 } | |
| 83 | |
| 84 Layer::Layer(LayerType type) | |
| 85 : type_(type), | |
| 86 compositor_(NULL), | |
| 87 parent_(NULL), | |
| 88 visible_(true), | |
| 89 force_render_surface_(false), | |
| 90 fills_bounds_opaquely_(true), | |
| 91 fills_bounds_completely_(false), | |
| 92 background_blur_radius_(0), | |
| 93 layer_saturation_(0.0f), | |
| 94 layer_brightness_(0.0f), | |
| 95 layer_grayscale_(0.0f), | |
| 96 layer_inverted_(false), | |
| 97 layer_mask_(NULL), | |
| 98 layer_mask_back_link_(NULL), | |
| 99 zoom_(1), | |
| 100 zoom_inset_(0), | |
| 101 delegate_(NULL), | |
| 102 owner_(NULL), | |
| 103 cc_layer_(NULL), | |
| 104 device_scale_factor_(1.0f) { | |
| 105 CreateCcLayer(); | |
| 106 } | |
| 107 | |
| 108 Layer::~Layer() { | |
| 109 // Destroying the animator may cause observers to use the layer (and | |
| 110 // indirectly the WebLayer). Destroy the animator first so that the WebLayer | |
| 111 // is still around. | |
| 112 if (animator_.get()) | |
| 113 animator_->SetDelegate(NULL); | |
| 114 animator_ = NULL; | |
| 115 if (compositor_) | |
| 116 compositor_->SetRootLayer(NULL); | |
| 117 if (parent_) | |
| 118 parent_->Remove(this); | |
| 119 if (layer_mask_) | |
| 120 SetMaskLayer(NULL); | |
| 121 if (layer_mask_back_link_) | |
| 122 layer_mask_back_link_->SetMaskLayer(NULL); | |
| 123 for (size_t i = 0; i < children_.size(); ++i) | |
| 124 children_[i]->parent_ = NULL; | |
| 125 cc_layer_->RemoveLayerAnimationEventObserver(this); | |
| 126 cc_layer_->RemoveFromParent(); | |
| 127 } | |
| 128 | |
| 129 // static | |
| 130 bool Layer::UsingPictureLayer() { | |
| 131 return g_ui_impl_side_painting_status.Get().enabled; | |
| 132 } | |
| 133 | |
| 134 Compositor* Layer::GetCompositor() { | |
| 135 return GetRoot(this)->compositor_; | |
| 136 } | |
| 137 | |
| 138 float Layer::opacity() const { | |
| 139 return cc_layer_->opacity(); | |
| 140 } | |
| 141 | |
| 142 void Layer::SetCompositor(Compositor* compositor) { | |
| 143 // This function must only be called to set the compositor on the root layer, | |
| 144 // or to reset it. | |
| 145 DCHECK(!compositor || !compositor_); | |
| 146 DCHECK(!compositor || compositor->root_layer() == this); | |
| 147 DCHECK(!parent_); | |
| 148 if (compositor_) { | |
| 149 RemoveAnimatorsInTreeFromCollection( | |
| 150 compositor_->layer_animator_collection()); | |
| 151 } | |
| 152 compositor_ = compositor; | |
| 153 if (compositor) { | |
| 154 OnDeviceScaleFactorChanged(compositor->device_scale_factor()); | |
| 155 SendPendingThreadedAnimations(); | |
| 156 AddAnimatorsInTreeToCollection(compositor_->layer_animator_collection()); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 void Layer::Add(Layer* child) { | |
| 161 DCHECK(!child->compositor_); | |
| 162 if (child->parent_) | |
| 163 child->parent_->Remove(child); | |
| 164 child->parent_ = this; | |
| 165 children_.push_back(child); | |
| 166 cc_layer_->AddChild(child->cc_layer_); | |
| 167 child->OnDeviceScaleFactorChanged(device_scale_factor_); | |
| 168 if (GetCompositor()) | |
| 169 child->SendPendingThreadedAnimations(); | |
| 170 LayerAnimatorCollection* collection = GetLayerAnimatorCollection(); | |
| 171 if (collection) | |
| 172 child->AddAnimatorsInTreeToCollection(collection); | |
| 173 } | |
| 174 | |
| 175 void Layer::Remove(Layer* child) { | |
| 176 // Current bounds are used to calculate offsets when layers are reparented. | |
| 177 // Stop (and complete) an ongoing animation to update the bounds immediately. | |
| 178 LayerAnimator* child_animator = child->animator_.get(); | |
| 179 if (child_animator) | |
| 180 child_animator->StopAnimatingProperty(ui::LayerAnimationElement::BOUNDS); | |
| 181 LayerAnimatorCollection* collection = GetLayerAnimatorCollection(); | |
| 182 if (collection) | |
| 183 child->RemoveAnimatorsInTreeFromCollection(collection); | |
| 184 | |
| 185 std::vector<Layer*>::iterator i = | |
| 186 std::find(children_.begin(), children_.end(), child); | |
| 187 DCHECK(i != children_.end()); | |
| 188 children_.erase(i); | |
| 189 child->parent_ = NULL; | |
| 190 child->cc_layer_->RemoveFromParent(); | |
| 191 } | |
| 192 | |
| 193 void Layer::StackAtTop(Layer* child) { | |
| 194 if (children_.size() <= 1 || child == children_.back()) | |
| 195 return; // Already in front. | |
| 196 StackAbove(child, children_.back()); | |
| 197 } | |
| 198 | |
| 199 void Layer::StackAbove(Layer* child, Layer* other) { | |
| 200 StackRelativeTo(child, other, true); | |
| 201 } | |
| 202 | |
| 203 void Layer::StackAtBottom(Layer* child) { | |
| 204 if (children_.size() <= 1 || child == children_.front()) | |
| 205 return; // Already on bottom. | |
| 206 StackBelow(child, children_.front()); | |
| 207 } | |
| 208 | |
| 209 void Layer::StackBelow(Layer* child, Layer* other) { | |
| 210 StackRelativeTo(child, other, false); | |
| 211 } | |
| 212 | |
| 213 bool Layer::Contains(const Layer* other) const { | |
| 214 for (const Layer* parent = other; parent; parent = parent->parent()) { | |
| 215 if (parent == this) | |
| 216 return true; | |
| 217 } | |
| 218 return false; | |
| 219 } | |
| 220 | |
| 221 void Layer::SetAnimator(LayerAnimator* animator) { | |
| 222 if (animator) | |
| 223 animator->SetDelegate(this); | |
| 224 animator_ = animator; | |
| 225 } | |
| 226 | |
| 227 LayerAnimator* Layer::GetAnimator() { | |
| 228 if (!animator_.get()) | |
| 229 SetAnimator(LayerAnimator::CreateDefaultAnimator()); | |
| 230 return animator_.get(); | |
| 231 } | |
| 232 | |
| 233 void Layer::SetTransform(const gfx::Transform& transform) { | |
| 234 GetAnimator()->SetTransform(transform); | |
| 235 } | |
| 236 | |
| 237 gfx::Transform Layer::GetTargetTransform() const { | |
| 238 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 239 LayerAnimationElement::TRANSFORM)) { | |
| 240 return animator_->GetTargetTransform(); | |
| 241 } | |
| 242 return transform(); | |
| 243 } | |
| 244 | |
| 245 void Layer::SetBounds(const gfx::Rect& bounds) { | |
| 246 GetAnimator()->SetBounds(bounds); | |
| 247 } | |
| 248 | |
| 249 void Layer::SetSubpixelPositionOffset(const gfx::Vector2dF offset) { | |
| 250 subpixel_position_offset_ = offset; | |
| 251 RecomputePosition(); | |
| 252 } | |
| 253 | |
| 254 gfx::Rect Layer::GetTargetBounds() const { | |
| 255 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 256 LayerAnimationElement::BOUNDS)) { | |
| 257 return animator_->GetTargetBounds(); | |
| 258 } | |
| 259 return bounds_; | |
| 260 } | |
| 261 | |
| 262 void Layer::SetMasksToBounds(bool masks_to_bounds) { | |
| 263 cc_layer_->SetMasksToBounds(masks_to_bounds); | |
| 264 } | |
| 265 | |
| 266 bool Layer::GetMasksToBounds() const { | |
| 267 return cc_layer_->masks_to_bounds(); | |
| 268 } | |
| 269 | |
| 270 void Layer::SetOpacity(float opacity) { | |
| 271 GetAnimator()->SetOpacity(opacity); | |
| 272 } | |
| 273 | |
| 274 float Layer::GetCombinedOpacity() const { | |
| 275 float opacity = this->opacity(); | |
| 276 Layer* current = this->parent_; | |
| 277 while (current) { | |
| 278 opacity *= current->opacity(); | |
| 279 current = current->parent_; | |
| 280 } | |
| 281 return opacity; | |
| 282 } | |
| 283 | |
| 284 void Layer::SetBackgroundBlur(int blur_radius) { | |
| 285 background_blur_radius_ = blur_radius; | |
| 286 | |
| 287 SetLayerBackgroundFilters(); | |
| 288 } | |
| 289 | |
| 290 void Layer::SetLayerSaturation(float saturation) { | |
| 291 layer_saturation_ = saturation; | |
| 292 SetLayerFilters(); | |
| 293 } | |
| 294 | |
| 295 void Layer::SetLayerBrightness(float brightness) { | |
| 296 GetAnimator()->SetBrightness(brightness); | |
| 297 } | |
| 298 | |
| 299 float Layer::GetTargetBrightness() const { | |
| 300 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 301 LayerAnimationElement::BRIGHTNESS)) { | |
| 302 return animator_->GetTargetBrightness(); | |
| 303 } | |
| 304 return layer_brightness(); | |
| 305 } | |
| 306 | |
| 307 void Layer::SetLayerGrayscale(float grayscale) { | |
| 308 GetAnimator()->SetGrayscale(grayscale); | |
| 309 } | |
| 310 | |
| 311 float Layer::GetTargetGrayscale() const { | |
| 312 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 313 LayerAnimationElement::GRAYSCALE)) { | |
| 314 return animator_->GetTargetGrayscale(); | |
| 315 } | |
| 316 return layer_grayscale(); | |
| 317 } | |
| 318 | |
| 319 void Layer::SetLayerInverted(bool inverted) { | |
| 320 layer_inverted_ = inverted; | |
| 321 SetLayerFilters(); | |
| 322 } | |
| 323 | |
| 324 void Layer::SetMaskLayer(Layer* layer_mask) { | |
| 325 // The provided mask should not have a layer mask itself. | |
| 326 DCHECK(!layer_mask || | |
| 327 (!layer_mask->layer_mask_layer() && | |
| 328 layer_mask->children().empty() && | |
| 329 !layer_mask->layer_mask_back_link_)); | |
| 330 DCHECK(!layer_mask_back_link_); | |
| 331 if (layer_mask_ == layer_mask) | |
| 332 return; | |
| 333 // We need to de-reference the currently linked object so that no problem | |
| 334 // arises if the mask layer gets deleted before this object. | |
| 335 if (layer_mask_) | |
| 336 layer_mask_->layer_mask_back_link_ = NULL; | |
| 337 layer_mask_ = layer_mask; | |
| 338 cc_layer_->SetMaskLayer( | |
| 339 layer_mask ? layer_mask->cc_layer() : NULL); | |
| 340 // We need to reference the linked object so that it can properly break the | |
| 341 // link to us when it gets deleted. | |
| 342 if (layer_mask) { | |
| 343 layer_mask->layer_mask_back_link_ = this; | |
| 344 layer_mask->OnDeviceScaleFactorChanged(device_scale_factor_); | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 void Layer::SetBackgroundZoom(float zoom, int inset) { | |
| 349 zoom_ = zoom; | |
| 350 zoom_inset_ = inset; | |
| 351 | |
| 352 SetLayerBackgroundFilters(); | |
| 353 } | |
| 354 | |
| 355 void Layer::SetAlphaShape(scoped_ptr<SkRegion> region) { | |
| 356 alpha_shape_ = region.Pass(); | |
| 357 | |
| 358 SetLayerFilters(); | |
| 359 } | |
| 360 | |
| 361 void Layer::SetLayerFilters() { | |
| 362 cc::FilterOperations filters; | |
| 363 if (layer_saturation_) { | |
| 364 filters.Append(cc::FilterOperation::CreateSaturateFilter( | |
| 365 layer_saturation_)); | |
| 366 } | |
| 367 if (layer_grayscale_) { | |
| 368 filters.Append(cc::FilterOperation::CreateGrayscaleFilter( | |
| 369 layer_grayscale_)); | |
| 370 } | |
| 371 if (layer_inverted_) | |
| 372 filters.Append(cc::FilterOperation::CreateInvertFilter(1.0)); | |
| 373 // Brightness goes last, because the resulting colors neeed clamping, which | |
| 374 // cause further color matrix filters to be applied separately. In this order, | |
| 375 // they all can be combined in a single pass. | |
| 376 if (layer_brightness_) { | |
| 377 filters.Append(cc::FilterOperation::CreateSaturatingBrightnessFilter( | |
| 378 layer_brightness_)); | |
| 379 } | |
| 380 if (alpha_shape_) { | |
| 381 filters.Append(cc::FilterOperation::CreateAlphaThresholdFilter( | |
| 382 *alpha_shape_, 0.f, 0.f)); | |
| 383 } | |
| 384 | |
| 385 cc_layer_->SetFilters(filters); | |
| 386 } | |
| 387 | |
| 388 void Layer::SetLayerBackgroundFilters() { | |
| 389 cc::FilterOperations filters; | |
| 390 if (zoom_ != 1) | |
| 391 filters.Append(cc::FilterOperation::CreateZoomFilter(zoom_, zoom_inset_)); | |
| 392 | |
| 393 if (background_blur_radius_) { | |
| 394 filters.Append(cc::FilterOperation::CreateBlurFilter( | |
| 395 background_blur_radius_)); | |
| 396 } | |
| 397 | |
| 398 cc_layer_->SetBackgroundFilters(filters); | |
| 399 } | |
| 400 | |
| 401 float Layer::GetTargetOpacity() const { | |
| 402 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 403 LayerAnimationElement::OPACITY)) | |
| 404 return animator_->GetTargetOpacity(); | |
| 405 return opacity(); | |
| 406 } | |
| 407 | |
| 408 void Layer::SetVisible(bool visible) { | |
| 409 GetAnimator()->SetVisibility(visible); | |
| 410 } | |
| 411 | |
| 412 bool Layer::GetTargetVisibility() const { | |
| 413 if (animator_.get() && animator_->IsAnimatingProperty( | |
| 414 LayerAnimationElement::VISIBILITY)) | |
| 415 return animator_->GetTargetVisibility(); | |
| 416 return visible_; | |
| 417 } | |
| 418 | |
| 419 bool Layer::IsDrawn() const { | |
| 420 const Layer* layer = this; | |
| 421 while (layer && layer->visible_) | |
| 422 layer = layer->parent_; | |
| 423 return layer == NULL; | |
| 424 } | |
| 425 | |
| 426 bool Layer::ShouldDraw() const { | |
| 427 return type_ != LAYER_NOT_DRAWN && GetCombinedOpacity() > 0.0f; | |
| 428 } | |
| 429 | |
| 430 // static | |
| 431 void Layer::ConvertPointToLayer(const Layer* source, | |
| 432 const Layer* target, | |
| 433 gfx::Point* point) { | |
| 434 if (source == target) | |
| 435 return; | |
| 436 | |
| 437 const Layer* root_layer = GetRoot(source); | |
| 438 CHECK_EQ(root_layer, GetRoot(target)); | |
| 439 | |
| 440 if (source != root_layer) | |
| 441 source->ConvertPointForAncestor(root_layer, point); | |
| 442 if (target != root_layer) | |
| 443 target->ConvertPointFromAncestor(root_layer, point); | |
| 444 } | |
| 445 | |
| 446 bool Layer::GetTargetTransformRelativeTo(const Layer* ancestor, | |
| 447 gfx::Transform* transform) const { | |
| 448 const Layer* p = this; | |
| 449 for (; p && p != ancestor; p = p->parent()) { | |
| 450 gfx::Transform translation; | |
| 451 translation.Translate(static_cast<float>(p->bounds().x()), | |
| 452 static_cast<float>(p->bounds().y())); | |
| 453 // Use target transform so that result will be correct once animation is | |
| 454 // finished. | |
| 455 if (!p->GetTargetTransform().IsIdentity()) | |
| 456 transform->ConcatTransform(p->GetTargetTransform()); | |
| 457 transform->ConcatTransform(translation); | |
| 458 } | |
| 459 return p == ancestor; | |
| 460 } | |
| 461 | |
| 462 void Layer::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { | |
| 463 if (fills_bounds_opaquely_ == fills_bounds_opaquely) | |
| 464 return; | |
| 465 | |
| 466 fills_bounds_opaquely_ = fills_bounds_opaquely; | |
| 467 | |
| 468 cc_layer_->SetContentsOpaque(fills_bounds_opaquely); | |
| 469 } | |
| 470 | |
| 471 void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) { | |
| 472 fills_bounds_completely_ = fills_bounds_completely; | |
| 473 } | |
| 474 | |
| 475 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) { | |
| 476 // Finish animations being handled by cc_layer_. | |
| 477 if (animator_.get()) { | |
| 478 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); | |
| 479 animator_->StopAnimatingProperty(LayerAnimationElement::OPACITY); | |
| 480 } | |
| 481 | |
| 482 if (texture_layer_.get()) | |
| 483 texture_layer_->ClearClient(); | |
| 484 // TODO(piman): delegated_renderer_layer_ cleanup. | |
| 485 | |
| 486 cc_layer_->RemoveAllChildren(); | |
| 487 if (cc_layer_->parent()) { | |
| 488 cc_layer_->parent()->ReplaceChild(cc_layer_, new_layer); | |
| 489 } | |
| 490 cc_layer_->SetLayerClient(NULL); | |
| 491 cc_layer_->RemoveLayerAnimationEventObserver(this); | |
| 492 new_layer->SetOpacity(cc_layer_->opacity()); | |
| 493 new_layer->SetTransform(cc_layer_->transform()); | |
| 494 new_layer->SetPosition(cc_layer_->position()); | |
| 495 new_layer->SetBackgroundColor(cc_layer_->background_color()); | |
| 496 | |
| 497 cc_layer_ = new_layer.get(); | |
| 498 content_layer_ = NULL; | |
| 499 solid_color_layer_ = NULL; | |
| 500 texture_layer_ = NULL; | |
| 501 delegated_renderer_layer_ = NULL; | |
| 502 surface_layer_ = NULL; | |
| 503 | |
| 504 cc_layer_->AddLayerAnimationEventObserver(this); | |
| 505 for (size_t i = 0; i < children_.size(); ++i) { | |
| 506 DCHECK(children_[i]->cc_layer_); | |
| 507 cc_layer_->AddChild(children_[i]->cc_layer_); | |
| 508 } | |
| 509 cc_layer_->SetLayerClient(this); | |
| 510 cc_layer_->SetTransformOrigin(gfx::Point3F()); | |
| 511 cc_layer_->SetContentsOpaque(fills_bounds_opaquely_); | |
| 512 cc_layer_->SetForceRenderSurface(force_render_surface_); | |
| 513 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); | |
| 514 cc_layer_->SetHideLayerAndSubtree(!visible_); | |
| 515 | |
| 516 SetLayerFilters(); | |
| 517 SetLayerBackgroundFilters(); | |
| 518 } | |
| 519 | |
| 520 void Layer::SwitchCCLayerForTest() { | |
| 521 scoped_refptr<cc::Layer> new_layer; | |
| 522 if (Layer::UsingPictureLayer()) | |
| 523 new_layer = cc::PictureLayer::Create(this); | |
| 524 else | |
| 525 new_layer = cc::ContentLayer::Create(this); | |
| 526 SwitchToLayer(new_layer); | |
| 527 content_layer_ = new_layer; | |
| 528 } | |
| 529 | |
| 530 void Layer::SetTextureMailbox( | |
| 531 const cc::TextureMailbox& mailbox, | |
| 532 scoped_ptr<cc::SingleReleaseCallback> release_callback, | |
| 533 gfx::Size texture_size_in_dip) { | |
| 534 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR); | |
| 535 DCHECK(mailbox.IsValid()); | |
| 536 DCHECK(release_callback); | |
| 537 if (!texture_layer_.get()) { | |
| 538 scoped_refptr<cc::TextureLayer> new_layer = | |
| 539 cc::TextureLayer::CreateForMailbox(this); | |
| 540 new_layer->SetFlipped(true); | |
| 541 SwitchToLayer(new_layer); | |
| 542 texture_layer_ = new_layer; | |
| 543 } | |
| 544 if (mailbox_release_callback_) | |
| 545 mailbox_release_callback_->Run(0, false); | |
| 546 mailbox_release_callback_ = release_callback.Pass(); | |
| 547 mailbox_ = mailbox; | |
| 548 SetTextureSize(texture_size_in_dip); | |
| 549 } | |
| 550 | |
| 551 void Layer::SetTextureSize(gfx::Size texture_size_in_dip) { | |
| 552 DCHECK(texture_layer_.get()); | |
| 553 if (frame_size_in_dip_ == texture_size_in_dip) | |
| 554 return; | |
| 555 frame_size_in_dip_ = texture_size_in_dip; | |
| 556 RecomputeDrawsContentAndUVRect(); | |
| 557 texture_layer_->SetNeedsDisplay(); | |
| 558 } | |
| 559 | |
| 560 void Layer::SetShowDelegatedContent(cc::DelegatedFrameProvider* frame_provider, | |
| 561 gfx::Size frame_size_in_dip) { | |
| 562 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR); | |
| 563 | |
| 564 scoped_refptr<cc::DelegatedRendererLayer> new_layer = | |
| 565 cc::DelegatedRendererLayer::Create(frame_provider); | |
| 566 SwitchToLayer(new_layer); | |
| 567 delegated_renderer_layer_ = new_layer; | |
| 568 | |
| 569 frame_size_in_dip_ = frame_size_in_dip; | |
| 570 RecomputeDrawsContentAndUVRect(); | |
| 571 } | |
| 572 | |
| 573 void Layer::SetShowSurface( | |
| 574 cc::SurfaceId id, | |
| 575 const cc::SurfaceLayer::SatisfyCallback& satisfy_callback, | |
| 576 const cc::SurfaceLayer::RequireCallback& require_callback, | |
| 577 gfx::Size frame_size_in_dip) { | |
| 578 DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR); | |
| 579 | |
| 580 scoped_refptr<cc::SurfaceLayer> new_layer = | |
| 581 cc::SurfaceLayer::Create(satisfy_callback, require_callback); | |
| 582 new_layer->SetSurfaceId(id, 1.f, frame_size_in_dip); | |
| 583 SwitchToLayer(new_layer); | |
| 584 surface_layer_ = new_layer; | |
| 585 | |
| 586 frame_size_in_dip_ = frame_size_in_dip; | |
| 587 RecomputeDrawsContentAndUVRect(); | |
| 588 } | |
| 589 | |
| 590 void Layer::SetShowSolidColorContent() { | |
| 591 DCHECK_EQ(type_, LAYER_SOLID_COLOR); | |
| 592 | |
| 593 if (solid_color_layer_.get()) | |
| 594 return; | |
| 595 | |
| 596 scoped_refptr<cc::SolidColorLayer> new_layer = cc::SolidColorLayer::Create(); | |
| 597 SwitchToLayer(new_layer); | |
| 598 solid_color_layer_ = new_layer; | |
| 599 | |
| 600 mailbox_ = cc::TextureMailbox(); | |
| 601 if (mailbox_release_callback_) { | |
| 602 mailbox_release_callback_->Run(0, false); | |
| 603 mailbox_release_callback_.reset(); | |
| 604 } | |
| 605 RecomputeDrawsContentAndUVRect(); | |
| 606 } | |
| 607 | |
| 608 void Layer::UpdateNinePatchLayerBitmap(const SkBitmap& bitmap) { | |
| 609 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get()); | |
| 610 SkBitmap bitmap_copy; | |
| 611 if (bitmap.isImmutable()) { | |
| 612 bitmap_copy = bitmap; | |
| 613 } else { | |
| 614 // UIResourceBitmap requires an immutable copy of the input |bitmap|. | |
| 615 bitmap.copyTo(&bitmap_copy); | |
| 616 bitmap_copy.setImmutable(); | |
| 617 } | |
| 618 nine_patch_layer_->SetBitmap(bitmap_copy); | |
| 619 } | |
| 620 | |
| 621 void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture) { | |
| 622 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get()); | |
| 623 nine_patch_layer_->SetAperture(aperture); | |
| 624 } | |
| 625 | |
| 626 void Layer::UpdateNinePatchLayerBorder(const gfx::Rect& border) { | |
| 627 DCHECK(type_ == LAYER_NINE_PATCH && nine_patch_layer_.get()); | |
| 628 nine_patch_layer_->SetBorder(border); | |
| 629 } | |
| 630 | |
| 631 void Layer::SetColor(SkColor color) { GetAnimator()->SetColor(color); } | |
| 632 | |
| 633 bool Layer::SchedulePaint(const gfx::Rect& invalid_rect) { | |
| 634 if ((type_ == LAYER_SOLID_COLOR && !texture_layer_.get()) || | |
| 635 type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid())) | |
| 636 return false; | |
| 637 | |
| 638 damaged_region_.op(invalid_rect.x(), | |
| 639 invalid_rect.y(), | |
| 640 invalid_rect.right(), | |
| 641 invalid_rect.bottom(), | |
| 642 SkRegion::kUnion_Op); | |
| 643 ScheduleDraw(); | |
| 644 return true; | |
| 645 } | |
| 646 | |
| 647 void Layer::ScheduleDraw() { | |
| 648 Compositor* compositor = GetCompositor(); | |
| 649 if (compositor) | |
| 650 compositor->ScheduleDraw(); | |
| 651 } | |
| 652 | |
| 653 void Layer::SendDamagedRects() { | |
| 654 if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) { | |
| 655 for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) { | |
| 656 const SkIRect& sk_damaged = iter.rect(); | |
| 657 gfx::Rect damaged( | |
| 658 sk_damaged.x(), | |
| 659 sk_damaged.y(), | |
| 660 sk_damaged.width(), | |
| 661 sk_damaged.height()); | |
| 662 cc_layer_->SetNeedsDisplayRect(damaged); | |
| 663 } | |
| 664 damaged_region_.setEmpty(); | |
| 665 } | |
| 666 for (size_t i = 0; i < children_.size(); ++i) | |
| 667 children_[i]->SendDamagedRects(); | |
| 668 } | |
| 669 | |
| 670 void Layer::CompleteAllAnimations() { | |
| 671 typedef std::vector<scoped_refptr<LayerAnimator> > LayerAnimatorVector; | |
| 672 LayerAnimatorVector animators; | |
| 673 CollectAnimators(&animators); | |
| 674 for (LayerAnimatorVector::const_iterator it = animators.begin(); | |
| 675 it != animators.end(); | |
| 676 ++it) { | |
| 677 (*it)->StopAnimating(); | |
| 678 } | |
| 679 } | |
| 680 | |
| 681 void Layer::SuppressPaint() { | |
| 682 if (!delegate_) | |
| 683 return; | |
| 684 delegate_ = NULL; | |
| 685 for (size_t i = 0; i < children_.size(); ++i) | |
| 686 children_[i]->SuppressPaint(); | |
| 687 } | |
| 688 | |
| 689 void Layer::OnDeviceScaleFactorChanged(float device_scale_factor) { | |
| 690 if (device_scale_factor_ == device_scale_factor) | |
| 691 return; | |
| 692 if (animator_.get()) | |
| 693 animator_->StopAnimatingProperty(LayerAnimationElement::TRANSFORM); | |
| 694 device_scale_factor_ = device_scale_factor; | |
| 695 RecomputeDrawsContentAndUVRect(); | |
| 696 RecomputePosition(); | |
| 697 SchedulePaint(gfx::Rect(bounds_.size())); | |
| 698 if (delegate_) | |
| 699 delegate_->OnDeviceScaleFactorChanged(device_scale_factor); | |
| 700 for (size_t i = 0; i < children_.size(); ++i) | |
| 701 children_[i]->OnDeviceScaleFactorChanged(device_scale_factor); | |
| 702 if (layer_mask_) | |
| 703 layer_mask_->OnDeviceScaleFactorChanged(device_scale_factor); | |
| 704 } | |
| 705 | |
| 706 void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) { | |
| 707 DCHECK(delegated_renderer_layer_.get() || surface_layer_.get()); | |
| 708 if (!delegate_) | |
| 709 return; | |
| 710 delegate_->OnDelegatedFrameDamage(damage_rect_in_dip); | |
| 711 } | |
| 712 | |
| 713 void Layer::RequestCopyOfOutput(scoped_ptr<cc::CopyOutputRequest> request) { | |
| 714 cc_layer_->RequestCopyOfOutput(request.Pass()); | |
| 715 } | |
| 716 | |
| 717 void Layer::PaintContents(SkCanvas* sk_canvas, | |
| 718 const gfx::Rect& clip, | |
| 719 ContentLayerClient::GraphicsContextStatus gc_status) { | |
| 720 TRACE_EVENT0("ui", "Layer::PaintContents"); | |
| 721 scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling( | |
| 722 sk_canvas, device_scale_factor_)); | |
| 723 if (delegate_) | |
| 724 delegate_->OnPaintLayer(canvas.get()); | |
| 725 } | |
| 726 | |
| 727 scoped_refptr<cc::DisplayItemList> Layer::PaintContentsToDisplayList( | |
| 728 const gfx::Rect& clip, | |
| 729 ContentLayerClient::GraphicsContextStatus gc_status) { | |
| 730 NOTIMPLEMENTED(); | |
| 731 return cc::DisplayItemList::Create(); | |
| 732 } | |
| 733 | |
| 734 bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; } | |
| 735 | |
| 736 bool Layer::PrepareTextureMailbox( | |
| 737 cc::TextureMailbox* mailbox, | |
| 738 scoped_ptr<cc::SingleReleaseCallback>* release_callback, | |
| 739 bool use_shared_memory) { | |
| 740 if (!mailbox_release_callback_) | |
| 741 return false; | |
| 742 *mailbox = mailbox_; | |
| 743 *release_callback = mailbox_release_callback_.Pass(); | |
| 744 return true; | |
| 745 } | |
| 746 | |
| 747 void Layer::SetForceRenderSurface(bool force) { | |
| 748 if (force_render_surface_ == force) | |
| 749 return; | |
| 750 | |
| 751 force_render_surface_ = force; | |
| 752 cc_layer_->SetForceRenderSurface(force_render_surface_); | |
| 753 } | |
| 754 | |
| 755 class LayerDebugInfo : public base::debug::ConvertableToTraceFormat { | |
| 756 public: | |
| 757 explicit LayerDebugInfo(std::string name) : name_(name) { } | |
| 758 void AppendAsTraceFormat(std::string* out) const override { | |
| 759 base::DictionaryValue dictionary; | |
| 760 dictionary.SetString("layer_name", name_); | |
| 761 base::JSONWriter::Write(&dictionary, out); | |
| 762 } | |
| 763 | |
| 764 private: | |
| 765 ~LayerDebugInfo() override {} | |
| 766 std::string name_; | |
| 767 }; | |
| 768 | |
| 769 scoped_refptr<base::debug::ConvertableToTraceFormat> Layer::TakeDebugInfo() { | |
| 770 return new LayerDebugInfo(name_); | |
| 771 } | |
| 772 | |
| 773 void Layer::OnAnimationStarted(const cc::AnimationEvent& event) { | |
| 774 if (animator_.get()) | |
| 775 animator_->OnThreadedAnimationStarted(event); | |
| 776 } | |
| 777 | |
| 778 void Layer::CollectAnimators( | |
| 779 std::vector<scoped_refptr<LayerAnimator> >* animators) { | |
| 780 if (IsAnimating()) | |
| 781 animators->push_back(animator_); | |
| 782 std::for_each(children_.begin(), children_.end(), | |
| 783 std::bind2nd(std::mem_fun(&Layer::CollectAnimators), | |
| 784 animators)); | |
| 785 } | |
| 786 | |
| 787 void Layer::StackRelativeTo(Layer* child, Layer* other, bool above) { | |
| 788 DCHECK_NE(child, other); | |
| 789 DCHECK_EQ(this, child->parent()); | |
| 790 DCHECK_EQ(this, other->parent()); | |
| 791 | |
| 792 const size_t child_i = | |
| 793 std::find(children_.begin(), children_.end(), child) - children_.begin(); | |
| 794 const size_t other_i = | |
| 795 std::find(children_.begin(), children_.end(), other) - children_.begin(); | |
| 796 if ((above && child_i == other_i + 1) || (!above && child_i + 1 == other_i)) | |
| 797 return; | |
| 798 | |
| 799 const size_t dest_i = | |
| 800 above ? | |
| 801 (child_i < other_i ? other_i : other_i + 1) : | |
| 802 (child_i < other_i ? other_i - 1 : other_i); | |
| 803 children_.erase(children_.begin() + child_i); | |
| 804 children_.insert(children_.begin() + dest_i, child); | |
| 805 | |
| 806 child->cc_layer_->RemoveFromParent(); | |
| 807 cc_layer_->InsertChild(child->cc_layer_, dest_i); | |
| 808 } | |
| 809 | |
| 810 bool Layer::ConvertPointForAncestor(const Layer* ancestor, | |
| 811 gfx::Point* point) const { | |
| 812 gfx::Transform transform; | |
| 813 bool result = GetTargetTransformRelativeTo(ancestor, &transform); | |
| 814 gfx::Point3F p(*point); | |
| 815 transform.TransformPoint(&p); | |
| 816 *point = gfx::ToFlooredPoint(p.AsPointF()); | |
| 817 return result; | |
| 818 } | |
| 819 | |
| 820 bool Layer::ConvertPointFromAncestor(const Layer* ancestor, | |
| 821 gfx::Point* point) const { | |
| 822 gfx::Transform transform; | |
| 823 bool result = GetTargetTransformRelativeTo(ancestor, &transform); | |
| 824 gfx::Point3F p(*point); | |
| 825 transform.TransformPointReverse(&p); | |
| 826 *point = gfx::ToFlooredPoint(p.AsPointF()); | |
| 827 return result; | |
| 828 } | |
| 829 | |
| 830 void Layer::SetBoundsFromAnimation(const gfx::Rect& bounds) { | |
| 831 if (bounds == bounds_) | |
| 832 return; | |
| 833 | |
| 834 base::Closure closure; | |
| 835 if (delegate_) | |
| 836 closure = delegate_->PrepareForLayerBoundsChange(); | |
| 837 bool was_move = bounds_.size() == bounds.size(); | |
| 838 bounds_ = bounds; | |
| 839 | |
| 840 RecomputeDrawsContentAndUVRect(); | |
| 841 RecomputePosition(); | |
| 842 | |
| 843 if (!closure.is_null()) | |
| 844 closure.Run(); | |
| 845 | |
| 846 if (was_move) { | |
| 847 // Don't schedule a draw if we're invisible. We'll schedule one | |
| 848 // automatically when we get visible. | |
| 849 if (IsDrawn()) | |
| 850 ScheduleDraw(); | |
| 851 } else { | |
| 852 // Always schedule a paint, even if we're invisible. | |
| 853 SchedulePaint(gfx::Rect(bounds.size())); | |
| 854 } | |
| 855 } | |
| 856 | |
| 857 void Layer::SetTransformFromAnimation(const gfx::Transform& transform) { | |
| 858 cc_layer_->SetTransform(transform); | |
| 859 } | |
| 860 | |
| 861 void Layer::SetOpacityFromAnimation(float opacity) { | |
| 862 cc_layer_->SetOpacity(opacity); | |
| 863 ScheduleDraw(); | |
| 864 } | |
| 865 | |
| 866 void Layer::SetVisibilityFromAnimation(bool visible) { | |
| 867 if (visible_ == visible) | |
| 868 return; | |
| 869 | |
| 870 visible_ = visible; | |
| 871 cc_layer_->SetHideLayerAndSubtree(!visible_); | |
| 872 } | |
| 873 | |
| 874 void Layer::SetBrightnessFromAnimation(float brightness) { | |
| 875 layer_brightness_ = brightness; | |
| 876 SetLayerFilters(); | |
| 877 } | |
| 878 | |
| 879 void Layer::SetGrayscaleFromAnimation(float grayscale) { | |
| 880 layer_grayscale_ = grayscale; | |
| 881 SetLayerFilters(); | |
| 882 } | |
| 883 | |
| 884 void Layer::SetColorFromAnimation(SkColor color) { | |
| 885 DCHECK_EQ(type_, LAYER_SOLID_COLOR); | |
| 886 cc_layer_->SetBackgroundColor(color); | |
| 887 SetFillsBoundsOpaquely(SkColorGetA(color) == 0xFF); | |
| 888 } | |
| 889 | |
| 890 void Layer::ScheduleDrawForAnimation() { | |
| 891 ScheduleDraw(); | |
| 892 } | |
| 893 | |
| 894 const gfx::Rect& Layer::GetBoundsForAnimation() const { | |
| 895 return bounds(); | |
| 896 } | |
| 897 | |
| 898 gfx::Transform Layer::GetTransformForAnimation() const { | |
| 899 return transform(); | |
| 900 } | |
| 901 | |
| 902 float Layer::GetOpacityForAnimation() const { | |
| 903 return opacity(); | |
| 904 } | |
| 905 | |
| 906 bool Layer::GetVisibilityForAnimation() const { | |
| 907 return visible(); | |
| 908 } | |
| 909 | |
| 910 float Layer::GetBrightnessForAnimation() const { | |
| 911 return layer_brightness(); | |
| 912 } | |
| 913 | |
| 914 float Layer::GetGrayscaleForAnimation() const { | |
| 915 return layer_grayscale(); | |
| 916 } | |
| 917 | |
| 918 SkColor Layer::GetColorForAnimation() const { | |
| 919 // WebColor is equivalent to SkColor, per WebColor.h. | |
| 920 // The NULL check is here since this is invoked regardless of whether we have | |
| 921 // been configured as LAYER_SOLID_COLOR. | |
| 922 return solid_color_layer_.get() ? | |
| 923 solid_color_layer_->background_color() : SK_ColorBLACK; | |
| 924 } | |
| 925 | |
| 926 float Layer::GetDeviceScaleFactor() const { | |
| 927 return device_scale_factor_; | |
| 928 } | |
| 929 | |
| 930 void Layer::AddThreadedAnimation(scoped_ptr<cc::Animation> animation) { | |
| 931 DCHECK(cc_layer_); | |
| 932 // Until this layer has a compositor (and hence cc_layer_ has a | |
| 933 // LayerTreeHost), addAnimation will fail. | |
| 934 if (GetCompositor()) | |
| 935 cc_layer_->AddAnimation(animation.Pass()); | |
| 936 else | |
| 937 pending_threaded_animations_.push_back(animation.Pass()); | |
| 938 } | |
| 939 | |
| 940 namespace{ | |
| 941 | |
| 942 struct HasAnimationId { | |
| 943 HasAnimationId(int id): id_(id) { | |
| 944 } | |
| 945 | |
| 946 bool operator()(cc::Animation* animation) const { | |
| 947 return animation->id() == id_; | |
| 948 } | |
| 949 | |
| 950 private: | |
| 951 int id_; | |
| 952 }; | |
| 953 | |
| 954 } | |
| 955 | |
| 956 void Layer::RemoveThreadedAnimation(int animation_id) { | |
| 957 DCHECK(cc_layer_); | |
| 958 if (pending_threaded_animations_.size() == 0) { | |
| 959 cc_layer_->RemoveAnimation(animation_id); | |
| 960 return; | |
| 961 } | |
| 962 | |
| 963 pending_threaded_animations_.erase( | |
| 964 cc::remove_if(&pending_threaded_animations_, | |
| 965 pending_threaded_animations_.begin(), | |
| 966 pending_threaded_animations_.end(), | |
| 967 HasAnimationId(animation_id)), | |
| 968 pending_threaded_animations_.end()); | |
| 969 } | |
| 970 | |
| 971 LayerAnimatorCollection* Layer::GetLayerAnimatorCollection() { | |
| 972 Compositor* compositor = GetCompositor(); | |
| 973 return compositor ? compositor->layer_animator_collection() : NULL; | |
| 974 } | |
| 975 | |
| 976 void Layer::SendPendingThreadedAnimations() { | |
| 977 for (cc::ScopedPtrVector<cc::Animation>::iterator it = | |
| 978 pending_threaded_animations_.begin(); | |
| 979 it != pending_threaded_animations_.end(); | |
| 980 ++it) | |
| 981 cc_layer_->AddAnimation(pending_threaded_animations_.take(it)); | |
| 982 | |
| 983 pending_threaded_animations_.clear(); | |
| 984 | |
| 985 for (size_t i = 0; i < children_.size(); ++i) | |
| 986 children_[i]->SendPendingThreadedAnimations(); | |
| 987 } | |
| 988 | |
| 989 void Layer::CreateCcLayer() { | |
| 990 if (type_ == LAYER_SOLID_COLOR) { | |
| 991 solid_color_layer_ = cc::SolidColorLayer::Create(); | |
| 992 cc_layer_ = solid_color_layer_.get(); | |
| 993 } else if (type_ == LAYER_NINE_PATCH) { | |
| 994 nine_patch_layer_ = cc::NinePatchLayer::Create(); | |
| 995 cc_layer_ = nine_patch_layer_.get(); | |
| 996 } else { | |
| 997 if (Layer::UsingPictureLayer()) | |
| 998 content_layer_ = cc::PictureLayer::Create(this); | |
| 999 else | |
| 1000 content_layer_ = cc::ContentLayer::Create(this); | |
| 1001 cc_layer_ = content_layer_.get(); | |
| 1002 } | |
| 1003 cc_layer_->SetTransformOrigin(gfx::Point3F()); | |
| 1004 cc_layer_->SetContentsOpaque(true); | |
| 1005 cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN); | |
| 1006 cc_layer_->AddLayerAnimationEventObserver(this); | |
| 1007 cc_layer_->SetLayerClient(this); | |
| 1008 RecomputePosition(); | |
| 1009 } | |
| 1010 | |
| 1011 gfx::Transform Layer::transform() const { | |
| 1012 return cc_layer_->transform(); | |
| 1013 } | |
| 1014 | |
| 1015 void Layer::RecomputeDrawsContentAndUVRect() { | |
| 1016 DCHECK(cc_layer_); | |
| 1017 gfx::Size size(bounds_.size()); | |
| 1018 if (texture_layer_.get()) { | |
| 1019 size.SetToMin(frame_size_in_dip_); | |
| 1020 gfx::PointF uv_top_left(0.f, 0.f); | |
| 1021 gfx::PointF uv_bottom_right( | |
| 1022 static_cast<float>(size.width()) / frame_size_in_dip_.width(), | |
| 1023 static_cast<float>(size.height()) / frame_size_in_dip_.height()); | |
| 1024 texture_layer_->SetUV(uv_top_left, uv_bottom_right); | |
| 1025 } else if (delegated_renderer_layer_.get() || surface_layer_.get()) { | |
| 1026 size.SetToMin(frame_size_in_dip_); | |
| 1027 } | |
| 1028 cc_layer_->SetBounds(size); | |
| 1029 } | |
| 1030 | |
| 1031 void Layer::RecomputePosition() { | |
| 1032 cc_layer_->SetPosition(bounds_.origin() + subpixel_position_offset_); | |
| 1033 } | |
| 1034 | |
| 1035 void Layer::AddAnimatorsInTreeToCollection( | |
| 1036 LayerAnimatorCollection* collection) { | |
| 1037 DCHECK(collection); | |
| 1038 if (IsAnimating()) | |
| 1039 animator_->AddToCollection(collection); | |
| 1040 std::for_each( | |
| 1041 children_.begin(), | |
| 1042 children_.end(), | |
| 1043 std::bind2nd(std::mem_fun(&Layer::AddAnimatorsInTreeToCollection), | |
| 1044 collection)); | |
| 1045 } | |
| 1046 | |
| 1047 void Layer::RemoveAnimatorsInTreeFromCollection( | |
| 1048 LayerAnimatorCollection* collection) { | |
| 1049 DCHECK(collection); | |
| 1050 if (IsAnimating()) | |
| 1051 animator_->RemoveFromCollection(collection); | |
| 1052 std::for_each( | |
| 1053 children_.begin(), | |
| 1054 children_.end(), | |
| 1055 std::bind2nd(std::mem_fun(&Layer::RemoveAnimatorsInTreeFromCollection), | |
| 1056 collection)); | |
| 1057 } | |
| 1058 | |
| 1059 bool Layer::IsAnimating() const { | |
| 1060 return animator_.get() && animator_->is_animating(); | |
| 1061 } | |
| 1062 | |
| 1063 } // namespace ui | |
| OLD | NEW |