Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(608)

Side by Side Diff: ui/gfx/shadow_util.cc

Issue 2589163003: Add shadow/corner radius to notifications (toasts and in-center). (Closed)
Patch Set: sky reviews Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/shadow_util.h ('k') | ui/message_center/views/message_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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
5 #include "ui/gfx/shadow_util.h"
6
7 #include <map>
8 #include <vector>
9
10 #include "base/lazy_instance.h"
11 #include "third_party/skia/include/core/SkDrawLooper.h"
12 #include "third_party/skia/include/core/SkRRect.h"
13 #include "ui/gfx/canvas.h"
14 #include "ui/gfx/geometry/insets.h"
15 #include "ui/gfx/image/canvas_image_source.h"
16 #include "ui/gfx/shadow_value.h"
17 #include "ui/gfx/skia_util.h"
18
19 namespace gfx {
20 namespace {
21
22 // Creates an image with the given shadows painted around a round rect with
23 // the given corner radius. The image will be just large enough to paint the
24 // shadows appropriately with a 1px square region reserved for "content".
25 class ShadowNineboxSource : public CanvasImageSource {
26 public:
27 ShadowNineboxSource(const std::vector<ShadowValue>& shadows,
28 float corner_radius)
29 : CanvasImageSource(CalculateSize(shadows, corner_radius), false),
30 shadows_(shadows),
31 corner_radius_(corner_radius) {
32 DCHECK(!shadows.empty());
33 }
34 ~ShadowNineboxSource() override {}
35
36 // CanvasImageSource overrides:
37 void Draw(Canvas* canvas) override {
38 SkPaint paint;
39 paint.setLooper(CreateShadowDrawLooperCorrectBlur(shadows_));
40 Insets insets = -ShadowValue::GetMargin(shadows_);
41 gfx::Rect bounds(size());
42 bounds.Inset(insets);
43 SkRRect r_rect = SkRRect::MakeRectXY(gfx::RectToSkRect(bounds),
44 corner_radius_, corner_radius_);
45
46 // Clip out the center so it's not painted with the shadow.
47 canvas->sk_canvas()->clipRRect(r_rect, SkClipOp::kDifference, true);
48 // Clipping alone is not enough --- due to anti aliasing there will still be
49 // some of the fill color in the rounded corners. We must make the fill
50 // color transparent.
51 paint.setColor(SK_ColorTRANSPARENT);
52 canvas->sk_canvas()->drawRRect(r_rect, paint);
53 }
54
55 private:
56 static Size CalculateSize(const std::vector<ShadowValue>& shadows,
57 float corner_radius) {
58 // The "content" area (the middle tile in the 3x3 grid) is a single pixel.
59 gfx::Rect bounds(0, 0, 1, 1);
60 // We need enough space to render the full range of blur.
61 bounds.Inset(-ShadowValue::GetBlurRegion(shadows));
62 // We also need space for the full roundrect corner rounding.
63 bounds.Inset(-gfx::Insets(corner_radius));
64 return bounds.size();
65 }
66
67 const std::vector<ShadowValue> shadows_;
68
69 const float corner_radius_;
70
71 DISALLOW_COPY_AND_ASSIGN(ShadowNineboxSource);
72 };
73
74 // Map from elevation/corner radius pair to a cached shadow.
75 using ShadowDetailsMap = std::map<std::pair<int, int>, ShadowDetails>;
76 base::LazyInstance<ShadowDetailsMap> g_shadow_cache = LAZY_INSTANCE_INITIALIZER;
77
78 } // namespace
79
80 ShadowDetails::ShadowDetails() {}
81 ShadowDetails::ShadowDetails(const ShadowDetails& other) = default;
82 ShadowDetails::~ShadowDetails() {}
83
84 const ShadowDetails& ShadowDetails::Get(int elevation, int corner_radius) {
85 auto iter =
86 g_shadow_cache.Get().find(std::make_pair(elevation, corner_radius));
87 if (iter != g_shadow_cache.Get().end())
88 return iter->second;
89
90 auto insertion = g_shadow_cache.Get().insert(std::make_pair(
91 std::make_pair(elevation, corner_radius), ShadowDetails()));
92 DCHECK(insertion.second);
93 ShadowDetails* shadow = &insertion.first->second;
94 // To match the CSS notion of blur (spread outside the bounding box) to the
95 // Skia notion of blur (spread outside and inside the bounding box), we have
96 // to double the designer-provided blur values.
97 const int kBlurCorrection = 2;
98 // "Key shadow": y offset is elevation and blur is twice the elevation.
99 shadow->values.emplace_back(gfx::Vector2d(0, elevation),
100 kBlurCorrection * elevation * 2,
101 SkColorSetA(SK_ColorBLACK, 0x3d));
102 // "Ambient shadow": no offset and blur matches the elevation.
103 shadow->values.emplace_back(gfx::Vector2d(), kBlurCorrection * elevation,
104 SkColorSetA(SK_ColorBLACK, 0x1f));
105 // To see what this looks like for elevation 24, try this CSS:
106 // box-shadow: 0 24px 48px rgba(0, 0, 0, .24),
107 // 0 0 24px rgba(0, 0, 0, .12);
108 auto source = new ShadowNineboxSource(shadow->values, corner_radius);
109 shadow->ninebox_image = ImageSkia(source, source->size());
110 return *shadow;
111 }
112
113 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/shadow_util.h ('k') | ui/message_center/views/message_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698