| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/gfx/shadow_value.h" |
| |
| #include <stddef.h> |
| |
| #include <algorithm> |
| |
| #include "base/check_op.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "ui/gfx/color_palette.h" |
| #include "ui/gfx/geometry/insets.h" |
| #include "ui/gfx/geometry/vector2d_conversions.h" |
| |
| namespace gfx { |
| |
| namespace { |
| |
| Insets GetInsets(const ShadowValues& shadows, bool include_inner_blur) { |
| int left = 0; |
| int top = 0; |
| int right = 0; |
| int bottom = 0; |
| |
| for (size_t i = 0; i < shadows.size(); ++i) { |
| const ShadowValue& shadow = shadows[i]; |
| |
| double blur = shadow.blur(); |
| if (!include_inner_blur) |
| blur /= 2; |
| int blur_length = base::ClampRound(blur); |
| |
| left = std::max(left, blur_length - shadow.x()); |
| top = std::max(top, blur_length - shadow.y()); |
| right = std::max(right, blur_length + shadow.x()); |
| bottom = std::max(bottom, blur_length + shadow.y()); |
| } |
| |
| return Insets::TLBR(top, left, bottom, right); |
| } |
| |
| } // namespace |
| |
| ShadowValue ShadowValue::Scale(float scale) const { |
| Vector2d scaled_offset = ToFlooredVector2d(ScaleVector2d(offset_, scale)); |
| return ShadowValue(scaled_offset, blur_ * scale, color_); |
| } |
| |
| std::string ShadowValue::ToString() const { |
| return base::StringPrintf( |
| "(%d,%d),%.2f,rgba(%d,%d,%d,%d)", |
| offset_.x(), offset_.y(), |
| blur_, |
| SkColorGetR(color_), |
| SkColorGetG(color_), |
| SkColorGetB(color_), |
| SkColorGetA(color_)); |
| } |
| |
| // static |
| Insets ShadowValue::GetMargin(const ShadowValues& shadows) { |
| Insets margins = GetInsets(shadows, false); |
| return -margins; |
| } |
| |
| // static |
| Insets ShadowValue::GetBlurRegion(const ShadowValues& shadows) { |
| return GetInsets(shadows, true); |
| } |
| |
| // static |
| ShadowValues ShadowValue::MakeShadowValues(int elevation, |
| SkColor key_shadow_color, |
| SkColor ambient_shadow_color) { |
| // Refresh uses hand-tweaked shadows corresponding to a small set of |
| // elevations. Use the Refresh spec and designer input to add missing shadow |
| // values. |
| |
| // To match the CSS notion of blur (spread outside the bounding box) to the |
| // Skia notion of blur (spread outside and inside the bounding box), we have |
| // to double the designer-provided blur values. |
| const int kBlurCorrection = 2; |
| |
| switch (elevation) { |
| case 3: { |
| ShadowValue key = {Vector2d(0, 1), 12, key_shadow_color}; |
| ShadowValue ambient = {Vector2d(0, 4), 64, ambient_shadow_color}; |
| return {key, ambient}; |
| } |
| case 16: { |
| ShadowValue key = {Vector2d(0, 0), kBlurCorrection * 16, |
| key_shadow_color}; |
| ShadowValue ambient = {Vector2d(0, 12), kBlurCorrection * 16, |
| ambient_shadow_color}; |
| return {key, ambient}; |
| } |
| default: |
| // This surface has not been updated for Refresh. Fall back to the |
| // deprecated style. |
| DCHECK_EQ(key_shadow_color, ambient_shadow_color); |
| return MakeMdShadowValues(elevation, key_shadow_color); |
| } |
| } |
| |
| // static |
| ShadowValues ShadowValue::MakeMdShadowValues(int elevation, SkColor color) { |
| ShadowValues shadow_values; |
| // To match the CSS notion of blur (spread outside the bounding box) to the |
| // Skia notion of blur (spread outside and inside the bounding box), we have |
| // to double the designer-provided blur values. |
| const int kBlurCorrection = 2; |
| // "Key shadow": y offset is elevation and blur is twice the elevation. |
| shadow_values.emplace_back(Vector2d(0, elevation), |
| kBlurCorrection * elevation * 2, |
| SkColorSetA(color, 0x3d)); |
| // "Ambient shadow": no offset and blur matches the elevation. |
| shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation, |
| SkColorSetA(color, 0x1f)); |
| // To see what this looks like for elevation 24, try this CSS: |
| // box-shadow: 0 24px 48px rgba(0, 0, 0, .24), |
| // 0 0 24px rgba(0, 0, 0, .12); |
| return shadow_values; |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| // static |
| ShadowValues ShadowValue::MakeChromeOSSystemUIShadowValues(int elevation, |
| SkColor color) { |
| ShadowValues shadow_values; |
| // To match the CSS notion of blur (spread outside the bounding box) to the |
| // Skia notion of blur (spread outside and inside the bounding box), we have |
| // to double the designer-provided blur values. |
| const int kBlurCorrection = 2; |
| // "Key shadow": y offset is elevation and blur value is equal to the |
| // elevation. |
| shadow_values.emplace_back(Vector2d(0, elevation), |
| kBlurCorrection * elevation, |
| SkColorSetA(color, 0x3d)); |
| // "Ambient shadow": no offset and blur matches the elevation. |
| shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation, |
| SkColorSetA(color, 0x1a)); |
| // To see what this looks like for elevation 24, try this CSS: |
| // box-shadow: 0 24px 24px rgba(0, 0, 0, .24), |
| // 0 0 24px rgba(0, 0, 0, .10); |
| return shadow_values; |
| } |
| #endif |
| |
| } // namespace gfx |