1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2017 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPathBuilder.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint3.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTDArray.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/utils/SkShadowUtils.h"
23*c8dee2aaSAndroid Build Coastguard Worker
24*c8dee2aaSAndroid Build Coastguard Worker #include <initializer_list>
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
27*c8dee2aaSAndroid Build Coastguard Worker
draw_shadow(SkCanvas * canvas,const SkPath & path,SkScalar height,SkColor color,SkPoint3 lightPos,SkScalar lightR,bool isAmbient,uint32_t flags)28*c8dee2aaSAndroid Build Coastguard Worker void draw_shadow(SkCanvas* canvas, const SkPath& path, SkScalar height, SkColor color,
29*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 lightPos, SkScalar lightR, bool isAmbient, uint32_t flags) {
30*c8dee2aaSAndroid Build Coastguard Worker SkScalar ambientAlpha = isAmbient ? .5f : 0.f;
31*c8dee2aaSAndroid Build Coastguard Worker SkScalar spotAlpha = isAmbient ? 0.f : .5f;
32*c8dee2aaSAndroid Build Coastguard Worker SkColor ambientColor = SkColorSetARGB(ambientAlpha*SkColorGetA(color), SkColorGetR(color),
33*c8dee2aaSAndroid Build Coastguard Worker SkColorGetG(color), SkColorGetB(color));
34*c8dee2aaSAndroid Build Coastguard Worker SkColor spotColor = SkColorSetARGB(spotAlpha*SkColorGetA(color), SkColorGetR(color),
35*c8dee2aaSAndroid Build Coastguard Worker SkColorGetG(color), SkColorGetB(color));
36*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, height}, lightPos, lightR,
37*c8dee2aaSAndroid Build Coastguard Worker ambientColor, spotColor, flags);
38*c8dee2aaSAndroid Build Coastguard Worker }
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kW = 800;
41*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kH = 960;
42*c8dee2aaSAndroid Build Coastguard Worker
43*c8dee2aaSAndroid Build Coastguard Worker enum ShadowMode {
44*c8dee2aaSAndroid Build Coastguard Worker kDebugColorNoOccluders,
45*c8dee2aaSAndroid Build Coastguard Worker kDebugColorOccluders,
46*c8dee2aaSAndroid Build Coastguard Worker kGrayscale
47*c8dee2aaSAndroid Build Coastguard Worker };
48*c8dee2aaSAndroid Build Coastguard Worker
draw_paths(SkCanvas * canvas,ShadowMode mode)49*c8dee2aaSAndroid Build Coastguard Worker void draw_paths(SkCanvas* canvas, ShadowMode mode) {
50*c8dee2aaSAndroid Build Coastguard Worker TArray<SkPath> paths;
51*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPath::RRect(SkRect::MakeWH(50, 50), 10, 10.00002f));
52*c8dee2aaSAndroid Build Coastguard Worker SkRRect oddRRect;
53*c8dee2aaSAndroid Build Coastguard Worker oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
54*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPath::RRect(oddRRect));
55*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPath::Rect(SkRect::MakeWH(50, 50)));
56*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPath::Circle(25, 25, 25));
57*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPathBuilder().cubicTo(100, 50, 20, 100, 0, 0).detach());
58*c8dee2aaSAndroid Build Coastguard Worker paths.push_back(SkPath::Oval(SkRect::MakeWH(20, 60)));
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker // star
61*c8dee2aaSAndroid Build Coastguard Worker TArray<SkPath> concavePaths;
62*c8dee2aaSAndroid Build Coastguard Worker concavePaths.push_back().moveTo(0.0f, -33.3333f);
63*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(9.62f, -16.6667f);
64*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(28.867f, -16.6667f);
65*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(19.24f, 0.0f);
66*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(28.867f, 16.6667f);
67*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(9.62f, 16.6667f);
68*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(0.0f, 33.3333f);
69*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(-9.62f, 16.6667f);
70*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(-28.867f, 16.6667f);
71*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(-19.24f, 0.0f);
72*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(-28.867f, -16.6667f);
73*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().lineTo(-9.62f, -16.6667f);
74*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().close();
75*c8dee2aaSAndroid Build Coastguard Worker
76*c8dee2aaSAndroid Build Coastguard Worker // dumbbell
77*c8dee2aaSAndroid Build Coastguard Worker concavePaths.push_back().moveTo(50, 0);
78*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
79*c8dee2aaSAndroid Build Coastguard Worker concavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kPad = 15.f;
82*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kLightR = 100.f;
83*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kHeight = 50.f;
84*c8dee2aaSAndroid Build Coastguard Worker
85*c8dee2aaSAndroid Build Coastguard Worker // transform light position relative to canvas to handle tiling
86*c8dee2aaSAndroid Build Coastguard Worker SkPoint lightXY = canvas->getTotalMatrix().mapXY(250, 400);
87*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 lightPos = { lightXY.fX, lightXY.fY, 500 };
88*c8dee2aaSAndroid Build Coastguard Worker
89*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(3 * kPad, 3 * kPad);
90*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
91*c8dee2aaSAndroid Build Coastguard Worker SkScalar x = 0;
92*c8dee2aaSAndroid Build Coastguard Worker SkScalar dy = 0;
93*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<SkMatrix> matrices;
94*c8dee2aaSAndroid Build Coastguard Worker matrices.append()->reset();
95*c8dee2aaSAndroid Build Coastguard Worker matrices.append()->setRotate(33.f, 25.f, 25.f).postScale(1.2f, 0.8f, 25.f, 25.f);
96*c8dee2aaSAndroid Build Coastguard Worker for (auto& m : matrices) {
97*c8dee2aaSAndroid Build Coastguard Worker for (int flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
98*c8dee2aaSAndroid Build Coastguard Worker int pathCounter = 0;
99*c8dee2aaSAndroid Build Coastguard Worker for (const auto& path : paths) {
100*c8dee2aaSAndroid Build Coastguard Worker SkRect postMBounds = path.getBounds();
101*c8dee2aaSAndroid Build Coastguard Worker m.mapRect(&postMBounds);
102*c8dee2aaSAndroid Build Coastguard Worker SkScalar w = postMBounds.width() + kHeight;
103*c8dee2aaSAndroid Build Coastguard Worker SkScalar dx = w + kPad;
104*c8dee2aaSAndroid Build Coastguard Worker if (x + dx > kW - 3 * kPad) {
105*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
106*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, dy);
107*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
108*c8dee2aaSAndroid Build Coastguard Worker x = 0;
109*c8dee2aaSAndroid Build Coastguard Worker dy = 0;
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
113*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(m);
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker // flip a couple of paths to test 180° rotation
116*c8dee2aaSAndroid Build Coastguard Worker if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) {
117*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
118*c8dee2aaSAndroid Build Coastguard Worker canvas->rotate(180, 25, 25);
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker if (kDebugColorNoOccluders == mode || kDebugColorOccluders == mode) {
121*c8dee2aaSAndroid Build Coastguard Worker draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR,
122*c8dee2aaSAndroid Build Coastguard Worker true, flags);
123*c8dee2aaSAndroid Build Coastguard Worker draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR,
124*c8dee2aaSAndroid Build Coastguard Worker false, flags);
125*c8dee2aaSAndroid Build Coastguard Worker } else if (kGrayscale == mode) {
126*c8dee2aaSAndroid Build Coastguard Worker SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0);
127*c8dee2aaSAndroid Build Coastguard Worker SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0);
128*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, path, SkPoint3{0, 0, kHeight}, lightPos,
129*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor, flags);
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker
132*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
133*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
134*c8dee2aaSAndroid Build Coastguard Worker if (kDebugColorNoOccluders == mode) {
135*c8dee2aaSAndroid Build Coastguard Worker // Draw the path outline in green on top of the ambient and spot shadows.
136*c8dee2aaSAndroid Build Coastguard Worker if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
137*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorCYAN);
138*c8dee2aaSAndroid Build Coastguard Worker } else {
139*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
140*c8dee2aaSAndroid Build Coastguard Worker }
141*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
142*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(0);
143*c8dee2aaSAndroid Build Coastguard Worker } else {
144*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(kDebugColorOccluders == mode ? SK_ColorLTGRAY : SK_ColorWHITE);
145*c8dee2aaSAndroid Build Coastguard Worker if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) {
146*c8dee2aaSAndroid Build Coastguard Worker paint.setAlphaf(0.5f);
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
149*c8dee2aaSAndroid Build Coastguard Worker }
150*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
151*c8dee2aaSAndroid Build Coastguard Worker if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) {
152*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(dx, 0);
157*c8dee2aaSAndroid Build Coastguard Worker x += dx;
158*c8dee2aaSAndroid Build Coastguard Worker dy = std::max(dy, postMBounds.height() + kPad + kHeight);
159*c8dee2aaSAndroid Build Coastguard Worker ++pathCounter;
160*c8dee2aaSAndroid Build Coastguard Worker }
161*c8dee2aaSAndroid Build Coastguard Worker }
162*c8dee2aaSAndroid Build Coastguard Worker }
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker // concave paths
165*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
166*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(kPad, dy);
167*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
168*c8dee2aaSAndroid Build Coastguard Worker x = kPad;
169*c8dee2aaSAndroid Build Coastguard Worker dy = 0;
170*c8dee2aaSAndroid Build Coastguard Worker for (auto& m : matrices) {
171*c8dee2aaSAndroid Build Coastguard Worker // for the concave paths we are not clipping, so transparent and opaque are the same
172*c8dee2aaSAndroid Build Coastguard Worker for (const auto& path : concavePaths) {
173*c8dee2aaSAndroid Build Coastguard Worker SkRect postMBounds = path.getBounds();
174*c8dee2aaSAndroid Build Coastguard Worker m.mapRect(&postMBounds);
175*c8dee2aaSAndroid Build Coastguard Worker SkScalar w = postMBounds.width() + kHeight;
176*c8dee2aaSAndroid Build Coastguard Worker SkScalar dx = w + kPad;
177*c8dee2aaSAndroid Build Coastguard Worker
178*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
179*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(m);
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker if (kDebugColorNoOccluders == mode || kDebugColorOccluders == mode) {
182*c8dee2aaSAndroid Build Coastguard Worker draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR,
183*c8dee2aaSAndroid Build Coastguard Worker true, kNone_ShadowFlag);
184*c8dee2aaSAndroid Build Coastguard Worker draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR,
185*c8dee2aaSAndroid Build Coastguard Worker false, kNone_ShadowFlag);
186*c8dee2aaSAndroid Build Coastguard Worker } else if (kGrayscale == mode) {
187*c8dee2aaSAndroid Build Coastguard Worker SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0);
188*c8dee2aaSAndroid Build Coastguard Worker SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0);
189*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, kHeight }, lightPos,
190*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor, kNone_ShadowFlag);
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
194*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
195*c8dee2aaSAndroid Build Coastguard Worker if (kDebugColorNoOccluders == mode) {
196*c8dee2aaSAndroid Build Coastguard Worker // Draw the path outline in green on top of the ambient and spot shadows.
197*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
198*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kStroke_Style);
199*c8dee2aaSAndroid Build Coastguard Worker paint.setStrokeWidth(0);
200*c8dee2aaSAndroid Build Coastguard Worker } else {
201*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(kDebugColorOccluders == mode ? SK_ColorLTGRAY : SK_ColorWHITE);
202*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
203*c8dee2aaSAndroid Build Coastguard Worker }
204*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(path, paint);
205*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(dx, 0);
208*c8dee2aaSAndroid Build Coastguard Worker x += dx;
209*c8dee2aaSAndroid Build Coastguard Worker dy = std::max(dy, postMBounds.height() + kPad + kHeight);
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker }
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker // Show where the light is in x,y as a circle (specified in device space).
214*c8dee2aaSAndroid Build Coastguard Worker SkMatrix invCanvasM = canvas->getTotalMatrix();
215*c8dee2aaSAndroid Build Coastguard Worker if (invCanvasM.invert(&invCanvasM)) {
216*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
217*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(invCanvasM);
218*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
219*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLACK);
220*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
221*c8dee2aaSAndroid Build Coastguard Worker canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
222*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker }
225*c8dee2aaSAndroid Build Coastguard Worker
DEF_SIMPLE_GM(shadow_utils,canvas,kW,kH)226*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
227*c8dee2aaSAndroid Build Coastguard Worker draw_paths(canvas, kDebugColorNoOccluders);
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker
DEF_SIMPLE_GM(shadow_utils_occl,canvas,kW,kH)230*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(shadow_utils_occl, canvas, kW, kH) {
231*c8dee2aaSAndroid Build Coastguard Worker draw_paths(canvas, kDebugColorOccluders);
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
DEF_SIMPLE_GM(shadow_utils_gray,canvas,kW,kH)234*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(shadow_utils_gray, canvas, kW, kH) {
235*c8dee2aaSAndroid Build Coastguard Worker draw_paths(canvas, kGrayscale);
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker
238*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
239*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorFilterPriv.h"
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(shadow_utils_gaussian_colorfilter, canvas, 512, 256) {
242*c8dee2aaSAndroid Build Coastguard Worker const SkRect r = SkRect::MakeWH(256, 256);
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { 0, 0xFF000000 };
245*c8dee2aaSAndroid Build Coastguard Worker auto sh = SkGradientShader::MakeRadial({r.centerX(), r.centerY()}, r.width(),
246*c8dee2aaSAndroid Build Coastguard Worker colors, nullptr, std::size(colors),
247*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp);
248*c8dee2aaSAndroid Build Coastguard Worker
249*c8dee2aaSAndroid Build Coastguard Worker SkPaint redPaint;
250*c8dee2aaSAndroid Build Coastguard Worker redPaint.setColor(SK_ColorRED);
251*c8dee2aaSAndroid Build Coastguard Worker
252*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
253*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(sh);
254*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, redPaint);
255*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
256*c8dee2aaSAndroid Build Coastguard Worker
257*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(256, 0);
258*c8dee2aaSAndroid Build Coastguard Worker paint.setColorFilter(SkColorFilterPriv::MakeGaussian());
259*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, redPaint);
260*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker
263*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(shadow_utils_directional, canvas, 256, 384) {
264*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kLightR = 1.f;
265*c8dee2aaSAndroid Build Coastguard Worker static constexpr SkScalar kHeight = 12.f;
266*c8dee2aaSAndroid Build Coastguard Worker
267*c8dee2aaSAndroid Build Coastguard Worker SkPath rrect(SkPath::RRect(SkRect::MakeLTRB(-25, -25, 25, 25), 10, 10));
268*c8dee2aaSAndroid Build Coastguard Worker SkPoint3 lightPos = { -45, -45, 77.9422863406f };
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker SkColor ambientColor = SkColorSetARGB(0.02f * 255, 0, 0, 0);
271*c8dee2aaSAndroid Build Coastguard Worker SkColor spotColor = SkColorSetARGB(0.35f * 255, 0, 0, 0);
272*c8dee2aaSAndroid Build Coastguard Worker
273*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
274*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
275*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorWHITE);
276*c8dee2aaSAndroid Build Coastguard Worker paint.setStyle(SkPaint::kFill_Style);
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker // translation
279*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
280*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(35, 35);
281*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
282*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
283*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor,
284*c8dee2aaSAndroid Build Coastguard Worker kDirectionalLight_ShadowFlag);
285*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(rrect, paint);
286*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(80, 0);
287*c8dee2aaSAndroid Build Coastguard Worker }
288*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker // rotation
291*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
292*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
293*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(35 + 80*i, 105);
294*c8dee2aaSAndroid Build Coastguard Worker canvas->rotate(20.f*(i + 1));
295*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
296*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor,
297*c8dee2aaSAndroid Build Coastguard Worker kDirectionalLight_ShadowFlag);
298*c8dee2aaSAndroid Build Coastguard Worker
299*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(rrect, paint);
300*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
301*c8dee2aaSAndroid Build Coastguard Worker }
302*c8dee2aaSAndroid Build Coastguard Worker
303*c8dee2aaSAndroid Build Coastguard Worker // scale
304*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
305*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
306*c8dee2aaSAndroid Build Coastguard Worker SkScalar scaleFactor = std::pow(2.0, -i);
307*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(35 + 80*i, 185);
308*c8dee2aaSAndroid Build Coastguard Worker canvas->scale(scaleFactor, scaleFactor);
309*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
310*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor,
311*c8dee2aaSAndroid Build Coastguard Worker kDirectionalLight_ShadowFlag);
312*c8dee2aaSAndroid Build Coastguard Worker
313*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(rrect, paint);
314*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker // perspective
318*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; ++i) {
319*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
320*c8dee2aaSAndroid Build Coastguard Worker SkMatrix mat;
321*c8dee2aaSAndroid Build Coastguard Worker mat.reset();
322*c8dee2aaSAndroid Build Coastguard Worker mat[SkMatrix::kMPersp1] = 0.005f;
323*c8dee2aaSAndroid Build Coastguard Worker mat[SkMatrix::kMPersp2] = 1.005f;
324*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(35 + 80*i, 265);
325*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(mat);
326*c8dee2aaSAndroid Build Coastguard Worker SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
327*c8dee2aaSAndroid Build Coastguard Worker kLightR, ambientColor, spotColor,
328*c8dee2aaSAndroid Build Coastguard Worker kDirectionalLight_ShadowFlag);
329*c8dee2aaSAndroid Build Coastguard Worker
330*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPath(rrect, paint);
331*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
332*c8dee2aaSAndroid Build Coastguard Worker }
333*c8dee2aaSAndroid Build Coastguard Worker
334*c8dee2aaSAndroid Build Coastguard Worker }
335