Flutter Engine
The Flutter Engine
shadowutils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm/gm.h"
17#include "include/core/SkRect.h"
23
24#include <initializer_list>
25
26using namespace skia_private;
27
29 SkPoint3 lightPos, SkScalar lightR, bool isAmbient, uint32_t flags) {
30 SkScalar ambientAlpha = isAmbient ? .5f : 0.f;
31 SkScalar spotAlpha = isAmbient ? 0.f : .5f;
32 SkColor ambientColor = SkColorSetARGB(ambientAlpha*SkColorGetA(color), SkColorGetR(color),
36 SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, height}, lightPos, lightR,
37 ambientColor, spotColor, flags);
38}
39
40static constexpr int kW = 800;
41static constexpr int kH = 960;
42
47};
48
50 TArray<SkPath> paths;
51 paths.push_back(SkPath::RRect(SkRect::MakeWH(50, 50), 10, 10.00002f));
52 SkRRect oddRRect;
53 oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16);
54 paths.push_back(SkPath::RRect(oddRRect));
56 paths.push_back(SkPath::Circle(25, 25, 25));
57 paths.push_back(SkPathBuilder().cubicTo(100, 50, 20, 100, 0, 0).detach());
59
60 // star
61 TArray<SkPath> concavePaths;
62 concavePaths.push_back().moveTo(0.0f, -33.3333f);
63 concavePaths.back().lineTo(9.62f, -16.6667f);
64 concavePaths.back().lineTo(28.867f, -16.6667f);
65 concavePaths.back().lineTo(19.24f, 0.0f);
66 concavePaths.back().lineTo(28.867f, 16.6667f);
67 concavePaths.back().lineTo(9.62f, 16.6667f);
68 concavePaths.back().lineTo(0.0f, 33.3333f);
69 concavePaths.back().lineTo(-9.62f, 16.6667f);
70 concavePaths.back().lineTo(-28.867f, 16.6667f);
71 concavePaths.back().lineTo(-19.24f, 0.0f);
72 concavePaths.back().lineTo(-28.867f, -16.6667f);
73 concavePaths.back().lineTo(-9.62f, -16.6667f);
74 concavePaths.back().close();
75
76 // dumbbell
77 concavePaths.push_back().moveTo(50, 0);
78 concavePaths.back().cubicTo(100, 25, 60, 50, 50, 0);
79 concavePaths.back().cubicTo(0, -25, 40, -50, 50, 0);
80
81 static constexpr SkScalar kPad = 15.f;
82 static constexpr SkScalar kLightR = 100.f;
83 static constexpr SkScalar kHeight = 50.f;
84
85 // transform light position relative to canvas to handle tiling
86 SkPoint lightXY = canvas->getTotalMatrix().mapXY(250, 400);
87 SkPoint3 lightPos = { lightXY.fX, lightXY.fY, 500 };
88
89 canvas->translate(3 * kPad, 3 * kPad);
90 canvas->save();
91 SkScalar x = 0;
92 SkScalar dy = 0;
93 SkTDArray<SkMatrix> matrices;
94 matrices.append()->reset();
95 matrices.append()->setRotate(33.f, 25.f, 25.f).postScale(1.2f, 0.8f, 25.f, 25.f);
96 for (auto& m : matrices) {
98 int pathCounter = 0;
99 for (const auto& path : paths) {
100 SkRect postMBounds = path.getBounds();
101 m.mapRect(&postMBounds);
102 SkScalar w = postMBounds.width() + kHeight;
103 SkScalar dx = w + kPad;
104 if (x + dx > kW - 3 * kPad) {
105 canvas->restore();
106 canvas->translate(0, dy);
107 canvas->save();
108 x = 0;
109 dy = 0;
110 }
111
112 canvas->save();
113 canvas->concat(m);
114
115 // flip a couple of paths to test 180° rotation
116 if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) {
117 canvas->save();
118 canvas->rotate(180, 25, 25);
119 }
121 draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR,
122 true, flags);
123 draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR,
124 false, flags);
125 } else if (kGrayscale == mode) {
126 SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0);
127 SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0);
128 SkShadowUtils::DrawShadow(canvas, path, SkPoint3{0, 0, kHeight}, lightPos,
129 kLightR, ambientColor, spotColor, flags);
130 }
131
133 paint.setAntiAlias(true);
135 // Draw the path outline in green on top of the ambient and spot shadows.
137 paint.setColor(SK_ColorCYAN);
138 } else {
139 paint.setColor(SK_ColorGREEN);
140 }
142 paint.setStrokeWidth(0);
143 } else {
146 paint.setAlphaf(0.5f);
147 }
148 paint.setStyle(SkPaint::kFill_Style);
149 }
150 canvas->drawPath(path, paint);
151 if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) {
152 canvas->restore();
153 }
154 canvas->restore();
155
156 canvas->translate(dx, 0);
157 x += dx;
158 dy = std::max(dy, postMBounds.height() + kPad + kHeight);
159 ++pathCounter;
160 }
161 }
162 }
163
164 // concave paths
165 canvas->restore();
166 canvas->translate(kPad, dy);
167 canvas->save();
168 x = kPad;
169 dy = 0;
170 for (auto& m : matrices) {
171 // for the concave paths we are not clipping, so transparent and opaque are the same
172 for (const auto& path : concavePaths) {
173 SkRect postMBounds = path.getBounds();
174 m.mapRect(&postMBounds);
175 SkScalar w = postMBounds.width() + kHeight;
176 SkScalar dx = w + kPad;
177
178 canvas->save();
179 canvas->concat(m);
180
182 draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR,
183 true, kNone_ShadowFlag);
184 draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR,
185 false, kNone_ShadowFlag);
186 } else if (kGrayscale == mode) {
187 SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0);
188 SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0);
189 SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, kHeight }, lightPos,
190 kLightR, ambientColor, spotColor, kNone_ShadowFlag);
191 }
192
194 paint.setAntiAlias(true);
196 // Draw the path outline in green on top of the ambient and spot shadows.
197 paint.setColor(SK_ColorGREEN);
199 paint.setStrokeWidth(0);
200 } else {
202 paint.setStyle(SkPaint::kFill_Style);
203 }
204 canvas->drawPath(path, paint);
205 canvas->restore();
206
207 canvas->translate(dx, 0);
208 x += dx;
209 dy = std::max(dy, postMBounds.height() + kPad + kHeight);
210 }
211 }
212
213 // Show where the light is in x,y as a circle (specified in device space).
214 SkMatrix invCanvasM = canvas->getTotalMatrix();
215 if (invCanvasM.invert(&invCanvasM)) {
216 canvas->save();
217 canvas->concat(invCanvasM);
219 paint.setColor(SK_ColorBLACK);
220 paint.setAntiAlias(true);
221 canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint);
222 canvas->restore();
223 }
224}
225
226DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
228}
229
230DEF_SIMPLE_GM(shadow_utils_occl, canvas, kW, kH) {
232}
233
234DEF_SIMPLE_GM(shadow_utils_gray, canvas, kW, kH) {
235 draw_paths(canvas, kGrayscale);
236}
237
240
241DEF_SIMPLE_GM(shadow_utils_gaussian_colorfilter, canvas, 512, 256) {
242 const SkRect r = SkRect::MakeWH(256, 256);
243
244 const SkColor colors[] = { 0, 0xFF000000 };
245 auto sh = SkGradientShader::MakeRadial({r.centerX(), r.centerY()}, r.width(),
246 colors, nullptr, std::size(colors),
248
249 SkPaint redPaint;
250 redPaint.setColor(SK_ColorRED);
251
253 paint.setShader(sh);
254 canvas->drawRect(r, redPaint);
255 canvas->drawRect(r, paint);
256
257 canvas->translate(256, 0);
258 paint.setColorFilter(SkColorFilterPriv::MakeGaussian());
259 canvas->drawRect(r, redPaint);
260 canvas->drawRect(r, paint);
261}
262
263DEF_SIMPLE_GM(shadow_utils_directional, canvas, 256, 384) {
264 static constexpr SkScalar kLightR = 1.f;
265 static constexpr SkScalar kHeight = 12.f;
266
267 SkPath rrect(SkPath::RRect(SkRect::MakeLTRB(-25, -25, 25, 25), 10, 10));
268 SkPoint3 lightPos = { -45, -45, 77.9422863406f };
269
270 SkColor ambientColor = SkColorSetARGB(0.02f * 255, 0, 0, 0);
271 SkColor spotColor = SkColorSetARGB(0.35f * 255, 0, 0, 0);
272
274 paint.setAntiAlias(true);
275 paint.setColor(SK_ColorWHITE);
276 paint.setStyle(SkPaint::kFill_Style);
277
278 // translation
279 canvas->save();
280 canvas->translate(35, 35);
281 for (int i = 0; i < 3; ++i) {
282 SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
283 kLightR, ambientColor, spotColor,
285 canvas->drawPath(rrect, paint);
286 canvas->translate(80, 0);
287 }
288 canvas->restore();
289
290 // rotation
291 for (int i = 0; i < 3; ++i) {
292 canvas->save();
293 canvas->translate(35 + 80*i, 105);
294 canvas->rotate(20.f*(i + 1));
295 SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
296 kLightR, ambientColor, spotColor,
298
299 canvas->drawPath(rrect, paint);
300 canvas->restore();
301 }
302
303 // scale
304 for (int i = 0; i < 3; ++i) {
305 canvas->save();
306 SkScalar scaleFactor = std::pow(2.0, -i);
307 canvas->translate(35 + 80*i, 185);
308 canvas->scale(scaleFactor, scaleFactor);
309 SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
310 kLightR, ambientColor, spotColor,
312
313 canvas->drawPath(rrect, paint);
314 canvas->restore();
315 }
316
317 // perspective
318 for (int i = 0; i < 3; ++i) {
319 canvas->save();
320 SkMatrix mat;
321 mat.reset();
322 mat[SkMatrix::kMPersp1] = 0.005f;
323 mat[SkMatrix::kMPersp2] = 1.005f;
324 canvas->translate(35 + 80*i, 265);
325 canvas->concat(mat);
326 SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos,
327 kLightR, ambientColor, spotColor,
329
330 canvas->drawPath(rrect, paint);
331 canvas->restore();
332 }
333
334}
constexpr SkColor SK_ColorLTGRAY
Definition: SkColor.h:118
#define SkColorGetR(color)
Definition: SkColor.h:65
#define SkColorGetG(color)
Definition: SkColor.h:69
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
#define SkColorGetA(color)
Definition: SkColor.h:61
#define SkColorGetB(color)
Definition: SkColor.h:73
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
@ kDirectionalLight_ShadowFlag
Definition: SkShadowUtils.h:31
@ kTransparentOccluder_ShadowFlag
Definition: SkShadowUtils.h:27
@ kNone_ShadowFlag
Definition: SkShadowUtils.h:24
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
constexpr int kPad
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void rotate(SkScalar degrees)
Definition: SkCanvas.cpp:1300
SkMatrix getTotalMatrix() const
Definition: SkCanvas.cpp:1629
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
Definition: SkCanvas.cpp:2707
static sk_sp< SkColorFilter > MakeGaussian()
static sk_sp< SkShader > MakeRadial(const SkPoint &center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static constexpr int kMPersp1
input y perspective factor
Definition: SkMatrix.h:360
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
void mapXY(SkScalar x, SkScalar y, SkPoint *result) const
Definition: SkMatrix.cpp:777
static constexpr int kMPersp2
perspective bias
Definition: SkMatrix.h:361
SkMatrix & reset()
Definition: SkMatrix.cpp:49
void setColor(SkColor color)
Definition: SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
@ kFill_Style
set to fill geometry
Definition: SkPaint.h:193
Definition: SkPath.h:59
static SkPath RRect(const SkRRect &, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3602
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
Definition: SkPath.cpp:3586
SkPath & moveTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:688
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728
static SkPath Circle(SkScalar center_x, SkScalar center_y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3598
static SkPath Oval(const SkRect &, SkPathDirection=SkPathDirection::kCW)
Definition: SkPath.cpp:3590
SkPath & cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, SkScalar x3, SkScalar y3)
Definition: SkPath.cpp:799
SkPath & close()
Definition: SkPath.cpp:823
void setNinePatch(const SkRect &rect, SkScalar leftRad, SkScalar topRad, SkScalar rightRad, SkScalar bottomRad)
Definition: SkRRect.cpp:115
static void DrawShadow(SkCanvas *canvas, const SkPath &path, const SkPoint3 &zPlaneParams, const SkPoint3 &lightPos, SkScalar lightRadius, SkColor ambientColor, SkColor spotColor, uint32_t flags=SkShadowFlags::kNone_ShadowFlag)
T * append()
Definition: SkTDArray.h:191
const Paint & paint
Definition: color_source.cc:38
DlColor color
float SkScalar
Definition: extension.cpp:12
FlutterSemanticsFlag flags
static float max(float r, float g, float b)
Definition: hsl.cpp:49
double x
SkRRect rrect
Definition: SkRecords.h:232
PODArray< SkColor > colors
Definition: SkRecords.h:276
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
Definition: switches.h:228
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
sh
Definition: run_sh.py:10
SkScalar w
int32_t height
void draw_shadow(SkCanvas *canvas, const SkPath &path, SkScalar height, SkColor color, SkPoint3 lightPos, SkScalar lightR, bool isAmbient, uint32_t flags)
Definition: shadowutils.cpp:28
static constexpr int kH
Definition: shadowutils.cpp:41
DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH)
ShadowMode
Definition: shadowutils.cpp:43
@ kDebugColorOccluders
Definition: shadowutils.cpp:45
@ kGrayscale
Definition: shadowutils.cpp:46
@ kDebugColorNoOccluders
Definition: shadowutils.cpp:44
void draw_paths(SkCanvas *canvas, ShadowMode mode)
Definition: shadowutils.cpp:49
static constexpr int kW
Definition: shadowutils.cpp:40
SkScalar fX
Definition: SkPoint3.h:16
SkScalar fY
Definition: SkPoint3.h:16
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
constexpr float centerX() const
Definition: SkRect.h:776
constexpr float height() const
Definition: SkRect.h:769
constexpr float centerY() const
Definition: SkRect.h:785
constexpr float width() const
Definition: SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
constexpr size_t kHeight