#include "chrome/browser/android/compositor/layer/overlay_panel_layer.h"
#include "cc/resources/scoped_ui_resource.h"
#include "cc/slim/layer.h"
#include "cc/slim/nine_patch_layer.h"
#include "cc/slim/solid_color_layer.h"
#include "cc/slim/ui_resource_layer.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/android/resources/nine_patch_resource.h"
#include "ui/android/resources/resource_manager.h"
#include "ui/base/l10n/l10n_util_android.h"
#include "ui/gfx/color_utils.h"
namespace android {
scoped_refptr<cc::slim::Layer> OverlayPanelLayer::GetIconLayer() {
if (panel_icon_resource_id_ == kInvalidResourceID)
return nullptr;
ui::Resource* panel_icon_resource = resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, panel_icon_resource_id_);
DCHECK(panel_icon_resource);
if (panel_icon_->parent() != layer_) {
layer_->AddChild(panel_icon_);
}
panel_icon_->SetUIResourceId(panel_icon_resource->ui_resource()->id());
panel_icon_->SetBounds(panel_icon_resource->size());
return panel_icon_;
}
void OverlayPanelLayer::AddBarTextLayer(
scoped_refptr<cc::slim::Layer> text_layer) {
if (text_container_->parent() != layer_)
layer_->AddChild(text_container_);
if (text_layer->parent() != text_container_)
text_container_->AddChild(text_layer);
}
void OverlayPanelLayer::SetResourceIds(int bar_text_resource_id,
int panel_shadow_resource_id,
int rounded_bar_top_resource_id,
int bar_shadow_resource_id,
int panel_icon_resource_id,
int drag_handlebar_resource_id,
int open_tab_icon_resource_id,
int close_icon_resource_id) {
bar_text_resource_id_ = bar_text_resource_id;
panel_shadow_resource_id_ = panel_shadow_resource_id;
rounded_bar_top_resource_id_ = rounded_bar_top_resource_id;
bar_shadow_resource_id_ = bar_shadow_resource_id;
panel_icon_resource_id_ = panel_icon_resource_id;
drag_handlebar_resource_id_ = drag_handlebar_resource_id;
open_tab_icon_resource_id_ = open_tab_icon_resource_id;
close_icon_resource_id_ = close_icon_resource_id;
}
void OverlayPanelLayer::SetProperties(
float dp_to_px,
const scoped_refptr<cc::slim::Layer>& content_layer,
float content_offset_y,
float panel_x,
float panel_y,
float panel_width,
float panel_height,
int bar_background_color,
float bar_margin_side,
float bar_margin_top,
float bar_margin_bottom,
float bar_height,
float bar_offset_y,
float bar_text_opacity,
bool bar_border_visible,
float bar_border_height,
int icon_tint,
int drag_handlebar_tint,
float icon_opacity,
int separator_line_color,
float in_bar_related_searches_height) {
bar_height = floor(bar_height);
float bar_top_y = bar_offset_y;
float bar_bottom = bar_top_y + bar_height;
bool is_rtl = l10n_util::IsLayoutRtl();
int content_top_y = bar_top_y;
int content_height = bar_height - in_bar_related_searches_height;
int rounded_top_height = 0;
gfx::Size rounded_bar_top_size;
gfx::PointF rounded_bar_top_position;
ui::NinePatchResource* rounded_bar_top_resource = nullptr;
content_top_y += bar_margin_top;
content_height -= bar_margin_top;
content_height -= bar_margin_bottom;
rounded_bar_top_resource =
ui::NinePatchResource::From(resource_manager_->GetStaticResourceWithTint(
rounded_bar_top_resource_id_, bar_background_color));
rounded_bar_top_size = gfx::Size(rounded_bar_top_resource->size().width(),
rounded_bar_top_resource->size().height());
const int vertical_fudge_factor = 2;
rounded_top_height = rounded_bar_top_resource->size().height();
rounded_bar_top_position =
gfx::PointF(-rounded_bar_top_resource->padding().x(),
bar_top_y + vertical_fudge_factor);
if (panel_shadow_resource_id_ != kInvalidResourceID) {
if (panel_shadow_->parent() != layer_) {
layer_->InsertChild(panel_shadow_, 0);
}
ui::NinePatchResource* panel_shadow_resource =
ui::NinePatchResource::From(resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, panel_shadow_resource_id_));
DCHECK(panel_shadow_resource);
gfx::Size shadow_res_size = panel_shadow_resource->size();
panel_shadow_->SetUIResourceId(panel_shadow_resource->ui_resource()->id());
panel_shadow_->SetAperture(panel_shadow_resource->aperture());
DCHECK(rounded_bar_top_resource);
int shadow_thickness = shadow_res_size.height() - rounded_top_height;
gfx::Size shadow_bounds(panel_width + (shadow_thickness * 2),
panel_height + shadow_thickness);
panel_shadow_->SetBounds(shadow_bounds);
panel_shadow_->SetBorder(panel_shadow_resource->Border(shadow_bounds));
gfx::PointF shadow_position(-shadow_thickness,
bar_top_y - shadow_thickness);
panel_shadow_->SetPosition(shadow_position);
}
DCHECK(rounded_bar_top_resource_id_ != kInvalidResourceID);
rounded_bar_top_->SetIsDrawable(true);
DCHECK(rounded_bar_top_resource);
gfx::Size bounds(panel_width, rounded_bar_top_resource->size().height());
rounded_bar_top_->SetUIResourceId(
rounded_bar_top_resource->ui_resource()->id());
rounded_bar_top_->SetBounds(bounds);
rounded_bar_top_->SetAperture(rounded_bar_top_resource->aperture());
rounded_bar_top_->SetBorder(rounded_bar_top_resource->Border(bounds));
rounded_bar_top_->SetPosition(rounded_bar_top_position);
rounded_bar_top_->SetOpacity(1.0f);
gfx::Size background_size(panel_width, bar_height - rounded_top_height);
bar_background_->SetBounds(background_size);
bar_background_->SetPosition(
gfx::PointF(0.f, bar_top_y + rounded_top_height));
bar_background_->SetBackgroundColor(
SkColor4f::FromColor(bar_background_color));
ui::Resource* bar_text_resource = resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_DYNAMIC, bar_text_resource_id_);
if (bar_text_resource) {
float bar_padding_top = content_top_y + content_height / 2 -
bar_text_resource->size().height() / 2;
bar_text_->SetUIResourceId(bar_text_resource->ui_resource()->id());
bar_text_->SetBounds(bar_text_resource->size());
bar_text_->SetPosition(gfx::PointF(0.f, bar_padding_top));
bar_text_->SetOpacity(bar_text_opacity);
}
scoped_refptr<cc::slim::Layer> icon_layer = GetIconLayer();
if (icon_layer) {
float icon_padding = (kDefaultIconWidthDp * dp_to_px -
icon_layer->bounds().width()) / 2.0f;
float icon_x;
if (is_rtl) {
icon_x = panel_width - icon_layer->bounds().width() -
(bar_margin_side + icon_padding);
} else {
icon_x = bar_margin_side + icon_padding;
}
float icon_y =
content_top_y + content_height / 2 - icon_layer->bounds().height() / 2;
icon_layer->SetPosition(gfx::PointF(icon_x, icon_y));
}
if (drag_handlebar_resource_id_ != kInvalidResourceID) {
if (drag_handlebar_->parent() != layer_)
layer_->AddChild(drag_handlebar_);
ui::Resource* drag_handlebar_resource =
resource_manager_->GetStaticResourceWithTint(
drag_handlebar_resource_id_, drag_handlebar_tint);
drag_handlebar_->SetUIResourceId(
drag_handlebar_resource->ui_resource()->id());
drag_handlebar_->SetBounds(drag_handlebar_resource->size());
float drag_handlebar_left =
panel_width / 2 - drag_handlebar_resource->size().width() / 2;
float drag_handlebar_top = bar_top_y + bar_margin_top -
drag_handlebar_resource->size().height() / 2;
drag_handlebar_->SetPosition(
gfx::PointF(drag_handlebar_left, drag_handlebar_top));
}
int close_icon_width = 0;
float close_icon_left = 0.f;
if (is_rtl) {
close_icon_left = bar_margin_side;
} else {
close_icon_left = panel_width - bar_margin_side;
}
if (close_icon_resource_id_ != kInvalidResourceID) {
ui::Resource* close_icon_resource =
resource_manager_->GetStaticResourceWithTint(close_icon_resource_id_,
icon_tint);
close_icon_width = close_icon_resource->size().width();
if (!is_rtl) {
close_icon_left = close_icon_left - close_icon_width;
}
float close_icon_top = content_top_y + content_height / 2 -
close_icon_resource->size().height() / 2;
close_icon_->SetUIResourceId(close_icon_resource->ui_resource()->id());
close_icon_->SetBounds(close_icon_resource->size());
close_icon_->SetPosition(gfx::PointF(close_icon_left, close_icon_top));
close_icon_->SetOpacity(icon_opacity);
}
if (open_tab_icon_resource_id_ != kInvalidResourceID) {
ui::Resource* open_tab_icon_resource =
resource_manager_->GetStaticResourceWithTint(open_tab_icon_resource_id_,
icon_tint);
float open_tab_top = content_top_y + content_height / 2 -
open_tab_icon_resource->size().height() / 2;
float open_tab_left;
float spacing_between_icons = 2 * bar_margin_side;
float margin_from_close_icon = close_icon_width + spacing_between_icons;
if (is_rtl) {
open_tab_left = close_icon_resource_id_ == kInvalidResourceID
? close_icon_left
: close_icon_left + margin_from_close_icon;
} else {
open_tab_left = close_icon_left - margin_from_close_icon;
}
open_tab_icon_->SetUIResourceId(
open_tab_icon_resource->ui_resource()->id());
open_tab_icon_->SetBounds(open_tab_icon_resource->size());
open_tab_icon_->SetPosition(gfx::PointF(open_tab_left, open_tab_top));
open_tab_icon_->SetOpacity(icon_opacity);
}
content_container_->SetPosition(
gfx::PointF(0.f, content_offset_y));
content_container_->SetBounds(gfx::Size(panel_width, panel_height));
content_container_->SetBackgroundColor(
SkColor4f::FromColor(bar_background_color));
if (content_layer) {
if (content_layer->parent() != content_container_)
content_container_->AddChild(content_layer);
} else {
content_container_->RemoveAllChildren();
}
ui::Resource* bar_shadow_resource = resource_manager_->GetResource(
ui::ANDROID_RESOURCE_TYPE_STATIC, bar_shadow_resource_id_);
if (bar_shadow_resource) {
if (bar_shadow_->parent() != layer_)
layer_->AddChild(bar_shadow_);
int shadow_height = bar_shadow_resource->size().height();
gfx::Size shadow_size(panel_width, shadow_height);
bar_shadow_->SetUIResourceId(bar_shadow_resource->ui_resource()->id());
bar_shadow_->SetBounds(shadow_size);
bar_shadow_->SetPosition(gfx::PointF(0.f, bar_bottom));
bar_shadow_->SetOpacity(1.0f);
}
layer_->SetPosition(gfx::PointF(panel_x, panel_y));
if (bar_border_visible) {
gfx::Size bar_border_size(panel_width,
bar_border_height);
float border_y = bar_bottom - bar_border_height;
bar_border_->SetBounds(bar_border_size);
bar_border_->SetPosition(
gfx::PointF(0.f, border_y));
bar_border_->SetBackgroundColor(SkColor4f::FromColor(separator_line_color));
if (bar_border_->parent() != layer_)
layer_->AddChild(bar_border_);
} else if (bar_border_.get() && bar_border_->parent()) {
bar_border_->RemoveFromParent();
}
}
void OverlayPanelLayer::SetProgressBar(int progress_bar_background_resource_id,
int progress_bar_background_tint,
int progress_bar_resource_id,
int progress_bar_tint,
bool progress_bar_visible,
float progress_bar_position_y,
float progress_bar_height,
float progress_bar_opacity,
float progress_bar_completion,
float panel_width) {
bool should_render_progress_bar =
progress_bar_visible && progress_bar_opacity > 0.f;
if (should_render_progress_bar) {
ui::NinePatchResource* progress_bar_background_resource =
ui::NinePatchResource::From(
resource_manager_->GetStaticResourceWithTint(
progress_bar_background_resource_id,
progress_bar_background_tint));
ui::NinePatchResource* progress_bar_resource = ui::NinePatchResource::From(
resource_manager_->GetStaticResourceWithTint(progress_bar_resource_id,
progress_bar_tint));
DCHECK(progress_bar_background_resource);
DCHECK(progress_bar_resource);
if (progress_bar_background_->parent() != layer_)
layer_->AddChild(progress_bar_background_);
float progress_bar_y = progress_bar_position_y - progress_bar_height;
gfx::Size progress_bar_background_size(panel_width, progress_bar_height);
progress_bar_background_->SetUIResourceId(
progress_bar_background_resource->ui_resource()->id());
progress_bar_background_->SetBorder(
progress_bar_background_resource->Border(progress_bar_background_size));
progress_bar_background_->SetAperture(
progress_bar_background_resource->aperture());
progress_bar_background_->SetBounds(progress_bar_background_size);
progress_bar_background_->SetPosition(gfx::PointF(0.f, progress_bar_y));
progress_bar_background_->SetOpacity(progress_bar_opacity);
if (progress_bar_->parent() != layer_)
layer_->AddChild(progress_bar_);
float progress_bar_width = floor(panel_width * progress_bar_completion);
gfx::Size progress_bar_size(progress_bar_width, progress_bar_height);
progress_bar_->SetUIResourceId(progress_bar_resource->ui_resource()->id());
progress_bar_->SetBorder(progress_bar_resource->Border(progress_bar_size));
progress_bar_->SetAperture(progress_bar_resource->aperture());
progress_bar_->SetBounds(progress_bar_size);
progress_bar_->SetPosition(gfx::PointF(0.f, progress_bar_y));
progress_bar_->SetOpacity(progress_bar_opacity);
} else {
if (progress_bar_background_.get() && progress_bar_background_->parent())
progress_bar_background_->RemoveFromParent();
if (progress_bar_.get() && progress_bar_->parent())
progress_bar_->RemoveFromParent();
}
}
OverlayPanelLayer::OverlayPanelLayer(ui::ResourceManager* resource_manager)
: resource_manager_(resource_manager),
layer_(cc::slim::Layer::Create()),
panel_shadow_(cc::slim::NinePatchLayer::Create()),
rounded_bar_top_(cc::slim::NinePatchLayer::Create()),
bar_background_(cc::slim::SolidColorLayer::Create()),
bar_text_(cc::slim::UIResourceLayer::Create()),
bar_shadow_(cc::slim::UIResourceLayer::Create()),
panel_icon_(cc::slim::UIResourceLayer::Create()),
drag_handlebar_(cc::slim::UIResourceLayer::Create()),
open_tab_icon_(cc::slim::UIResourceLayer::Create()),
close_icon_(cc::slim::UIResourceLayer::Create()),
content_container_(cc::slim::SolidColorLayer::Create()),
text_container_(cc::slim::Layer::Create()),
bar_border_(cc::slim::SolidColorLayer::Create()),
progress_bar_(cc::slim::NinePatchLayer::Create()),
progress_bar_background_(cc::slim::NinePatchLayer::Create()) {
layer_->SetMasksToBounds(false);
layer_->SetIsDrawable(true);
panel_shadow_->SetIsDrawable(true);
panel_shadow_->SetFillCenter(false);
rounded_bar_top_->SetIsDrawable(false);
layer_->AddChild(rounded_bar_top_);
bar_background_->SetIsDrawable(true);
layer_->AddChild(bar_background_);
bar_text_->SetIsDrawable(true);
AddBarTextLayer(bar_text_);
panel_icon_->SetIsDrawable(true);
text_container_->SetIsDrawable(true);
drag_handlebar_->SetIsDrawable(true);
open_tab_icon_->SetIsDrawable(true);
layer_->AddChild(open_tab_icon_);
close_icon_->SetIsDrawable(true);
layer_->AddChild(close_icon_);
content_container_->SetIsDrawable(true);
layer_->AddChild(content_container_);
bar_border_->SetIsDrawable(true);
bar_shadow_->SetIsDrawable(true);
progress_bar_background_->SetIsDrawable(true);
progress_bar_background_->SetFillCenter(true);
progress_bar_->SetIsDrawable(true);
progress_bar_->SetFillCenter(true);
}
OverlayPanelLayer::~OverlayPanelLayer() = default;
scoped_refptr<cc::slim::Layer> OverlayPanelLayer::layer() {
return layer_;
}
}