xref: /aosp_15_r20/external/skia/tools/viewer/AndroidShadowsSlide.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 
2 /*
3  * Copyright 2016 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkColorFilter.h"
10 #include "include/core/SkPath.h"
11 #include "include/core/SkPoint3.h"
12 #include "include/core/SkRRect.h"
13 #include "include/pathops/SkPathOps.h"
14 #include "include/utils/SkCamera.h"
15 #include "include/utils/SkShadowUtils.h"
16 #include "src/base/SkUTF.h"
17 #include "src/core/SkBlurMask.h"
18 #include "tools/ToolUtils.h"
19 #include "tools/timer/TimeUtils.h"
20 #include "tools/viewer/Slide.h"
21 
22 ////////////////////////////////////////////////////////////////////////////
23 
24 class ShadowsSlide : public Slide {
25     SkPath    fRectPath;
26     SkPath    fRRPath;
27     SkPath    fCirclePath;
28     SkPath    fFunkyRRPath;
29     SkPath    fCubicPath;
30     SkPath    fStarPath;
31     SkPath    fSquareRRectPath;
32     SkPath    fWideRectPath;
33     SkPath    fWideOvalPath;
34     SkPath    fNotchPath;
35     SkPath    fTabPath;
36 
37     SkPoint3  fLightPos;
38     SkScalar  fZDelta = 0;
39     SkScalar  fAnimTranslate = 0;
40     SkScalar  fAnimAngle = 0;
41     SkScalar  fAnimAlpha = 1;
42 
43     bool      fShowAmbient = true;
44     bool      fShowSpot = true;
45     bool      fUseAlt = false;
46     bool      fUseBlur = true;
47     bool      fShowObject = true;
48     bool      fIgnoreShadowAlpha = false;
49     bool      fDoAlphaAnimation = false;
50 
51 public:
ShadowsSlide()52     ShadowsSlide() { fName = "AndroidShadows"; }
53 
load(SkScalar w,SkScalar h)54     void load(SkScalar w, SkScalar h) override {
55         fCirclePath.addCircle(0, 0, 50);
56         fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
57         fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
58         fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100),
59                                   40 * SK_Scalar1, 20 * SK_Scalar1,
60                                   SkPathDirection::kCW);
61         fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
62                            20 * SK_Scalar1, 100 * SK_Scalar1,
63                            0 * SK_Scalar1, 0 * SK_Scalar1);
64         fStarPath.moveTo(0.0f, -50.0f);
65         fStarPath.lineTo(14.43f, -25.0f);
66         fStarPath.lineTo(43.30f, -25.0f);
67         fStarPath.lineTo(28.86f, 0.0f);
68         fStarPath.lineTo(43.30f, 25.0f);
69         fStarPath.lineTo(14.43f, 25.0f);
70         fStarPath.lineTo(0.0f, 50.0f);
71         fStarPath.lineTo(-14.43f, 25.0f);
72         fStarPath.lineTo(-43.30f, 25.0f);
73         fStarPath.lineTo(-28.86f, 0.0f);
74         fStarPath.lineTo(-43.30f, -25.0f);
75         fStarPath.lineTo(-14.43f, -25.0f);
76         fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100),
77                                                       10, 10));
78         fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70));
79         fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70));
80 
81         fNotchPath.moveTo(0, 80);
82         fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), -90, -90, false);
83         fNotchPath.lineTo(-75, 100);
84         fNotchPath.lineTo(-75, -100);
85         fNotchPath.lineTo(75, -100);
86         fNotchPath.lineTo(75, 100);
87         fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, -90, false);
88 
89         fTabPath.moveTo(-75, -100);
90         fTabPath.lineTo(75, -100);
91         fTabPath.lineTo(75, 100);
92         fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, 90, false);
93         fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 90, 90, false);
94         fTabPath.lineTo(-75, 100);
95 
96         fLightPos = SkPoint3::Make(350, 0, 600);
97     }
98 
onChar(SkUnichar uni)99     bool onChar(SkUnichar uni) override {
100             bool handled = false;
101             switch (uni) {
102                 case 'W':
103                     fShowAmbient = !fShowAmbient;
104                     handled = true;
105                     break;
106                 case 'S':
107                     fShowSpot = !fShowSpot;
108                     handled = true;
109                     break;
110                 case 'T':
111                     fUseAlt = !fUseAlt;
112                     handled = true;
113                     break;
114                 case 'B':
115                     fUseBlur = !fUseBlur;
116                     handled = true;
117                     break;
118                 case 'O':
119                     fShowObject = !fShowObject;
120                     handled = true;
121                     break;
122                 case 'N':
123                     fDoAlphaAnimation = !fDoAlphaAnimation;
124                     if (!fDoAlphaAnimation) {
125                         fAnimAlpha = 1;
126                     }
127                     handled = true;
128                     break;
129                 case '>':
130                     fZDelta += 0.5f;
131                     handled = true;
132                     break;
133                 case '<':
134                     fZDelta -= 0.5f;
135                     handled = true;
136                     break;
137                 case '?':
138                     fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
139                     handled = true;
140                     break;
141                 default:
142                     break;
143             }
144             if (handled) {
145                 return true;
146             }
147             return false;
148     }
149 
150 
animate(double nanos)151     bool animate(double nanos) override {
152         fAnimTranslate = TimeUtils::PingPong(1e-9 * nanos, 30, 0, 125, -125);
153         fAnimAngle = TimeUtils::PingPong(1e-9 * nanos, 15, 0, 0, 20);
154         if (fDoAlphaAnimation) {
155             fAnimAlpha = TimeUtils::PingPong(1e-9 * nanos, 5, 0, 1, 0);
156         }
157         return true;
158     }
159 
draw(SkCanvas * canvas)160     void draw(SkCanvas* canvas) override {
161         canvas->drawColor(0xFFDDDDDD);
162 
163         const SkScalar kLightWidth = 800;
164         const SkScalar kAmbientAlpha = 0.039f;
165         const SkScalar kSpotAlpha = 0.19f;
166 
167         SkPaint paint;
168         paint.setAntiAlias(true);
169 
170         SkPoint3 lightPos = fLightPos;
171         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0);
172 
173         paint.setColor(SK_ColorWHITE);
174         canvas->translate(200, 90);
175         zPlaneParams.fZ = std::max(1.0f, 2 + fZDelta);
176         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
177                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
178 
179         paint.setColor(SK_ColorRED);
180         canvas->translate(250, 0);
181         zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta);
182         this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
183                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
184 
185         paint.setColor(SK_ColorBLUE);
186         canvas->translate(-250, 110);
187         zPlaneParams.fZ = std::max(1.0f, 12 + fZDelta);
188         this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
189                                lightPos, kLightWidth, fAnimAlpha*0.5f);
190 
191         paint.setColor(SK_ColorGREEN);
192         canvas->translate(250, 0);
193         zPlaneParams.fZ = std::max(1.0f, 64 + fZDelta);
194         this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
195                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
196 
197         paint.setColor(SK_ColorYELLOW);
198         canvas->translate(-250, 110);
199         zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta);
200         this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
201                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
202 
203         paint.setColor(SK_ColorCYAN);
204         canvas->translate(250, 0);
205         zPlaneParams.fZ = std::max(1.0f, 16 + fZDelta);
206         this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha,
207                                lightPos, kLightWidth, fAnimAlpha*kSpotAlpha);
208 
209         paint.setColor(SK_ColorWHITE);
210         canvas->translate(250, -180);
211         zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta);
212         this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint,
213                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
214 
215         paint.setColor(SK_ColorWHITE);
216         canvas->translate(150, 0);
217         zPlaneParams.fZ = std::max(1.0f, 2 + fZDelta);
218         this->drawShadowedPath(canvas, fNotchPath, zPlaneParams, paint,
219                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
220 
221         paint.setColor(SK_ColorWHITE);
222         canvas->translate(200, 0);
223         zPlaneParams.fZ = std::max(1.0f, 16 + fZDelta);
224         this->drawShadowedPath(canvas, fTabPath, zPlaneParams, paint,
225                                kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha);
226 
227         // circular reveal
228         SkPath tmpPath;
229         SkPath tmpClipPath;
230         tmpClipPath.addCircle(fAnimTranslate, 0, 60);
231         Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath);
232 
233         paint.setColor(SK_ColorMAGENTA);
234         canvas->translate(-725, 240);
235         zPlaneParams.fZ = std::max(1.0f, 32 + fZDelta);
236         this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
237                                lightPos, kLightWidth, .5f);
238 
239         // path ops bug
240         SkPath tmpClipPathBug;
241         tmpClipPathBug.addCircle(88.0344925f, 0, 60);
242         Op(fSquareRRectPath, tmpClipPathBug, kIntersect_SkPathOp, &tmpPath);
243 
244         canvas->translate(250, 0);
245         zPlaneParams.fZ = std::max(1.0f, 32 + fZDelta);
246         this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f,
247                                lightPos, kLightWidth, .5f);
248 
249         // perspective paths
250         SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2,
251                                       fWideRectPath.getBounds().height()/2);
252         SkPoint translate = SkPoint::Make(100, 450);
253         paint.setColor(SK_ColorWHITE);
254         Sk3DView view;
255         view.save();
256         view.rotateX(fAnimAngle);
257         SkMatrix persp;
258         view.getMatrix(&persp);
259         persp.preTranslate(-pivot.fX, -pivot.fY);
260         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
261         canvas->setMatrix(persp);
262         SkScalar radians = SkDegreesToRadians(fAnimAngle);
263         zPlaneParams = SkPoint3::Make(0,
264                                       SkScalarSin(radians),
265                                       std::max(1.0f, 16 + fZDelta) - SkScalarSin(radians)*pivot.fY);
266         this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f,
267                                lightPos, kLightWidth, .5f);
268 
269         pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2,
270                               fWideOvalPath.getBounds().height() / 2);
271         translate = SkPoint::Make(100, 600);
272         view.restore();
273         view.save();
274         view.rotateY(fAnimAngle);
275         view.getMatrix(&persp);
276         persp.preTranslate(-pivot.fX, -pivot.fY);
277         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
278         canvas->setMatrix(persp);
279         zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
280                                       0,
281                                       std::max(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX);
282         this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f,
283                                lightPos, kLightWidth, .5f);
284 
285         pivot = SkPoint::Make(fStarPath.getBounds().width() / 2,
286                               fStarPath.getBounds().height() / 2);
287         translate = SkPoint::Make(700, 250);
288         view.restore();
289         view.rotateY(fAnimAngle);
290         view.getMatrix(&persp);
291         persp.preTranslate(-pivot.fX, -pivot.fY);
292         persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY);
293         canvas->setMatrix(persp);
294         zPlaneParams = SkPoint3::Make(-SkScalarSin(radians),
295                                       0,
296                                       std::max(1.0f, 8 + fZDelta) + SkScalarSin(radians)*pivot.fX);
297         this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, .1f,
298                                lightPos, kLightWidth, .5f);
299     }
300 
301 private:
drawShadowedPath(SkCanvas * canvas,const SkPath & path,const SkPoint3 & zPlaneParams,const SkPaint & paint,SkScalar ambientAlpha,const SkPoint3 & lightPos,SkScalar lightWidth,SkScalar spotAlpha)302     void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
303                           const SkPoint3& zPlaneParams,
304                           const SkPaint& paint, SkScalar ambientAlpha,
305                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
306         if (fIgnoreShadowAlpha) {
307             ambientAlpha = 1;
308             spotAlpha = 1;
309         }
310         if (!fShowAmbient) {
311             ambientAlpha = 0;
312         }
313         if (!fShowSpot) {
314             spotAlpha = 0;
315         }
316         uint32_t flags = 0;
317         if (fUseAlt) {
318             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
319         }
320         if (fUseBlur) {
321             flags |= SkShadowFlags::kConcaveBlurOnly_ShadowFlag;
322         }
323 
324         SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0);
325         SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0);
326         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth,
327                                   ambientColor, spotColor, flags);
328 
329         if (fShowObject) {
330             canvas->drawPath(path, paint);
331         } else {
332             SkPaint strokePaint;
333 
334             strokePaint.setColor(paint.getColor());
335             strokePaint.setStyle(SkPaint::kStroke_Style);
336 
337             canvas->drawPath(path, strokePaint);
338         }
339     }
340 };
341 
342 //////////////////////////////////////////////////////////////////////////////
343 
344 DEF_SLIDE( return new ShadowsSlide(); )
345