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