• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2017 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 "SampleCode.h"
9 #include "SkAnimTimer.h"
10 #include "SkBlurMask.h"
11 #include "SkBlurMaskFilter.h"
12 #include "SkColorFilter.h"
13 #include "SkCamera.h"
14 #include "SkCanvas.h"
15 #include "SkPath.h"
16 #include "SkPathOps.h"
17 #include "SkPoint3.h"
18 #include "SkShadowUtils.h"
19 #include "SkUtils.h"
20 #include "SkView.h"
21 #include "sk_tool_utils.h"
22 
23 ////////////////////////////////////////////////////////////////////////////
24 
25 class ShadowUtilsView : public SampleView {
26     SkTArray<SkPath> fPaths;
27     SkScalar         fZDelta;
28 
29     bool      fShowAmbient;
30     bool      fShowSpot;
31     bool      fUseAlt;
32     bool      fShowObject;
33     bool      fIgnoreShadowAlpha;
34 
35 public:
ShadowUtilsView()36     ShadowUtilsView()
37         : fZDelta(0)
38         , fShowAmbient(true)
39         , fShowSpot(true)
40         , fUseAlt(false)
41         , fShowObject(false)
42         , fIgnoreShadowAlpha(false) {}
43 
44 protected:
onOnceBeforeDraw()45     void onOnceBeforeDraw() override {
46         fPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
47         SkRRect oddRRect;
48         oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
49         fPaths.push_back().addRRect(oddRRect);
50         fPaths.push_back().addRect(SkRect::MakeWH(50, 50));
51         fPaths.push_back().addCircle(25, 25, 25);
52         fPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0);
53         fPaths.push_back().addOval(SkRect::MakeWH(20, 60));
54     }
55 
56     // overrides from SkEventSink
onQuery(SkEvent * evt)57     bool onQuery(SkEvent* evt) override {
58         if (SampleCode::TitleQ(*evt)) {
59             SampleCode::TitleR(evt, "ShadowUtils");
60             return true;
61         }
62 
63         SkUnichar uni;
64         if (SampleCode::CharQ(*evt, &uni)) {
65             bool handled = false;
66             switch (uni) {
67                 case 'W':
68                     fShowAmbient = !fShowAmbient;
69                     handled = true;
70                     break;
71                 case 'S':
72                     fShowSpot = !fShowSpot;
73                     handled = true;
74                     break;
75                 case 'T':
76                     fUseAlt = !fUseAlt;
77                     handled = true;
78                     break;
79                 case 'O':
80                     fShowObject = !fShowObject;
81                     handled = true;
82                     break;
83                 case '>':
84                     fZDelta += 0.5f;
85                     handled = true;
86                     break;
87                 case '<':
88                     fZDelta -= 0.5f;
89                     handled = true;
90                     break;
91                 case '?':
92                     fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
93                     handled = true;
94                     break;
95                 default:
96                     break;
97             }
98             if (handled) {
99                 this->inval(nullptr);
100                 return true;
101             }
102         }
103         return this->INHERITED::onQuery(evt);
104     }
105 
drawBG(SkCanvas * canvas)106     void drawBG(SkCanvas* canvas) {
107         canvas->drawColor(0xFFFFFFFF);
108     }
109 
drawShadowedPath(SkCanvas * canvas,const SkPath & path,const SkPoint3 & zPlaneParams,const SkPaint & paint,SkScalar ambientAlpha,const SkPoint3 & lightPos,SkScalar lightWidth,SkScalar spotAlpha,uint32_t flags)110     void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
111                           const SkPoint3& zPlaneParams,
112                           const SkPaint& paint, SkScalar ambientAlpha,
113                           const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha,
114                           uint32_t flags) {
115         if (fIgnoreShadowAlpha) {
116             ambientAlpha = 255;
117             spotAlpha = 255;
118         }
119         if (!fShowAmbient) {
120             ambientAlpha = 0;
121         }
122         if (!fShowSpot) {
123             spotAlpha = 0;
124         }
125         if (fUseAlt) {
126             flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
127         }
128         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
129                                   lightPos, lightWidth,
130                                   ambientAlpha, 0, SK_ColorRED, flags);
131         SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
132                                   lightPos, lightWidth,
133                                   0, spotAlpha, SK_ColorBLUE, flags);
134 
135         if (fShowObject) {
136             canvas->drawPath(path, paint);
137         } else {
138             SkPaint strokePaint;
139 
140             strokePaint.setColor(paint.getColor());
141             strokePaint.setStyle(SkPaint::kStroke_Style);
142 
143             canvas->drawPath(path, strokePaint);
144         }
145     }
146 
onDrawContent(SkCanvas * canvas)147     void onDrawContent(SkCanvas* canvas) override {
148         this->drawBG(canvas);
149 
150         static constexpr int kW = 800;
151         static constexpr SkScalar kPad = 15.f;
152         static constexpr SkScalar kLightR = 100.f;
153         static constexpr SkScalar kHeight = 50.f;
154         static constexpr SkScalar kAmbientAlpha = 0.5f;
155         static constexpr SkScalar kSpotAlpha = 0.5f;
156         static constexpr SkPoint3 lightPos = { 250, 400, 500 };
157 
158         canvas->translate(3 * kPad, 3 * kPad);
159         canvas->save();
160         SkScalar x = 0;
161         SkScalar dy = 0;
162         SkTDArray<SkMatrix> matrices;
163         matrices.push()->reset();
164         SkMatrix* m = matrices.push();
165         m->setRotate(33.f, 25.f, 25.f);
166         m->postScale(1.2f, 0.8f, 25.f, 25.f);
167         SkPaint paint;
168         paint.setColor(SK_ColorGREEN);
169         paint.setAntiAlias(true);
170         SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta));
171         for (auto& m : matrices) {
172             for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
173                 for (const auto& path : fPaths) {
174                     SkRect postMBounds = path.getBounds();
175                     m.mapRect(&postMBounds);
176                     SkScalar w = postMBounds.width() + kHeight;
177                     SkScalar dx = w + kPad;
178                     if (x + dx > kW - 3 * kPad) {
179                         canvas->restore();
180                         canvas->translate(0, dy);
181                         canvas->save();
182                         x = 0;
183                         dy = 0;
184                     }
185 
186                     canvas->save();
187                     canvas->concat(m);
188                     drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos,
189                                      kLightR, kSpotAlpha, flags);
190                     canvas->restore();
191 
192                     canvas->translate(dx, 0);
193                     x += dx;
194                     dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
195                 }
196             }
197         }
198         // Show where the light is in x,y as a circle (specified in device space).
199         SkMatrix invCanvasM = canvas->getTotalMatrix();
200         if (invCanvasM.invert(&invCanvasM)) {
201             canvas->save();
202             canvas->concat(invCanvasM);
203             SkPaint paint;
204             paint.setColor(SK_ColorBLACK);
205             paint.setAntiAlias(true);
206             canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
207             canvas->restore();
208         }
209     }
210 
211 private:
212     typedef SampleView INHERITED;
213 };
214 
215 //////////////////////////////////////////////////////////////////////////////
216 
MyFactory()217 static SkView* MyFactory() { return new ShadowUtilsView; }
218 static SkViewRegister reg(MyFactory);
219