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