1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// 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 {
// 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.
constexpr int kBlurCorrection = 2;
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.
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) {
// 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 MakeMdShadowValues(elevation, SkColorSetA(color, 0x3d),
SkColorSetA(color, 0x1f));
}
// static
ShadowValues ShadowValue::MakeMdShadowValues(int elevation,
SkColor key_shadow_color,
SkColor ambient_shadow_color) {
ShadowValues shadow_values;
// "Key shadow": y offset is elevation and blur is twice the elevation.
shadow_values.emplace_back(Vector2d(0, elevation),
kBlurCorrection * elevation * 2, key_shadow_color);
// "Ambient shadow": no offset and blur matches the elevation.
shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation,
ambient_shadow_color);
return shadow_values;
}
#if BUILDFLAG(IS_CHROMEOS)
// static
ShadowValues ShadowValue::MakeChromeOSSystemUIShadowValues(int elevation,
SkColor color) {
// 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 MakeChromeOSSystemUIShadowValues(elevation, SkColorSetA(color, 0x3d),
SkColorSetA(color, 0x1a));
}
// static
ShadowValues ShadowValue::MakeChromeOSSystemUIShadowValues(
int elevation,
SkColor key_shadow_color,
SkColor ambient_shadow_color) {
ShadowValues shadow_values;
// "Key shadow": y offset is elevation and blur equals to the elevation.
shadow_values.emplace_back(Vector2d(0, elevation),
kBlurCorrection * elevation, key_shadow_color);
// "Ambient shadow": no offset and blur matches the elevation.
shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation,
ambient_shadow_color);
return shadow_values;
}
#endif
} // namespace gfx
|