blob: 49298775480747d522d2d812d126ca848f887904 [file] [log] [blame]
Jim Van Verthe7705782017-05-04 14:00:59 -04001
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"
Jim Van Verthe7705782017-05-04 14:00:59 -040015#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
25class ShadowUtilsView : public SampleView {
Jim Van Verth22526362018-02-28 14:51:19 -050026 SkTArray<SkPath> fConvexPaths;
27 SkTArray<SkPath> fConcavePaths;
Jim Van Verthe7705782017-05-04 14:00:59 -040028 SkScalar fZDelta;
29
30 bool fShowAmbient;
31 bool fShowSpot;
32 bool fUseAlt;
33 bool fShowObject;
34 bool fIgnoreShadowAlpha;
35
36public:
37 ShadowUtilsView()
38 : fZDelta(0)
39 , fShowAmbient(true)
40 , fShowSpot(true)
41 , fUseAlt(false)
42 , fShowObject(false)
43 , fIgnoreShadowAlpha(false) {}
44
45protected:
46 void onOnceBeforeDraw() override {
Jim Van Verth22526362018-02-28 14:51:19 -050047 fConvexPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
Jim Van Verthe7705782017-05-04 14:00:59 -040048 SkRRect oddRRect;
49 oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
Jim Van Verth22526362018-02-28 14:51:19 -050050 fConvexPaths.push_back().addRRect(oddRRect);
51 fConvexPaths.push_back().addRect(SkRect::MakeWH(50, 50));
52 fConvexPaths.push_back().addCircle(25, 25, 25);
53 fConvexPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0);
54 fConvexPaths.push_back().addOval(SkRect::MakeWH(20, 60));
55
56 // star
57 fConcavePaths.push_back().moveTo(0.0f, -33.3333f);
58 fConcavePaths.back().lineTo(9.62f, -16.6667f);
59 fConcavePaths.back().lineTo(28.867f, -16.6667f);
60 fConcavePaths.back().lineTo(19.24f, 0.0f);
61 fConcavePaths.back().lineTo(28.867f, 16.6667f);
62 fConcavePaths.back().lineTo(9.62f, 16.6667f);
63 fConcavePaths.back().lineTo(0.0f, 33.3333f);
64 fConcavePaths.back().lineTo(-9.62f, 16.6667f);
65 fConcavePaths.back().lineTo(-28.867f, 16.6667f);
66 fConcavePaths.back().lineTo(-19.24f, 0.0f);
67 fConcavePaths.back().lineTo(-28.867f, -16.6667f);
68 fConcavePaths.back().lineTo(-9.62f, -16.6667f);
69 fConcavePaths.back().close();
70
71 // dumbbell
72 fConcavePaths.push_back().moveTo(50, 0);
73 fConcavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
74 fConcavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
Jim Van Verthe7705782017-05-04 14:00:59 -040075 }
76
77 // overrides from SkEventSink
78 bool onQuery(SkEvent* evt) override {
79 if (SampleCode::TitleQ(*evt)) {
80 SampleCode::TitleR(evt, "ShadowUtils");
81 return true;
82 }
83
84 SkUnichar uni;
85 if (SampleCode::CharQ(*evt, &uni)) {
86 bool handled = false;
87 switch (uni) {
88 case 'W':
89 fShowAmbient = !fShowAmbient;
90 handled = true;
91 break;
92 case 'S':
93 fShowSpot = !fShowSpot;
94 handled = true;
95 break;
96 case 'T':
97 fUseAlt = !fUseAlt;
98 handled = true;
99 break;
100 case 'O':
101 fShowObject = !fShowObject;
102 handled = true;
103 break;
104 case '>':
105 fZDelta += 0.5f;
106 handled = true;
107 break;
108 case '<':
109 fZDelta -= 0.5f;
110 handled = true;
111 break;
112 case '?':
113 fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
114 handled = true;
115 break;
116 default:
117 break;
118 }
119 if (handled) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400120 return true;
121 }
122 }
123 return this->INHERITED::onQuery(evt);
124 }
125
126 void drawBG(SkCanvas* canvas) {
Jim Van Verth8d1e0ac2017-05-05 15:53:23 -0400127 canvas->drawColor(0xFFFFFFFF);
Jim Van Verthe7705782017-05-04 14:00:59 -0400128 }
129
130 void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
Jim Van Verthe308a122017-05-08 14:19:30 -0400131 const SkPoint3& zPlaneParams,
Jim Van Verthe7705782017-05-04 14:00:59 -0400132 const SkPaint& paint, SkScalar ambientAlpha,
133 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha,
134 uint32_t flags) {
135 if (fIgnoreShadowAlpha) {
136 ambientAlpha = 255;
137 spotAlpha = 255;
138 }
139 if (!fShowAmbient) {
140 ambientAlpha = 0;
141 }
142 if (!fShowSpot) {
143 spotAlpha = 0;
144 }
145 if (fUseAlt) {
146 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
147 }
Jim Van Vertha5566842018-02-22 10:58:34 -0500148
149 SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 255, 0, 0);
150 SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 255);
Jim Van Verth37c5a962017-05-10 14:13:24 -0400151 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
152 lightPos, lightWidth,
Jim Van Vertha5566842018-02-22 10:58:34 -0500153 ambientColor, spotColor, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400154
155 if (fShowObject) {
156 canvas->drawPath(path, paint);
157 } else {
158 SkPaint strokePaint;
159
160 strokePaint.setColor(paint.getColor());
161 strokePaint.setStyle(SkPaint::kStroke_Style);
162
163 canvas->drawPath(path, strokePaint);
164 }
165 }
166
167 void onDrawContent(SkCanvas* canvas) override {
168 this->drawBG(canvas);
169
170 static constexpr int kW = 800;
171 static constexpr SkScalar kPad = 15.f;
Jim Van Verthe7705782017-05-04 14:00:59 -0400172 static constexpr SkScalar kLightR = 100.f;
173 static constexpr SkScalar kHeight = 50.f;
174 static constexpr SkScalar kAmbientAlpha = 0.5f;
175 static constexpr SkScalar kSpotAlpha = 0.5f;
Jim Van Verth8793e382017-05-22 15:52:21 -0400176 static constexpr SkPoint3 lightPos = { 250, 400, 500 };
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400177
Jim Van Verthe7705782017-05-04 14:00:59 -0400178 canvas->translate(3 * kPad, 3 * kPad);
179 canvas->save();
180 SkScalar x = 0;
181 SkScalar dy = 0;
182 SkTDArray<SkMatrix> matrices;
183 matrices.push()->reset();
184 SkMatrix* m = matrices.push();
185 m->setRotate(33.f, 25.f, 25.f);
186 m->postScale(1.2f, 0.8f, 25.f, 25.f);
187 SkPaint paint;
188 paint.setColor(SK_ColorGREEN);
189 paint.setAntiAlias(true);
Jim Van Verthe308a122017-05-08 14:19:30 -0400190 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta));
Jim Van Verth22526362018-02-28 14:51:19 -0500191
192 // convex paths
Jim Van Verthe7705782017-05-04 14:00:59 -0400193 for (auto& m : matrices) {
194 for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
Jim Van Verth22526362018-02-28 14:51:19 -0500195 for (const auto& path : fConvexPaths) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400196 SkRect postMBounds = path.getBounds();
197 m.mapRect(&postMBounds);
198 SkScalar w = postMBounds.width() + kHeight;
199 SkScalar dx = w + kPad;
200 if (x + dx > kW - 3 * kPad) {
201 canvas->restore();
202 canvas->translate(0, dy);
203 canvas->save();
204 x = 0;
205 dy = 0;
206 }
207
208 canvas->save();
209 canvas->concat(m);
Jim Van Verth22526362018-02-28 14:51:19 -0500210 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha,
211 lightPos, kLightR, kSpotAlpha, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400212 canvas->restore();
213
214 canvas->translate(dx, 0);
215 x += dx;
216 dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
217 }
218 }
219 }
Jim Van Verth22526362018-02-28 14:51:19 -0500220
221 // concave paths
222 canvas->restore();
223 canvas->translate(kPad, dy);
224 canvas->save();
225 x = kPad;
226 dy = 0;
227 for (auto& m : matrices) {
228 for (const auto& path : fConcavePaths) {
229 SkRect postMBounds = path.getBounds();
230 m.mapRect(&postMBounds);
231 SkScalar w = postMBounds.width();
232 SkScalar dx = w + kPad;
233
234 canvas->save();
235 canvas->concat(m);
236 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos,
237 kLightR, kSpotAlpha, kNone_ShadowFlag);
238 canvas->restore();
239
240 canvas->translate(dx, 0);
241 x += dx;
242 dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
243 }
244 }
245
Jim Van Verthe7705782017-05-04 14:00:59 -0400246 // Show where the light is in x,y as a circle (specified in device space).
247 SkMatrix invCanvasM = canvas->getTotalMatrix();
248 if (invCanvasM.invert(&invCanvasM)) {
249 canvas->save();
250 canvas->concat(invCanvasM);
251 SkPaint paint;
252 paint.setColor(SK_ColorBLACK);
253 paint.setAntiAlias(true);
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400254 canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
Jim Van Verthe7705782017-05-04 14:00:59 -0400255 canvas->restore();
256 }
257 }
258
259private:
260 typedef SampleView INHERITED;
261};
262
263//////////////////////////////////////////////////////////////////////////////
264
265static SkView* MyFactory() { return new ShadowUtilsView; }
266static SkViewRegister reg(MyFactory);