blob: 5fffd63a5114a3b1c73f91457b0f63897a9ea6e2 [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"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#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"
Jim Van Verthe7705782017-05-04 14:00:59 -040019
20////////////////////////////////////////////////////////////////////////////
21
Ben Wagnerb2c4ea62018-08-08 11:36:17 -040022class ShadowUtilsView : public Sample {
Jim Van Verth22526362018-02-28 14:51:19 -050023 SkTArray<SkPath> fConvexPaths;
24 SkTArray<SkPath> fConcavePaths;
Jim Van Verthe7705782017-05-04 14:00:59 -040025 SkScalar fZDelta;
26
27 bool fShowAmbient;
28 bool fShowSpot;
29 bool fUseAlt;
30 bool fShowObject;
31 bool fIgnoreShadowAlpha;
32
33public:
34 ShadowUtilsView()
35 : fZDelta(0)
36 , fShowAmbient(true)
37 , fShowSpot(true)
38 , fUseAlt(false)
39 , fShowObject(false)
40 , fIgnoreShadowAlpha(false) {}
41
42protected:
43 void onOnceBeforeDraw() override {
Mike Reed4241f5e2019-09-14 19:13:23 +000044 fConvexPaths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
Jim Van Verthe7705782017-05-04 14:00:59 -040045 SkRRect oddRRect;
46 oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
Jim Van Verth22526362018-02-28 14:51:19 -050047 fConvexPaths.push_back().addRRect(oddRRect);
48 fConvexPaths.push_back().addRect(SkRect::MakeWH(50, 50));
49 fConvexPaths.push_back().addCircle(25, 25, 25);
50 fConvexPaths.push_back().cubicTo(100, 50, 20, 100, 0, 0);
51 fConvexPaths.push_back().addOval(SkRect::MakeWH(20, 60));
52
53 // star
54 fConcavePaths.push_back().moveTo(0.0f, -33.3333f);
55 fConcavePaths.back().lineTo(9.62f, -16.6667f);
56 fConcavePaths.back().lineTo(28.867f, -16.6667f);
57 fConcavePaths.back().lineTo(19.24f, 0.0f);
58 fConcavePaths.back().lineTo(28.867f, 16.6667f);
59 fConcavePaths.back().lineTo(9.62f, 16.6667f);
60 fConcavePaths.back().lineTo(0.0f, 33.3333f);
61 fConcavePaths.back().lineTo(-9.62f, 16.6667f);
62 fConcavePaths.back().lineTo(-28.867f, 16.6667f);
63 fConcavePaths.back().lineTo(-19.24f, 0.0f);
64 fConcavePaths.back().lineTo(-28.867f, -16.6667f);
65 fConcavePaths.back().lineTo(-9.62f, -16.6667f);
66 fConcavePaths.back().close();
67
68 // dumbbell
69 fConcavePaths.push_back().moveTo(50, 0);
70 fConcavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
71 fConcavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
Jim Van Verthe7705782017-05-04 14:00:59 -040072 }
73
Hal Canary8a027312019-07-03 10:55:44 -040074 SkString name() override { return SkString("ShadowUtils"); }
Jim Van Verthe7705782017-05-04 14:00:59 -040075
Hal Canary6cc65e12019-07-03 15:53:04 -040076 bool onChar(SkUnichar uni) override {
Jim Van Verthe7705782017-05-04 14:00:59 -040077 bool handled = false;
78 switch (uni) {
79 case 'W':
80 fShowAmbient = !fShowAmbient;
81 handled = true;
82 break;
83 case 'S':
84 fShowSpot = !fShowSpot;
85 handled = true;
86 break;
87 case 'T':
88 fUseAlt = !fUseAlt;
89 handled = true;
90 break;
91 case 'O':
92 fShowObject = !fShowObject;
93 handled = true;
94 break;
95 case '>':
96 fZDelta += 0.5f;
97 handled = true;
98 break;
99 case '<':
100 fZDelta -= 0.5f;
101 handled = true;
102 break;
103 case '?':
104 fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
105 handled = true;
106 break;
107 default:
108 break;
109 }
110 if (handled) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400111 return true;
112 }
Hal Canary6cc65e12019-07-03 15:53:04 -0400113 return false;
Jim Van Verthe7705782017-05-04 14:00:59 -0400114 }
115
116 void drawBG(SkCanvas* canvas) {
Jim Van Verth8d1e0ac2017-05-05 15:53:23 -0400117 canvas->drawColor(0xFFFFFFFF);
Jim Van Verthe7705782017-05-04 14:00:59 -0400118 }
119
120 void drawShadowedPath(SkCanvas* canvas, const SkPath& path,
Jim Van Verthe308a122017-05-08 14:19:30 -0400121 const SkPoint3& zPlaneParams,
Jim Van Verthe7705782017-05-04 14:00:59 -0400122 const SkPaint& paint, SkScalar ambientAlpha,
123 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha,
124 uint32_t flags) {
125 if (fIgnoreShadowAlpha) {
126 ambientAlpha = 255;
127 spotAlpha = 255;
128 }
129 if (!fShowAmbient) {
130 ambientAlpha = 0;
131 }
132 if (!fShowSpot) {
133 spotAlpha = 0;
134 }
135 if (fUseAlt) {
136 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag;
137 }
Jim Van Vertha5566842018-02-22 10:58:34 -0500138
139 SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 255, 0, 0);
140 SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 255);
Jim Van Verth37c5a962017-05-10 14:13:24 -0400141 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams,
142 lightPos, lightWidth,
Jim Van Vertha5566842018-02-22 10:58:34 -0500143 ambientColor, spotColor, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400144
145 if (fShowObject) {
146 canvas->drawPath(path, paint);
147 } else {
148 SkPaint strokePaint;
149
150 strokePaint.setColor(paint.getColor());
151 strokePaint.setStyle(SkPaint::kStroke_Style);
152
153 canvas->drawPath(path, strokePaint);
154 }
155 }
156
157 void onDrawContent(SkCanvas* canvas) override {
158 this->drawBG(canvas);
159
160 static constexpr int kW = 800;
161 static constexpr SkScalar kPad = 15.f;
Jim Van Verthe7705782017-05-04 14:00:59 -0400162 static constexpr SkScalar kLightR = 100.f;
163 static constexpr SkScalar kHeight = 50.f;
164 static constexpr SkScalar kAmbientAlpha = 0.5f;
165 static constexpr SkScalar kSpotAlpha = 0.5f;
Jim Van Verth8793e382017-05-22 15:52:21 -0400166 static constexpr SkPoint3 lightPos = { 250, 400, 500 };
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400167
Jim Van Verthe7705782017-05-04 14:00:59 -0400168 canvas->translate(3 * kPad, 3 * kPad);
169 canvas->save();
170 SkScalar x = 0;
171 SkScalar dy = 0;
172 SkTDArray<SkMatrix> matrices;
173 matrices.push()->reset();
174 SkMatrix* m = matrices.push();
175 m->setRotate(33.f, 25.f, 25.f);
176 m->postScale(1.2f, 0.8f, 25.f, 25.f);
177 SkPaint paint;
178 paint.setColor(SK_ColorGREEN);
179 paint.setAntiAlias(true);
Brian Osman788b9162020-02-07 10:36:46 -0500180 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, std::max(1.0f, kHeight + fZDelta));
Jim Van Verth22526362018-02-28 14:51:19 -0500181
182 // convex paths
Jim Van Verthe7705782017-05-04 14:00:59 -0400183 for (auto& m : matrices) {
184 for (auto flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) {
Jim Van Verth22526362018-02-28 14:51:19 -0500185 for (const auto& path : fConvexPaths) {
Jim Van Verthe7705782017-05-04 14:00:59 -0400186 SkRect postMBounds = path.getBounds();
187 m.mapRect(&postMBounds);
188 SkScalar w = postMBounds.width() + kHeight;
189 SkScalar dx = w + kPad;
190 if (x + dx > kW - 3 * kPad) {
191 canvas->restore();
192 canvas->translate(0, dy);
193 canvas->save();
194 x = 0;
195 dy = 0;
196 }
197
198 canvas->save();
199 canvas->concat(m);
Jim Van Verth22526362018-02-28 14:51:19 -0500200 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha,
201 lightPos, kLightR, kSpotAlpha, flags);
Jim Van Verthe7705782017-05-04 14:00:59 -0400202 canvas->restore();
203
204 canvas->translate(dx, 0);
205 x += dx;
Brian Osman788b9162020-02-07 10:36:46 -0500206 dy = std::max(dy, postMBounds.height() + kPad + kHeight);
Jim Van Verthe7705782017-05-04 14:00:59 -0400207 }
208 }
209 }
Jim Van Verth22526362018-02-28 14:51:19 -0500210
211 // concave paths
212 canvas->restore();
213 canvas->translate(kPad, dy);
214 canvas->save();
215 x = kPad;
216 dy = 0;
217 for (auto& m : matrices) {
218 for (const auto& path : fConcavePaths) {
219 SkRect postMBounds = path.getBounds();
220 m.mapRect(&postMBounds);
221 SkScalar w = postMBounds.width();
222 SkScalar dx = w + kPad;
223
224 canvas->save();
225 canvas->concat(m);
226 this->drawShadowedPath(canvas, path, zPlaneParams, paint, kAmbientAlpha, lightPos,
227 kLightR, kSpotAlpha, kNone_ShadowFlag);
228 canvas->restore();
229
230 canvas->translate(dx, 0);
231 x += dx;
Brian Osman788b9162020-02-07 10:36:46 -0500232 dy = std::max(dy, postMBounds.height() + kPad + kHeight);
Jim Van Verth22526362018-02-28 14:51:19 -0500233 }
234 }
235
Jim Van Verthe7705782017-05-04 14:00:59 -0400236 // Show where the light is in x,y as a circle (specified in device space).
237 SkMatrix invCanvasM = canvas->getTotalMatrix();
238 if (invCanvasM.invert(&invCanvasM)) {
239 canvas->save();
240 canvas->concat(invCanvasM);
241 SkPaint paint;
242 paint.setColor(SK_ColorBLACK);
243 paint.setAntiAlias(true);
Jim Van Verth9392f569c2017-05-16 15:01:43 -0400244 canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
Jim Van Verthe7705782017-05-04 14:00:59 -0400245 canvas->restore();
246 }
247 }
248
249private:
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400250 typedef Sample INHERITED;
Jim Van Verthe7705782017-05-04 14:00:59 -0400251};
252
253//////////////////////////////////////////////////////////////////////////////
254
Ben Wagnerb2c4ea62018-08-08 11:36:17 -0400255DEF_SAMPLE( return new ShadowUtilsView(); )