blob: 36a2a7d3568a68c541915f8f9f2ff4933d27c920 [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 */
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#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/AnimTimer.h"
Jim Van Verthe7705782017-05-04 14:00:59 -040021
22////////////////////////////////////////////////////////////////////////////
23
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040024class ShadowUtilsView : public Sample {
Jim Van Verth22526362018-02-28 14:51:19 -050025 SkTArray<SkPath> fConvexPaths;
26 SkTArray<SkPath> fConcavePaths;
Jim Van Verthe7705782017-05-04 14:00:59 -040027 SkScalar fZDelta;
28
29 bool fShowAmbient;
30 bool fShowSpot;
31 bool fUseAlt;
32 bool fShowObject;
33 bool fIgnoreShadowAlpha;
34
35public:
36 ShadowUtilsView()
37 : fZDelta(0)
38 , fShowAmbient(true)
39 , fShowSpot(true)
40 , fUseAlt(false)
41 , fShowObject(false)
42 , fIgnoreShadowAlpha(false) {}
43
44protected:
45 void onOnceBeforeDraw() override {
Jim Van Verth22526362018-02-28 14:51:19 -050046 fConvexPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
Jim Van Verthe7705782017-05-04 14:00:59 -040047 SkRRect oddRRect;
48 oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
Jim Van Verth22526362018-02-28 14:51:19 -050049 fConvexPaths.push_back().addRRect(oddRRect);
50 fConvexPaths.push_back().addRect(SkRect::MakeWH(50, 50));
51 fConvexPaths.push_back().addCircle(25, 25, 25);
52 fConvexPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0);
53 fConvexPaths.push_back().addOval(SkRect::MakeWH(20, 60));
54
55 // star
56 fConcavePaths.push_back().moveTo(0.0f, -33.3333f);
57 fConcavePaths.back().lineTo(9.62f, -16.6667f);
58 fConcavePaths.back().lineTo(28.867f, -16.6667f);
59 fConcavePaths.back().lineTo(19.24f, 0.0f);
60 fConcavePaths.back().lineTo(28.867f, 16.6667f);
61 fConcavePaths.back().lineTo(9.62f, 16.6667f);
62 fConcavePaths.back().lineTo(0.0f, 33.3333f);
63 fConcavePaths.back().lineTo(-9.62f, 16.6667f);
64 fConcavePaths.back().lineTo(-28.867f, 16.6667f);
65 fConcavePaths.back().lineTo(-19.24f, 0.0f);
66 fConcavePaths.back().lineTo(-28.867f, -16.6667f);
67 fConcavePaths.back().lineTo(-9.62f, -16.6667f);
68 fConcavePaths.back().close();
69
70 // dumbbell
71 fConcavePaths.push_back().moveTo(50, 0);
72 fConcavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
73 fConcavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
Jim Van Verthe7705782017-05-04 14:00:59 -040074 }
75
Hal Canary8a027312019-07-03 10:55:44 -040076 SkString name() override { return SkString("ShadowUtils"); }
Jim Van Verthe7705782017-05-04 14:00:59 -040077
Hal Canary8a027312019-07-03 10:55:44 -040078 bool onQuery(Sample::Event* evt) override {
Jim Van Verthe7705782017-05-04 14:00:59 -040079 SkUnichar uni;
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040080 if (Sample::CharQ(*evt, &uni)) {
Jim Van Verthe7705782017-05-04 14:00:59 -040081 bool handled = false;
82 switch (uni) {
83 case 'W':
84 fShowAmbient = !fShowAmbient;
85 handled = true;
86 break;
87 case 'S':
88 fShowSpot = !fShowSpot;
89 handled = true;
90 break;
91 case 'T':
92 fUseAlt = !fUseAlt;
93 handled = true;
94 break;
95 case 'O':
96 fShowObject = !fShowObject;
97 handled = true;
98 break;
99 case '>':
100 fZDelta += 0.5f;
101 handled = true;
102 break;
103 case '<':
104 fZDelta -= 0.5f;
105 handled = true;
106 break;
107 case '?':
108 fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
109 handled = true;
110 break;
111 default:
112 break;
113 }
114 if (handled) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400115 return true;
116 }
117 }
118 return this->INHERITED::onQuery(evt);
119 }
120
121 void drawBG(SkCanvas* canvas) {
Jim Van Verth8d1e0ac2017-05-05 15:53:23 -0400122 canvas->drawColor(0xFFFFFFFF);
Jim Van Verthe7705782017-05-04 14:00:59 -0400123 }
124
125 void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
Jim Van Verthe308a122017-05-08 14:19:30 -0400126 const SkPoint3& zPlaneParams,
Jim Van Verthe7705782017-05-04 14:00:59 -0400127 const SkPaint& paint, SkScalar ambientAlpha,
128 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha,
129 uint32_t flags) {
130 if (fIgnoreShadowAlpha) {
131 ambientAlpha = 255;
132 spotAlpha = 255;
133 }
134 if (!fShowAmbient) {
135 ambientAlpha = 0;
136 }
137 if (!fShowSpot) {
138 spotAlpha = 0;
139 }
140 if (fUseAlt) {
141 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
142 }
Jim Van Vertha5566842018-02-22 10:58:34 -0500143
144 SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 255, 0, 0);
145 SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 255);
Jim Van Verth37c5a962017-05-10 14:13:24 -0400146 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
147 lightPos, lightWidth,
Jim Van Vertha5566842018-02-22 10:58:34 -0500148 ambientColor, spotColor, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400149
150 if (fShowObject) {
151 canvas->drawPath(path, paint);
152 } else {
153 SkPaint strokePaint;
154
155 strokePaint.setColor(paint.getColor());
156 strokePaint.setStyle(SkPaint::kStroke_Style);
157
158 canvas->drawPath(path, strokePaint);
159 }
160 }
161
162 void onDrawContent(SkCanvas* canvas) override {
163 this->drawBG(canvas);
164
165 static constexpr int kW = 800;
166 static constexpr SkScalar kPad = 15.f;
Jim Van Verthe7705782017-05-04 14:00:59 -0400167 static constexpr SkScalar kLightR = 100.f;
168 static constexpr SkScalar kHeight = 50.f;
169 static constexpr SkScalar kAmbientAlpha = 0.5f;
170 static constexpr SkScalar kSpotAlpha = 0.5f;
Jim Van Verth8793e382017-05-22 15:52:21 -0400171 static constexpr SkPoint3 lightPos = { 250, 400, 500 };
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400172
Jim Van Verthe7705782017-05-04 14:00:59 -0400173 canvas->translate(3 * kPad, 3 * kPad);
174 canvas->save();
175 SkScalar x = 0;
176 SkScalar dy = 0;
177 SkTDArray<SkMatrix> matrices;
178 matrices.push()->reset();
179 SkMatrix* m = matrices.push();
180 m->setRotate(33.f, 25.f, 25.f);
181 m->postScale(1.2f, 0.8f, 25.f, 25.f);
182 SkPaint paint;
183 paint.setColor(SK_ColorGREEN);
184 paint.setAntiAlias(true);
Jim Van Verthe308a122017-05-08 14:19:30 -0400185 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, SkTMax(1.0f, kHeight + fZDelta));
Jim Van Verth22526362018-02-28 14:51:19 -0500186
187 // convex paths
Jim Van Verthe7705782017-05-04 14:00:59 -0400188 for (auto& m : matrices) {
189 for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
Jim Van Verth22526362018-02-28 14:51:19 -0500190 for (const auto& path : fConvexPaths) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400191 SkRect postMBounds = path.getBounds();
192 m.mapRect(&postMBounds);
193 SkScalar w = postMBounds.width() + kHeight;
194 SkScalar dx = w + kPad;
195 if (x + dx > kW - 3 * kPad) {
196 canvas->restore();
197 canvas->translate(0, dy);
198 canvas->save();
199 x = 0;
200 dy = 0;
201 }
202
203 canvas->save();
204 canvas->concat(m);
Jim Van Verth22526362018-02-28 14:51:19 -0500205 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha,
206 lightPos, kLightR, kSpotAlpha, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400207 canvas->restore();
208
209 canvas->translate(dx, 0);
210 x += dx;
211 dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
212 }
213 }
214 }
Jim Van Verth22526362018-02-28 14:51:19 -0500215
216 // concave paths
217 canvas->restore();
218 canvas->translate(kPad, dy);
219 canvas->save();
220 x = kPad;
221 dy = 0;
222 for (auto& m : matrices) {
223 for (const auto& path : fConcavePaths) {
224 SkRect postMBounds = path.getBounds();
225 m.mapRect(&postMBounds);
226 SkScalar w = postMBounds.width();
227 SkScalar dx = w + kPad;
228
229 canvas->save();
230 canvas->concat(m);
231 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos,
232 kLightR, kSpotAlpha, kNone_ShadowFlag);
233 canvas->restore();
234
235 canvas->translate(dx, 0);
236 x += dx;
237 dy = SkTMax(dy, postMBounds.height() + kPad + kHeight);
238 }
239 }
240
Jim Van Verthe7705782017-05-04 14:00:59 -0400241 // Show where the light is in x,y as a circle (specified in device space).
242 SkMatrix invCanvasM = canvas->getTotalMatrix();
243 if (invCanvasM.invert(&invCanvasM)) {
244 canvas->save();
245 canvas->concat(invCanvasM);
246 SkPaint paint;
247 paint.setColor(SK_ColorBLACK);
248 paint.setAntiAlias(true);
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400249 canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
Jim Van Verthe7705782017-05-04 14:00:59 -0400250 canvas->restore();
251 }
252 }
253
254private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400255 typedef Sample INHERITED;
Jim Van Verthe7705782017-05-04 14:00:59 -0400256};
257
258//////////////////////////////////////////////////////////////////////////////
259
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400260DEF_SAMPLE( return new ShadowUtilsView(); )