| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/style/system_shadow_on_texture_layer.h" |
| |
| #include "ash/style/style_util.h" |
| #include "ui/color/color_provider.h" |
| #include "ui/compositor/paint_recorder.h" |
| #include "ui/gfx/skia_paint_util.h" |
| |
| namespace ash { |
| |
| SystemShadowOnTextureLayer::SystemShadowOnTextureLayer(SystemShadow::Type type) |
| : type_(type), |
| shadow_values_(gfx::ShadowValue::MakeChromeOSSystemUIShadowValues( |
| SystemShadow::GetElevationFromType(type))) { |
| layer_.SetFillsBoundsOpaquely(false); |
| layer_.set_delegate(this); |
| layer_.SetBounds(GetLayerBounds()); |
| } |
| |
| SystemShadowOnTextureLayer::~SystemShadowOnTextureLayer() = default; |
| |
| void SystemShadowOnTextureLayer::SetType(SystemShadow::Type type) { |
| type_ = type; |
| UpdateShadowValues(); |
| UpdateLayer(); |
| } |
| |
| void SystemShadowOnTextureLayer::SetContentBounds(const gfx::Rect& bounds) { |
| content_bounds_ = bounds; |
| layer_.SetBounds(GetLayerBounds()); |
| UpdateLayer(); |
| } |
| |
| void SystemShadowOnTextureLayer::SetRoundedCornerRadius(int corner_radius) { |
| SetRoundedCorners(gfx::RoundedCornersF(corner_radius)); |
| } |
| |
| void SystemShadowOnTextureLayer::SetRoundedCorners( |
| const gfx::RoundedCornersF& rounded_corners) { |
| if (rounded_corners_ == rounded_corners) { |
| return; |
| } |
| |
| rounded_corners_ = rounded_corners; |
| UpdateLayer(); |
| } |
| |
| const gfx::Rect& SystemShadowOnTextureLayer::GetContentBounds() { |
| return content_bounds_; |
| } |
| |
| ui::Layer* SystemShadowOnTextureLayer::GetLayer() { |
| return &layer_; |
| } |
| |
| ui::Layer* SystemShadowOnTextureLayer::GetNinePatchLayer() { |
| return nullptr; |
| } |
| |
| gfx::Rect SystemShadowOnTextureLayer::GetLayerBounds() const { |
| gfx::Rect layer_bounds = content_bounds_; |
| layer_bounds.Inset(gfx::ShadowValue::GetMargin(shadow_values_)); |
| return layer_bounds; |
| } |
| |
| const gfx::ShadowValues SystemShadowOnTextureLayer::GetShadowValuesForTesting() |
| const { |
| return shadow_values_; |
| } |
| |
| void SystemShadowOnTextureLayer::UpdateLayer() { |
| layer_.SchedulePaint(GetLayerBounds()); |
| } |
| |
| void SystemShadowOnTextureLayer::UpdateShadowValues() { |
| const int elevation = SystemShadow::GetElevationFromType(type_); |
| auto iter = colors_map_.find(elevation); |
| if (iter == colors_map_.end()) { |
| shadow_values_ = |
| gfx::ShadowValue::MakeChromeOSSystemUIShadowValues(elevation); |
| } else { |
| shadow_values_ = gfx::ShadowValue::MakeChromeOSSystemUIShadowValues( |
| elevation, /*key_shadow_color=*/iter->second.first, |
| /*second_color=*/iter->second.second); |
| } |
| } |
| |
| void SystemShadowOnTextureLayer::OnPaintLayer(const ui::PaintContext& context) { |
| // Create a rounded rect of content area. |
| const gfx::Rect r_rect_bounds = |
| content_bounds_ - GetLayerBounds().OffsetFromOrigin(); |
| SkRRect r_rect; |
| float upper_left = rounded_corners_.upper_left(); |
| float upper_right = rounded_corners_.upper_right(); |
| float lower_right = rounded_corners_.lower_right(); |
| float lower_left = rounded_corners_.lower_left(); |
| SkVector radii[4] = {{upper_left, upper_left}, |
| {upper_right, upper_right}, |
| {lower_right, lower_right}, |
| {lower_left, lower_left}}; |
| r_rect.setRectRadii(gfx::RectToSkRect(r_rect_bounds), radii); |
| |
| // Clip out the center. |
| ui::PaintRecorder recorder(context, content_bounds_.size()); |
| recorder.canvas()->sk_canvas()->clipRRect(r_rect, SkClipOp::kDifference, |
| true); |
| // Paint shadow. |
| cc::PaintFlags shadow_flags; |
| shadow_flags.setAntiAlias(true); |
| shadow_flags.setLooper(gfx::CreateShadowDrawLooper(shadow_values_)); |
| // Due to anti alias, we should fill transparent color to the rounded corner |
| // area. |
| shadow_flags.setColor(SK_ColorTRANSPARENT); |
| recorder.canvas()->sk_canvas()->drawRRect(r_rect, shadow_flags); |
| } |
| |
| void SystemShadowOnTextureLayer::OnDeviceScaleFactorChanged( |
| float old_device_scale_factor, |
| float new_device_scale_factor) {} |
| |
| void SystemShadowOnTextureLayer::UpdateShadowColors( |
| const ui::ColorProvider* color_provider) { |
| colors_map_ = StyleUtil::CreateShadowElevationToColorsMap(color_provider); |
| UpdateShadowValues(); |
| UpdateLayer(); |
| } |
| |
| } // namespace ash |