Commit fe635a27 authored by David Black's avatar David Black Committed by Commit Bot

Paint contents for holding space tray icon items.

Contents are derived from the image for the associated holding space
item. We crop and resize the holding space item's image as necessary to
properly fit our icon item.

Screenshot: https://screenshot.googleplex.com/uDkubRhHiiF6x9z

Bug: 1142572
Change-Id: Iac13dbb71499d44657fe20da25759054e7cb6ba6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2508130
Commit-Queue: David Black <dmblack@google.com>
Reviewed-by: default avatarToni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#822515}
parent 2357c735
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/system/holding_space/holding_space_tray_icon_item.h" #include "ash/system/holding_space/holding_space_tray_icon_item.h"
#include "ash/public/cpp/holding_space/holding_space_constants.h" #include "ash/public/cpp/holding_space/holding_space_constants.h"
#include "ash/public/cpp/holding_space/holding_space_item.h"
#include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_config.h"
#include "ash/system/holding_space/holding_space_tray_icon.h" #include "ash/system/holding_space/holding_space_tray_icon.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_constants.h"
...@@ -12,6 +13,8 @@ ...@@ -12,6 +13,8 @@
#include "ui/compositor/paint_recorder.h" #include "ui/compositor/paint_recorder.h"
#include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/shadow_util.h" #include "ui/gfx/shadow_util.h"
#include "ui/gfx/skia_paint_util.h" #include "ui/gfx/skia_paint_util.h"
...@@ -22,12 +25,25 @@ namespace { ...@@ -22,12 +25,25 @@ namespace {
// Appearance. // Appearance.
constexpr int kElevation = 2; constexpr int kElevation = 2;
// Returns the shadow details to use when painting elevation for `layer`. // Helpers ---------------------------------------------------------------------
const gfx::ShadowDetails GetShadowDetails(const ui::Layer* layer) {
DCHECK(layer); // Returns the shadow details to use when painting elevation.
const gfx::Size size = layer->size(); const gfx::ShadowDetails& GetShadowDetails() {
return gfx::ShadowDetails::Get( return gfx::ShadowDetails::Get(kElevation, /*radius=*/kTrayItemSize / 2);
kElevation, /*radius=*/std::min(size.width(), size.height()) / 2); }
// Returns contents bounds for painting, having accounted for shadow details.
gfx::Rect GetContentsBounds() {
gfx::Size contents_size(kTrayItemSize, kTrayItemSize);
gfx::Rect contents_bounds(contents_size);
const gfx::ShadowDetails& shadow = GetShadowDetails();
const gfx::Insets shadow_margins(gfx::ShadowValue::GetMargin(shadow.values));
contents_size.Enlarge(shadow_margins.width(), shadow_margins.height());
contents_bounds.ClampToCenteredSize(contents_size);
return contents_bounds;
} }
// Performs set up of the specified `animation_settings`. // Performs set up of the specified `animation_settings`.
...@@ -45,7 +61,14 @@ void SetUpAnimation(ui::ScopedLayerAnimationSettings* animation_settings) { ...@@ -45,7 +61,14 @@ void SetUpAnimation(ui::ScopedLayerAnimationSettings* animation_settings) {
HoldingSpaceTrayIconItem::HoldingSpaceTrayIconItem(HoldingSpaceTrayIcon* icon, HoldingSpaceTrayIconItem::HoldingSpaceTrayIconItem(HoldingSpaceTrayIcon* icon,
const HoldingSpaceItem* item) const HoldingSpaceItem* item)
: icon_(icon), item_(item) {} : icon_(icon), item_(item) {
image_subscription_ =
item->image().AddImageSkiaChangedCallback(base::BindRepeating(
&HoldingSpaceTrayIconItem::OnHoldingSpaceItemImageChanged,
base::Unretained(this)));
if (!item->image().image_skia().isNull())
OnHoldingSpaceItemImageChanged();
}
HoldingSpaceTrayIconItem::~HoldingSpaceTrayIconItem() = default; HoldingSpaceTrayIconItem::~HoldingSpaceTrayIconItem() = default;
...@@ -132,17 +155,9 @@ void HoldingSpaceTrayIconItem::AnimateUnshift() { ...@@ -132,17 +155,9 @@ void HoldingSpaceTrayIconItem::AnimateUnshift() {
} }
void HoldingSpaceTrayIconItem::OnPaintLayer(const ui::PaintContext& context) { void HoldingSpaceTrayIconItem::OnPaintLayer(const ui::PaintContext& context) {
DCHECK(layer_); ui::PaintRecorder recorder(context, gfx::Size(kTrayItemSize, kTrayItemSize));
const gfx::Rect contents_bounds = GetContentsBounds();
const gfx::ShadowDetails& shadow = GetShadowDetails(layer_.get());
const gfx::Insets shadow_margins(gfx::ShadowValue::GetMargin(shadow.values));
gfx::Size contents_size = layer_->size();
contents_size.Enlarge(shadow_margins.width(), shadow_margins.height());
gfx::Rect contents_bounds = layer_->bounds();
contents_bounds.ClampToCenteredSize(contents_size);
ui::PaintRecorder recorder(context, layer_->size());
PaintBackground(recorder.canvas(), contents_bounds); PaintBackground(recorder.canvas(), contents_bounds);
PaintContents(recorder.canvas(), contents_bounds); PaintContents(recorder.canvas(), contents_bounds);
} }
...@@ -171,6 +186,7 @@ void HoldingSpaceTrayIconItem::CreateLayer() { ...@@ -171,6 +186,7 @@ void HoldingSpaceTrayIconItem::CreateLayer() {
DCHECK(!layer_); DCHECK(!layer_);
layer_ = std::make_unique<ui::Layer>(ui::LAYER_TEXTURED); layer_ = std::make_unique<ui::Layer>(ui::LAYER_TEXTURED);
layer_->SetBounds(gfx::Rect(0, 0, kTrayItemSize, kTrayItemSize)); layer_->SetBounds(gfx::Rect(0, 0, kTrayItemSize, kTrayItemSize));
layer_->SetFillsBoundsOpaquely(false);
layer_->SetTransform(transform_); layer_->SetTransform(transform_);
layer_->set_delegate(this); layer_->set_delegate(this);
} }
...@@ -188,17 +204,52 @@ void HoldingSpaceTrayIconItem::PaintBackground( ...@@ -188,17 +204,52 @@ void HoldingSpaceTrayIconItem::PaintBackground(
cc::PaintFlags flags; cc::PaintFlags flags;
flags.setAntiAlias(true); flags.setAntiAlias(true);
flags.setColor(SK_ColorWHITE); flags.setColor(SK_ColorWHITE);
flags.setLooper( flags.setLooper(gfx::CreateShadowDrawLooper(GetShadowDetails().values));
gfx::CreateShadowDrawLooper(GetShadowDetails(layer_.get()).values));
canvas->DrawCircle( canvas->DrawCircle(
contents_bounds.CenterPoint(), contents_bounds.CenterPoint(),
std::min(contents_bounds.width(), contents_bounds.height()) / 2, flags); std::min(contents_bounds.width(), contents_bounds.height()) / 2, flags);
} }
// TODO(crbug.com/1142572): Implement.
void HoldingSpaceTrayIconItem::PaintContents(gfx::Canvas* canvas, void HoldingSpaceTrayIconItem::PaintContents(gfx::Canvas* canvas,
const gfx::Rect& contents_bounds) { const gfx::Rect& contents_bounds) {
NOTIMPLEMENTED(); if (image_.isNull())
return;
const gfx::Point center_point = contents_bounds.CenterPoint();
const int radius =
std::min(contents_bounds.width(), contents_bounds.height()) / 2;
// Clip `image_` to a circular path.
gfx::ScopedCanvas scoped_canvas(canvas);
canvas->ClipPath(
/*path=*/SkPath::Circle(center_point.x(), center_point.y(), radius),
/*anti_alias=*/true);
canvas->DrawImageInt(image_, contents_bounds.x(), contents_bounds.y());
}
void HoldingSpaceTrayIconItem::OnHoldingSpaceItemImageChanged() {
image_ = item_->image().image_skia();
// Crop to square (if necessary).
gfx::Size square_size = image_.size();
square_size.SetToMin(gfx::Size(square_size.height(), square_size.width()));
if (image_.size() != square_size) {
gfx::Rect square_rect(image_.size());
square_rect.ClampToCenteredSize(square_size);
image_ = gfx::ImageSkiaOperations::ExtractSubset(image_, square_rect);
}
// Resize to contents size (if necessary).
gfx::Size contents_size = GetContentsBounds().size();
if (image_.size() != contents_size) {
image_ = gfx::ImageSkiaOperations::CreateResizedImage(
image_, skia::ImageOperations::ResizeMethod::RESIZE_BEST,
contents_size);
}
if (layer_)
layer_->SchedulePaint(layer_->bounds());
} }
} // namespace ash } // namespace ash
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <string> #include <string>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/public/cpp/holding_space/holding_space_image.h"
#include "base/callback.h" #include "base/callback.h"
#include "ui/compositor/layer_animation_observer.h" #include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_delegate.h"
...@@ -76,9 +77,16 @@ class ASH_EXPORT HoldingSpaceTrayIconItem ...@@ -76,9 +77,16 @@ class ASH_EXPORT HoldingSpaceTrayIconItem
void PaintBackground(gfx::Canvas* canvas, const gfx::Rect& contents_bounds); void PaintBackground(gfx::Canvas* canvas, const gfx::Rect& contents_bounds);
void PaintContents(gfx::Canvas* canvas, const gfx::Rect& contents_bounds); void PaintContents(gfx::Canvas* canvas, const gfx::Rect& contents_bounds);
// Invoked when the associated holding space `item_`'s image has been changed.
void OnHoldingSpaceItemImageChanged();
HoldingSpaceTrayIcon* const icon_; HoldingSpaceTrayIcon* const icon_;
const HoldingSpaceItem* item_; const HoldingSpaceItem* item_;
// A cached representation of the associated holding space `item_`'s image
// which has been cropped and resized to be painted to `layer_`.
gfx::ImageSkia image_;
// This is a proxy for `layer_`'s transform and represents the target // This is a proxy for `layer_`'s transform and represents the target
// position of this item. Because `layer_` only exists while in `icon_`'s // position of this item. Because `layer_` only exists while in `icon_`'s
// viewport, we need to manage transform ourselves and continue to update it // viewport, we need to manage transform ourselves and continue to update it
...@@ -90,6 +98,10 @@ class ASH_EXPORT HoldingSpaceTrayIconItem ...@@ -90,6 +98,10 @@ class ASH_EXPORT HoldingSpaceTrayIconItem
// while in the `icon_`s viewport as determined by the current `transform_`. // while in the `icon_`s viewport as determined by the current `transform_`.
std::unique_ptr<ui::Layer> layer_; std::unique_ptr<ui::Layer> layer_;
// We need to repaint `layer_` whenever the associated holding space `item_`'s
// image is changed. We receive change events while this subscription exists.
std::unique_ptr<HoldingSpaceImage::Subscription> image_subscription_;
// Closure to invoke on completion of `AnimateOut()`. It is expected that this // Closure to invoke on completion of `AnimateOut()`. It is expected that this
// instance may be deleted during invocation. // instance may be deleted during invocation.
base::OnceClosure animate_out_closure_; base::OnceClosure animate_out_closure_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment