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

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

Issue 2589163003: Add shadow/corner radius to notifications (toasts and in-center). (Closed)
Patch Set: . 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
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) {
sky 2017/01/05 00:39:17 Does = default; work here?
Evan Stade 2017/01/05 00:51:15 ah, that's nifty. Seems to work.
82 values = other.values;
83 ninebox_image = other.ninebox_image;
84 }
85 ShadowDetails::~ShadowDetails() {}
86
87 const ShadowDetails& ShadowDetails::Get(int elevation, int corner_radius) {
88 auto iter =
89 g_shadow_cache.Get().find(std::make_pair(elevation, corner_radius));
90 if (iter != g_shadow_cache.Get().end())
91 return iter->second;
92
93 auto insertion = g_shadow_cache.Get().insert(std::make_pair(
94 std::make_pair(elevation, corner_radius), ShadowDetails()));
95 DCHECK(insertion.second);
96 ShadowDetails* shadow = &insertion.first->second;
97 // To match the CSS notion of blur (spread outside the bounding box) to the
98 // Skia notion of blur (spread outside and inside the bounding box), we have
99 // to double the designer-provided blur values.
100 const int kBlurCorrection = 2;
101 // "Key shadow": y offset is elevation and blur is twice the elevation.
102 shadow->values.emplace_back(gfx::Vector2d(0, elevation),
103 kBlurCorrection * elevation * 2,
104 SkColorSetA(SK_ColorBLACK, 0x3d));
105 // "Ambient shadow": no offset and blur matches the elevation.
106 shadow->values.emplace_back(gfx::Vector2d(), kBlurCorrection * elevation,
107 SkColorSetA(SK_ColorBLACK, 0x1f));
108 // To see what this looks like for elevation 24, try this CSS:
109 // box-shadow: 0 24px 48px rgba(0, 0, 0, .24),
110 // 0 0 24px rgba(0, 0, 0, .12);
111 auto source = new ShadowNineboxSource(shadow->values, corner_radius);
112 shadow->ninebox_image = ImageSkia(source, source->size());
113 return *shadow;
114 }
115
116 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698