shadow_value.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/shadow_value.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include "base/check_op.h"
  8. #include "base/numerics/safe_conversions.h"
  9. #include "base/strings/stringprintf.h"
  10. #include "ui/gfx/color_palette.h"
  11. #include "ui/gfx/geometry/insets.h"
  12. #include "ui/gfx/geometry/vector2d_conversions.h"
  13. namespace gfx {
  14. namespace {
  15. Insets GetInsets(const ShadowValues& shadows, bool include_inner_blur) {
  16. int left = 0;
  17. int top = 0;
  18. int right = 0;
  19. int bottom = 0;
  20. for (size_t i = 0; i < shadows.size(); ++i) {
  21. const ShadowValue& shadow = shadows[i];
  22. double blur = shadow.blur();
  23. if (!include_inner_blur)
  24. blur /= 2;
  25. int blur_length = base::ClampRound(blur);
  26. left = std::max(left, blur_length - shadow.x());
  27. top = std::max(top, blur_length - shadow.y());
  28. right = std::max(right, blur_length + shadow.x());
  29. bottom = std::max(bottom, blur_length + shadow.y());
  30. }
  31. return Insets::TLBR(top, left, bottom, right);
  32. }
  33. } // namespace
  34. ShadowValue ShadowValue::Scale(float scale) const {
  35. Vector2d scaled_offset = ToFlooredVector2d(ScaleVector2d(offset_, scale));
  36. return ShadowValue(scaled_offset, blur_ * scale, color_);
  37. }
  38. std::string ShadowValue::ToString() const {
  39. return base::StringPrintf(
  40. "(%d,%d),%.2f,rgba(%d,%d,%d,%d)",
  41. offset_.x(), offset_.y(),
  42. blur_,
  43. SkColorGetR(color_),
  44. SkColorGetG(color_),
  45. SkColorGetB(color_),
  46. SkColorGetA(color_));
  47. }
  48. // static
  49. Insets ShadowValue::GetMargin(const ShadowValues& shadows) {
  50. Insets margins = GetInsets(shadows, false);
  51. return -margins;
  52. }
  53. // static
  54. Insets ShadowValue::GetBlurRegion(const ShadowValues& shadows) {
  55. return GetInsets(shadows, true);
  56. }
  57. // static
  58. ShadowValues ShadowValue::MakeShadowValues(int elevation,
  59. SkColor key_shadow_color,
  60. SkColor ambient_shadow_color) {
  61. // Refresh uses hand-tweaked shadows corresponding to a small set of
  62. // elevations. Use the Refresh spec and designer input to add missing shadow
  63. // values.
  64. // To match the CSS notion of blur (spread outside the bounding box) to the
  65. // Skia notion of blur (spread outside and inside the bounding box), we have
  66. // to double the designer-provided blur values.
  67. const int kBlurCorrection = 2;
  68. switch (elevation) {
  69. case 3: {
  70. ShadowValue key = {Vector2d(0, 1), 12, key_shadow_color};
  71. ShadowValue ambient = {Vector2d(0, 4), 64, ambient_shadow_color};
  72. return {key, ambient};
  73. }
  74. case 16: {
  75. ShadowValue key = {Vector2d(0, 0), kBlurCorrection * 16,
  76. key_shadow_color};
  77. ShadowValue ambient = {Vector2d(0, 12), kBlurCorrection * 16,
  78. ambient_shadow_color};
  79. return {key, ambient};
  80. }
  81. default:
  82. // This surface has not been updated for Refresh. Fall back to the
  83. // deprecated style.
  84. DCHECK_EQ(key_shadow_color, ambient_shadow_color);
  85. return MakeMdShadowValues(elevation, key_shadow_color);
  86. }
  87. }
  88. // static
  89. ShadowValues ShadowValue::MakeMdShadowValues(int elevation, SkColor color) {
  90. ShadowValues shadow_values;
  91. // To match the CSS notion of blur (spread outside the bounding box) to the
  92. // Skia notion of blur (spread outside and inside the bounding box), we have
  93. // to double the designer-provided blur values.
  94. const int kBlurCorrection = 2;
  95. // "Key shadow": y offset is elevation and blur is twice the elevation.
  96. shadow_values.emplace_back(Vector2d(0, elevation),
  97. kBlurCorrection * elevation * 2,
  98. SkColorSetA(color, 0x3d));
  99. // "Ambient shadow": no offset and blur matches the elevation.
  100. shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation,
  101. SkColorSetA(color, 0x1f));
  102. // To see what this looks like for elevation 24, try this CSS:
  103. // box-shadow: 0 24px 48px rgba(0, 0, 0, .24),
  104. // 0 0 24px rgba(0, 0, 0, .12);
  105. return shadow_values;
  106. }
  107. #if BUILDFLAG(IS_CHROMEOS_ASH)
  108. // static
  109. ShadowValues ShadowValue::MakeChromeOSSystemUIShadowValues(int elevation,
  110. SkColor color) {
  111. ShadowValues shadow_values;
  112. // To match the CSS notion of blur (spread outside the bounding box) to the
  113. // Skia notion of blur (spread outside and inside the bounding box), we have
  114. // to double the designer-provided blur values.
  115. const int kBlurCorrection = 2;
  116. // "Key shadow": y offset is elevation and blur value is equal to the
  117. // elevation.
  118. shadow_values.emplace_back(Vector2d(0, elevation),
  119. kBlurCorrection * elevation,
  120. SkColorSetA(color, 0x3d));
  121. // "Ambient shadow": no offset and blur matches the elevation.
  122. shadow_values.emplace_back(Vector2d(), kBlurCorrection * elevation,
  123. SkColorSetA(color, 0x1a));
  124. // To see what this looks like for elevation 24, try this CSS:
  125. // box-shadow: 0 24px 24px rgba(0, 0, 0, .24),
  126. // 0 0 24px rgba(0, 0, 0, .10);
  127. return shadow_values;
  128. }
  129. #endif
  130. } // namespace gfx