blob: d9e513b5c436f5c77dc01497d7ac0565dbc1fb88 [file] [log] [blame]
jvanverthe1a3bc62016-08-12 10:40:38 -07001
2/*
3 * Copyright 2016 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 "SkBlurMask.h"
10#include "SkBlurMaskFilter.h"
11#include "SkCanvas.h"
jvanverth6c177a12016-08-17 07:59:41 -070012#include "SkGaussianEdgeShader.h"
jvanverthe1a3bc62016-08-12 10:40:38 -070013#include "SkPath.h"
14#include "SkPoint3.h"
Jim Van Verth43475ad2017-01-13 14:37:37 -050015#include "SkShadowUtils.h"
jvanverthe1a3bc62016-08-12 10:40:38 -070016#include "SkUtils.h"
17#include "SkView.h"
18#include "sk_tool_utils.h"
19
Jim Van Verth43475ad2017-01-13 14:37:37 -050020#define USE_SHADOW_UTILS
21
jvanverth6c177a12016-08-17 07:59:41 -070022////////////////////////////////////////////////////////////////////////////
23
jvanverthe1a3bc62016-08-12 10:40:38 -070024class ShadowsView : public SampleView {
25 SkPath fRectPath;
26 SkPath fRRPath;
27 SkPath fCirclePath;
28 SkPoint3 fLightPos;
29
30 bool fShowAmbient;
31 bool fShowSpot;
jvanverthd7315f912016-08-17 10:06:18 -070032 bool fUseAlt;
jvanverthe1a3bc62016-08-12 10:40:38 -070033 bool fShowObject;
Robert Phillips95304e32016-10-07 14:44:07 -040034 bool fIgnoreShadowAlpha;
jvanverthe1a3bc62016-08-12 10:40:38 -070035
36public:
37 ShadowsView()
38 : fShowAmbient(true)
39 , fShowSpot(true)
jvanverthd7315f912016-08-17 10:06:18 -070040 , fUseAlt(true)
Robert Phillips95304e32016-10-07 14:44:07 -040041 , fShowObject(true)
42 , fIgnoreShadowAlpha(false) {}
jvanverthe1a3bc62016-08-12 10:40:38 -070043
44protected:
45 void onOnceBeforeDraw() override {
46 fCirclePath.addCircle(0, 0, 50);
47 fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
48 fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
jvanverthd99858a2016-09-12 07:51:04 -070049 fLightPos = SkPoint3::Make(-700, -700, 2800);
jvanverthe1a3bc62016-08-12 10:40:38 -070050 }
51
52 // overrides from SkEventSink
53 bool onQuery(SkEvent* evt) override {
54 if (SampleCode::TitleQ(*evt)) {
55 SampleCode::TitleR(evt, "AndroidShadows");
56 return true;
57 }
58
59 SkUnichar uni;
60 if (SampleCode::CharQ(*evt, &uni)) {
61 switch (uni) {
62 case 'B':
63 fShowAmbient = !fShowAmbient;
64 break;
65 case 'S':
66 fShowSpot = !fShowSpot;
67 break;
jvanverthd7315f912016-08-17 10:06:18 -070068 case 'T':
69 fUseAlt = !fUseAlt;
70 break;
jvanverthe1a3bc62016-08-12 10:40:38 -070071 case 'O':
72 fShowObject = !fShowObject;
73 break;
74 case '>':
75 fLightPos.fZ += 10;
76 break;
77 case '<':
78 fLightPos.fZ -= 10;
79 break;
Robert Phillips95304e32016-10-07 14:44:07 -040080 case '?':
81 fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
82 break;
jvanverthe1a3bc62016-08-12 10:40:38 -070083 default:
84 break;
85 }
86 this->inval(nullptr);
87 }
88 return this->INHERITED::onQuery(evt);
89 }
90
91 void drawBG(SkCanvas* canvas) {
92 canvas->drawColor(0xFFDDDDDD);
93 }
94
95 static void GetOcclRect(const SkPath& path, SkRect* occlRect) {
96 SkRect pathRect;
97 SkRRect pathRRect;
98 if (path.isOval(&pathRect)) {
99 *occlRect = sk_tool_utils::compute_central_occluder(SkRRect::MakeOval(pathRect));
100 } else if (path.isRRect(&pathRRect)) {
101 *occlRect = sk_tool_utils::compute_central_occluder(pathRRect);
102 } else if (path.isRect(occlRect)) {
103 // the inverse transform for the spot shadow occluder doesn't always get us
104 // back to exactly the same position, so deducting a little slop
105 occlRect->inset(1, 1);
106 } else {
107 *occlRect = SkRect::MakeEmpty();
108 }
109 }
110
111 void drawAmbientShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
112 SkScalar ambientAlpha) {
113
114 if (ambientAlpha <= 0) {
115 return;
116 }
117
118 const SkScalar kHeightFactor = 1.f / 128.f;
119 const SkScalar kGeomFactor = 64;
120
121 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
122 SkScalar radius = zValue*kHeightFactor*kGeomFactor;
123
124 // occlude blur
125 SkRect occlRect;
126 GetOcclRect(path, &occlRect);
127 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
128 SkBlurMask::ConvertRadiusToSigma(radius),
129 occlRect,
130 SkBlurMaskFilter::kNone_BlurFlag);
131
132 SkPaint paint;
133 paint.setAntiAlias(true);
134 paint.setMaskFilter(std::move(mf));
Robert Phillips95304e32016-10-07 14:44:07 -0400135 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
136 ? 255
137 : (unsigned char)(ambientAlpha*umbraAlpha*255.999f), 0, 0, 0));
jvanverthe1a3bc62016-08-12 10:40:38 -0700138 canvas->drawPath(path, paint);
139
140 // draw occlusion rect
jvanverth6c177a12016-08-17 07:59:41 -0700141#if DRAW_OCCL_RECT
jvanverthe1a3bc62016-08-12 10:40:38 -0700142 SkPaint stroke;
143 stroke.setStyle(SkPaint::kStroke_Style);
144 stroke.setColor(SK_ColorBLUE);
145 canvas->drawRect(occlRect, stroke);
jvanverth6c177a12016-08-17 07:59:41 -0700146#endif
147 }
148
149 void drawAmbientShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
150 SkScalar ambientAlpha) {
151
152 if (ambientAlpha <= 0) {
153 return;
154 }
155
156 const SkScalar kHeightFactor = 1.f / 128.f;
157 const SkScalar kGeomFactor = 64;
158
159 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
160 SkScalar radius = zValue*kHeightFactor*kGeomFactor;
jvanverthd99858a2016-09-12 07:51:04 -0700161 // distance to outer of edge of geometry from original shape edge
162 SkScalar offset = radius*umbraAlpha;
jvanverth6c177a12016-08-17 07:59:41 -0700163
jvanvertha4f1af82016-08-29 07:17:47 -0700164 SkRect pathRect;
165 SkRRect pathRRect;
jvanverthd99858a2016-09-12 07:51:04 -0700166 SkScalar scaleFactors[2];
167 if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
168 return;
169 }
170 if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 64 ||
jvanvertha4f1af82016-08-29 07:17:47 -0700171 !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
172 (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
173 path.isRect(&pathRect))) {
174 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
175 return;
176 }
177
jvanverthd99858a2016-09-12 07:51:04 -0700178 // For all of these, we inset the offset rect by half the radius to get our stroke shape.
179 SkScalar strokeOutset = offset - SK_ScalarHalf*radius;
180 // Make sure we'll have a radius of at least 0.5 after xform
181 if (strokeOutset*scaleFactors[0] < 0.5f) {
182 strokeOutset = 0.5f / scaleFactors[0];
183 }
jvanverthd7315f912016-08-17 10:06:18 -0700184 if (path.isOval(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700185 pathRect.outset(strokeOutset, strokeOutset);
jvanverthd7315f912016-08-17 10:06:18 -0700186 pathRRect = SkRRect::MakeOval(pathRect);
187 } else if (path.isRect(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700188 pathRect.outset(strokeOutset, strokeOutset);
189 pathRRect = SkRRect::MakeRectXY(pathRect, strokeOutset, strokeOutset);
jvanverth6c177a12016-08-17 07:59:41 -0700190 } else {
jvanverthd99858a2016-09-12 07:51:04 -0700191 pathRRect.outset(strokeOutset, strokeOutset);
jvanverth6c177a12016-08-17 07:59:41 -0700192 }
193
jvanverthd7315f912016-08-17 10:06:18 -0700194 SkPaint paint;
195 paint.setAntiAlias(true);
jvanvertha4f1af82016-08-29 07:17:47 -0700196 paint.setStyle(SkPaint::kStroke_Style);
197 // we outset the stroke a little to cover up AA on the interior edge
jvanverthd99858a2016-09-12 07:51:04 -0700198 SkScalar pad = 0.5f;
199 paint.setStrokeWidth(radius + 2*pad);
200 // handle scale of radius and pad due to CTM
201 radius *= scaleFactors[0];
202 pad *= scaleFactors[0];
203 SkASSERT(radius < 16384);
204 SkASSERT(pad < 64);
205 // Convert radius to 14.2 fixed point and place in the R & G components.
206 // Convert pad to 6.2 fixed point and place in the B component.
207 uint16_t iRadius = (uint16_t)(radius*4.0f);
208 unsigned char alpha = (unsigned char)(ambientAlpha*255.999f);
Robert Phillips95304e32016-10-07 14:44:07 -0400209 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
210 iRadius >> 8, iRadius & 0xff,
jvanverthd99858a2016-09-12 07:51:04 -0700211 (unsigned char)(4.0f*pad)));
jvanverthd7315f912016-08-17 10:06:18 -0700212
jvanverthc20c0c02016-09-14 07:04:49 -0700213 paint.setShader(SkGaussianEdgeShader::Make());
jvanverthd7315f912016-08-17 10:06:18 -0700214 canvas->drawRRect(pathRRect, paint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700215 }
216
217 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
218 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
219 if (spotAlpha <= 0) {
220 return;
221 }
222
223 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
224 if (zRatio < 0.0f) {
225 zRatio = 0.0f;
226 } else if (zRatio > 0.95f) {
227 zRatio = 0.95f;
228 }
jvanverthd99858a2016-09-12 07:51:04 -0700229 SkScalar blurRadius = lightWidth*zRatio;
jvanverthe1a3bc62016-08-12 10:40:38 -0700230
231 // compute the transformation params
232 SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
jvanverthd99858a2016-09-12 07:51:04 -0700233 SkMatrix ctmInverse;
234 if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
235 return;
jvanverthe1a3bc62016-08-12 10:40:38 -0700236 }
jvanverthd99858a2016-09-12 07:51:04 -0700237 SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
238 ctmInverse.mapPoints(&lightPos2D, 1);
239 SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
240 zRatio*(center.fY - lightPos2D.fY));
241 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
jvanverthe1a3bc62016-08-12 10:40:38 -0700242
243 SkAutoCanvasRestore acr(canvas, true);
244
jvanverthe1a3bc62016-08-12 10:40:38 -0700245 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
jvanverthd99858a2016-09-12 07:51:04 -0700246 SkBlurMask::ConvertRadiusToSigma(blurRadius),
jvanverthe1a3bc62016-08-12 10:40:38 -0700247 SkBlurMaskFilter::kNone_BlurFlag);
248
249 SkPaint paint;
250 paint.setAntiAlias(true);
251 paint.setMaskFilter(std::move(mf));
Robert Phillips95304e32016-10-07 14:44:07 -0400252 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
253 ? 255
254 : (unsigned char)(spotAlpha*255.999f), 0, 0, 0));
jvanverthe1a3bc62016-08-12 10:40:38 -0700255
256 // apply transformation to shadow
jvanverthe1a3bc62016-08-12 10:40:38 -0700257 canvas->scale(scale, scale);
jvanverthd99858a2016-09-12 07:51:04 -0700258 canvas->translate(offset.fX, offset.fY);
jvanverthe1a3bc62016-08-12 10:40:38 -0700259 canvas->drawPath(path, paint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700260 }
261
jvanverthd7315f912016-08-17 10:06:18 -0700262 void drawSpotShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
263 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
264 if (spotAlpha <= 0) {
265 return;
266 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700267
jvanverthd7315f912016-08-17 10:06:18 -0700268 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
269 if (zRatio < 0.0f) {
270 zRatio = 0.0f;
271 } else if (zRatio > 0.95f) {
272 zRatio = 0.95f;
273 }
jvanverthd99858a2016-09-12 07:51:04 -0700274 SkScalar radius = 2.0f*lightWidth*zRatio;
jvanverthd7315f912016-08-17 10:06:18 -0700275
jvanvertha4f1af82016-08-29 07:17:47 -0700276 SkRect pathRect;
277 SkRRect pathRRect;
jvanverthd99858a2016-09-12 07:51:04 -0700278 SkScalar scaleFactors[2];
279 if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
280 return;
281 }
282 if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 16384 ||
jvanvertha4f1af82016-08-29 07:17:47 -0700283 !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
284 (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
285 path.isRect(&pathRect))) {
286 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
287 return;
288 }
289
jvanverthd99858a2016-09-12 07:51:04 -0700290 // For all of these, we need to ensure we have a rrect with radius >= 0.5f in device space
Robert Phillips95304e32016-10-07 14:44:07 -0400291 const SkScalar minRadius = SK_ScalarHalf/scaleFactors[0];
jvanverthd7315f912016-08-17 10:06:18 -0700292 if (path.isOval(nullptr)) {
jvanverthd7315f912016-08-17 10:06:18 -0700293 pathRRect = SkRRect::MakeOval(pathRect);
294 } else if (path.isRect(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700295 pathRRect = SkRRect::MakeRectXY(pathRect, minRadius, minRadius);
jvanverthd7315f912016-08-17 10:06:18 -0700296 } else {
jvanverthd99858a2016-09-12 07:51:04 -0700297 if (pathRRect.getSimpleRadii().fX < minRadius) {
298 pathRRect.setRectXY(pathRRect.rect(), minRadius, minRadius);
299 }
jvanverthd7315f912016-08-17 10:06:18 -0700300 }
301
jvanverthd99858a2016-09-12 07:51:04 -0700302 // compute the scale and translation for the shadow
303 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
304 SkRRect shadowRRect;
305 pathRRect.transform(SkMatrix::MakeScale(scale, scale), &shadowRRect);
306 SkPoint center = SkPoint::Make(shadowRRect.rect().centerX(), shadowRRect.rect().centerY());
307 SkMatrix ctmInverse;
308 if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
309 return;
310 }
311 SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
312 ctmInverse.mapPoints(&lightPos2D, 1);
313 SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
314 zRatio*(center.fY - lightPos2D.fY));
jvanverthd7315f912016-08-17 10:06:18 -0700315 SkAutoCanvasRestore acr(canvas, true);
316
317 SkPaint paint;
318 paint.setAntiAlias(true);
Robert Phillips95304e32016-10-07 14:44:07 -0400319 // We want to extend the stroked area in so that it meets up with the caster
320 // geometry. The stroked geometry will, by definition already be inset half the
321 // stroke width but we also have to account for the scaling.
322 // We also add 1/2 to cover up AA on the interior edge.
323 SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(pathRect.fLeft),
324 SkTAbs(pathRect.fRight)),
325 SkTMax(SkTAbs(pathRect.fTop),
326 SkTAbs(pathRect.fBottom)));
327 SkScalar insetAmount = offset.length() - (0.5f * radius) + scaleOffset + 0.5f;
328
jvanvertha4f1af82016-08-29 07:17:47 -0700329 // compute area
Robert Phillips95304e32016-10-07 14:44:07 -0400330 SkScalar strokeWidth = radius + insetAmount;
jvanverthd99858a2016-09-12 07:51:04 -0700331 SkScalar strokedArea = 2.0f*strokeWidth*(shadowRRect.width() + shadowRRect.height());
332 SkScalar filledArea = (shadowRRect.height() + radius)*(shadowRRect.width() + radius);
jvanvertha4f1af82016-08-29 07:17:47 -0700333 // If the area of the stroked geometry is larger than the fill geometry, or
334 // if our pad is too big to convert to 6.2 fixed point, just fill it.
Robert Phillips95304e32016-10-07 14:44:07 -0400335 if (strokedArea > filledArea) {
jvanvertha4f1af82016-08-29 07:17:47 -0700336 paint.setStyle(SkPaint::kStrokeAndFill_Style);
337 paint.setStrokeWidth(radius);
338 } else {
Robert Phillips95304e32016-10-07 14:44:07 -0400339 // Since we can't have unequal strokes, inset the shadow rect so the inner
340 // and outer edges of the stroke will land where we want.
341 SkRect insetRect = shadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
342 SkScalar insetRad = SkTMax(shadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
343 minRadius);
344
345 shadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
jvanvertha4f1af82016-08-29 07:17:47 -0700346 paint.setStyle(SkPaint::kStroke_Style);
347 paint.setStrokeWidth(strokeWidth);
348 }
jvanverthc20c0c02016-09-14 07:04:49 -0700349 paint.setShader(SkGaussianEdgeShader::Make());
jvanverthd7315f912016-08-17 10:06:18 -0700350 // handle scale of radius due to CTM
jvanverthd99858a2016-09-12 07:51:04 -0700351 radius *= scaleFactors[0];
352 // don't need to scale pad as it was computed from the transformed offset
353 SkASSERT(radius < 16384);
Robert Phillips95304e32016-10-07 14:44:07 -0400354 SkScalar pad = 0;
jvanvertha4f1af82016-08-29 07:17:47 -0700355 SkASSERT(pad < 64);
jvanverthd99858a2016-09-12 07:51:04 -0700356 // Convert radius to 14.2 fixed point and place in the R & G components.
357 // Convert pad to 6.2 fixed point and place in the B component.
358 uint16_t iRadius = (uint16_t)(radius*4.0f);
359 unsigned char alpha = (unsigned char)(spotAlpha*255.999f);
Robert Phillips95304e32016-10-07 14:44:07 -0400360 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
361 iRadius >> 8, iRadius & 0xff,
jvanverthd99858a2016-09-12 07:51:04 -0700362 (unsigned char)(4.0f*pad)));
jvanverthd7315f912016-08-17 10:06:18 -0700363
364 // apply transformation to shadow
365 canvas->translate(offset.fX, offset.fY);
jvanverthd99858a2016-09-12 07:51:04 -0700366 canvas->drawRRect(shadowRRect, paint);
jvanverthd7315f912016-08-17 10:06:18 -0700367 }
368
369 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
370 const SkPaint& paint, SkScalar ambientAlpha,
371 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
Jim Van Verth43475ad2017-01-13 14:37:37 -0500372#ifdef USE_SHADOW_UTILS
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400373 if (fUseAlt) {
374 if (fShowAmbient) {
375 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
376 }
377 if (fShowSpot) {
378 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
379 }
380 } else {
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400381 if (!fShowAmbient) {
382 ambientAlpha = 0;
383 }
384 if (!fShowSpot) {
385 spotAlpha = 0;
386 }
Jim Van Verth43475ad2017-01-13 14:37:37 -0500387 SkShadowUtils::DrawShadow(canvas, path, zValue, lightPos, lightWidth,
388 ambientAlpha, spotAlpha, SK_ColorBLACK);
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400389 }
390#else
jvanverthe1a3bc62016-08-12 10:40:38 -0700391 if (fShowAmbient) {
jvanverthd7315f912016-08-17 10:06:18 -0700392 if (fUseAlt) {
393 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
jvanverth6c177a12016-08-17 07:59:41 -0700394 } else {
jvanverthd7315f912016-08-17 10:06:18 -0700395 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
jvanverth6c177a12016-08-17 07:59:41 -0700396 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700397 }
398 if (fShowSpot) {
jvanverthd7315f912016-08-17 10:06:18 -0700399 if (fUseAlt) {
400 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
401 } else {
402 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
403 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700404 }
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400405#endif
406
jvanverthe1a3bc62016-08-12 10:40:38 -0700407 if (fShowObject) {
408 canvas->drawPath(path, paint);
Robert Phillips95304e32016-10-07 14:44:07 -0400409 } else {
410 SkPaint strokePaint;
411
412 strokePaint.setColor(paint.getColor());
413 strokePaint.setStyle(SkPaint::kStroke_Style);
414
415 canvas->drawPath(path, strokePaint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700416 }
417 }
418
419 void onDrawContent(SkCanvas* canvas) override {
420 this->drawBG(canvas);
jvanverthd99858a2016-09-12 07:51:04 -0700421 const SkScalar kLightWidth = 2800;
jvanverthd7315f912016-08-17 10:06:18 -0700422 const SkScalar kAmbientAlpha = 0.25f;
423 const SkScalar kSpotAlpha = 0.25f;
jvanverthe1a3bc62016-08-12 10:40:38 -0700424
425 SkPaint paint;
426 paint.setAntiAlias(true);
427
jvanverthd7315f912016-08-17 10:06:18 -0700428 SkPoint3 lightPos = fLightPos;
429
jvanverthe1a3bc62016-08-12 10:40:38 -0700430 paint.setColor(SK_ColorWHITE);
431 canvas->translate(200, 90);
jvanverthd7315f912016-08-17 10:06:18 -0700432 lightPos.fX += 200;
433 lightPos.fY += 90;
Jim Van Verthc5903412016-11-17 15:27:09 -0500434 this->drawShadowedPath(canvas, fRectPath, 2, paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700435 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700436
437 paint.setColor(SK_ColorRED);
438 canvas->translate(250, 0);
jvanverthd7315f912016-08-17 10:06:18 -0700439 lightPos.fX += 250;
jvanverthd99858a2016-09-12 07:51:04 -0700440 this->drawShadowedPath(canvas, fRRPath, 4, paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700441 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700442
443 paint.setColor(SK_ColorBLUE);
444 canvas->translate(-250, 110);
jvanverthd7315f912016-08-17 10:06:18 -0700445 lightPos.fX -= 250;
446 lightPos.fY += 110;
jvanverthd99858a2016-09-12 07:51:04 -0700447 this->drawShadowedPath(canvas, fCirclePath, 8, paint, 0.0f,
jvanverthd7315f912016-08-17 10:06:18 -0700448 lightPos, kLightWidth, 0.5f);
jvanverth6c177a12016-08-17 07:59:41 -0700449
450 paint.setColor(SK_ColorGREEN);
451 canvas->translate(250, 0);
jvanverthd7315f912016-08-17 10:06:18 -0700452 lightPos.fX += 250;
jvanverthd99858a2016-09-12 07:51:04 -0700453 this->drawShadowedPath(canvas, fRRPath, 64, paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700454 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700455 }
456
457protected:
458 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
459 return new SkView::Click(this);
460 }
461
462 bool onClick(Click *click) override {
463 SkScalar x = click->fCurr.fX;
464 SkScalar y = click->fCurr.fY;
465
466 SkScalar dx = x - click->fPrev.fX;
467 SkScalar dy = y - click->fPrev.fY;
468
469 if (dx != 0 || dy != 0) {
470 fLightPos.fX += dx;
471 fLightPos.fY += dy;
472 this->inval(nullptr);
473 }
474
475 return true;
476 }
477
478private:
479 typedef SkView INHERITED;
480};
481
482//////////////////////////////////////////////////////////////////////////////
483
484static SkView* MyFactory() { return new ShadowsView; }
485static SkViewRegister reg(MyFactory);