// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/compositor/layer/content_layer.h"
#include <vector>
#include "base/lazy_instance.h"
#include "cc/slim/filter.h"
#include "cc/slim/layer.h"
#include "chrome/browser/android/compositor/layer/thumbnail_layer.h"
#include "chrome/browser/android/compositor/tab_content_manager.h"
#include "ui/gfx/geometry/size.h"
namespace android {
// static
scoped_refptr<ContentLayer> ContentLayer::Create(
TabContentManager* tab_content_manager) {
return base::WrapRefCounted(new ContentLayer(tab_content_manager));
}
static void SetOpacityOnLeaf(scoped_refptr<cc::slim::Layer> layer,
float alpha) {
const auto& children = layer->children();
if (!children.empty()) {
layer->SetOpacity(1.0f);
for (const auto& child : children) {
SetOpacityOnLeaf(child, alpha);
}
} else {
layer->SetOpacity(alpha);
}
}
static cc::slim::Layer* GetDrawsContentLeaf(
scoped_refptr<cc::slim::Layer> layer) {
if (!layer.get()) {
return nullptr;
}
// If the subtree is hidden, then any layers in this tree will not be drawn.
if (layer->hide_layer_and_subtree()) {
return nullptr;
}
if (layer->opacity() == 0.0f) {
return nullptr;
}
if (layer->draws_content()) {
return layer.get();
}
const auto& children = layer->children();
for (const auto& child : children) {
cc::slim::Layer* leaf = GetDrawsContentLeaf(child);
if (leaf) {
return leaf;
}
}
return nullptr;
}
void ContentLayer::SetProperties(int id,
bool can_use_live_layer,
float static_to_view_blend,
bool should_override_content_alpha,
float content_alpha_override,
float saturation,
bool should_clip,
const gfx::Rect& clip) {
scoped_refptr<cc::slim::Layer> live_layer =
tab_content_manager_->GetLiveLayer(id);
if (live_layer) {
live_layer->SetHideLayerAndSubtree(!can_use_live_layer);
}
bool live_layer_draws = GetDrawsContentLeaf(live_layer);
float content_opacity =
should_override_content_alpha ? content_alpha_override : 1.0f;
float static_opacity =
should_override_content_alpha ? content_alpha_override : 1.0f;
if (live_layer_draws) {
static_opacity = static_to_view_blend;
}
layer_->RemoveAllChildren();
if (live_layer.get()) {
live_layer->SetMasksToBounds(should_clip);
live_layer->SetBounds(clip.size());
// Don't override the opacity for layers internal to the WebContents.
live_layer->SetOpacity(content_opacity);
layer_->AddChild(live_layer);
}
if (static_opacity > 0) {
ThumbnailLayer* static_layer = tab_content_manager_->GetStaticLayer(id);
if (static_layer) {
static_layer->layer()->SetIsDrawable(true);
if (should_clip) {
static_layer->Clip(clip);
} else {
static_layer->ClearClip();
}
// TOOD(liuwilliam): The opacity should only need to be set on the static
// layer, instead of all its children. The recursive setting was a
// workaround for some old CC bug.
SetOpacityOnLeaf(static_layer->layer(), static_opacity);
std::vector<cc::slim::Filter> filters;
if (saturation < 1.0f) {
filters.push_back(cc::slim::Filter::CreateSaturation(saturation));
}
static_layer->layer()->SetFilters(std::move(filters));
layer_->AddChild(static_layer->layer());
}
}
}
gfx::Size ContentLayer::ComputeSize(int id) const {
gfx::Size size;
scoped_refptr<cc::slim::Layer> live_layer =
tab_content_manager_->GetLiveLayer(id);
cc::slim::Layer* leaf_that_draws = GetDrawsContentLeaf(live_layer);
if (leaf_that_draws) {
size.SetToMax(leaf_that_draws->bounds());
}
ThumbnailLayer* static_layer = tab_content_manager_->GetStaticLayer(id);
if (static_layer && GetDrawsContentLeaf(static_layer->layer())) {
size.SetToMax(static_layer->layer()->bounds());
}
return size;
}
scoped_refptr<cc::slim::Layer> ContentLayer::layer() {
return layer_;
}
ContentLayer::ContentLayer(TabContentManager* tab_content_manager)
: layer_(cc::slim::Layer::Create()),
tab_content_manager_(tab_content_manager) {}
ContentLayer::~ContentLayer() = default;
} // namespace android