blob: 0e0a4b4a79dc873d8de90d3953ab5326783f2778 [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"
Jim Van Verth2aa535e2017-02-06 14:36:01 -050011#include "SkColorFilter.h"
jvanverthe1a3bc62016-08-12 10:40:38 -070012#include "SkCanvas.h"
jvanverth6c177a12016-08-17 07:59:41 -070013#include "SkGaussianEdgeShader.h"
jvanverthe1a3bc62016-08-12 10:40:38 -070014#include "SkPath.h"
15#include "SkPoint3.h"
Jim Van Verth43475ad2017-01-13 14:37:37 -050016#include "SkShadowUtils.h"
jvanverthe1a3bc62016-08-12 10:40:38 -070017#include "SkUtils.h"
18#include "SkView.h"
19#include "sk_tool_utils.h"
20
Jim Van Verth43475ad2017-01-13 14:37:37 -050021#define USE_SHADOW_UTILS
22
jvanverth6c177a12016-08-17 07:59:41 -070023////////////////////////////////////////////////////////////////////////////
24
jvanverthe1a3bc62016-08-12 10:40:38 -070025class ShadowsView : public SampleView {
26 SkPath fRectPath;
27 SkPath fRRPath;
28 SkPath fCirclePath;
Jim Van Verthbce74962017-01-25 09:39:46 -050029 SkPath fFunkyRRPath;
30 SkPath fCubicPath;
jvanverthe1a3bc62016-08-12 10:40:38 -070031 SkPoint3 fLightPos;
Jim Van Verth2aa535e2017-02-06 14:36:01 -050032 SkScalar fZDelta;
jvanverthe1a3bc62016-08-12 10:40:38 -070033
34 bool fShowAmbient;
35 bool fShowSpot;
jvanverthd7315f912016-08-17 10:06:18 -070036 bool fUseAlt;
jvanverthe1a3bc62016-08-12 10:40:38 -070037 bool fShowObject;
Robert Phillips95304e32016-10-07 14:44:07 -040038 bool fIgnoreShadowAlpha;
jvanverthe1a3bc62016-08-12 10:40:38 -070039
40public:
Jim Van Verth2aa535e2017-02-06 14:36:01 -050041 ShadowsView()
42 : fZDelta(0.0f)
43 , fShowAmbient(true)
jvanverthe1a3bc62016-08-12 10:40:38 -070044 , fShowSpot(true)
jvanverthd7315f912016-08-17 10:06:18 -070045 , fUseAlt(true)
Robert Phillips95304e32016-10-07 14:44:07 -040046 , fShowObject(true)
47 , fIgnoreShadowAlpha(false) {}
jvanverthe1a3bc62016-08-12 10:40:38 -070048
49protected:
50 void onOnceBeforeDraw() override {
51 fCirclePath.addCircle(0, 0, 50);
52 fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
53 fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4));
Jim Van Verthbce74962017-01-25 09:39:46 -050054 fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100),
55 40 * SK_Scalar1, 20 * SK_Scalar1,
56 SkPath::kCW_Direction);
57 fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1,
58 20 * SK_Scalar1, 100 * SK_Scalar1,
59 0 * SK_Scalar1, 0 * SK_Scalar1);
60
jvanverthd99858a2016-09-12 07:51:04 -070061 fLightPos = SkPoint3::Make(-700, -700, 2800);
jvanverthe1a3bc62016-08-12 10:40:38 -070062 }
63
64 // overrides from SkEventSink
65 bool onQuery(SkEvent* evt) override {
66 if (SampleCode::TitleQ(*evt)) {
67 SampleCode::TitleR(evt, "AndroidShadows");
68 return true;
69 }
70
71 SkUnichar uni;
72 if (SampleCode::CharQ(*evt, &uni)) {
73 switch (uni) {
Jim Van Verth2aa535e2017-02-06 14:36:01 -050074 case 'W':
jvanverthe1a3bc62016-08-12 10:40:38 -070075 fShowAmbient = !fShowAmbient;
76 break;
77 case 'S':
78 fShowSpot = !fShowSpot;
79 break;
jvanverthd7315f912016-08-17 10:06:18 -070080 case 'T':
81 fUseAlt = !fUseAlt;
82 break;
jvanverthe1a3bc62016-08-12 10:40:38 -070083 case 'O':
84 fShowObject = !fShowObject;
85 break;
86 case '>':
Jim Van Verth2aa535e2017-02-06 14:36:01 -050087 fZDelta += 0.5f;
jvanverthe1a3bc62016-08-12 10:40:38 -070088 break;
89 case '<':
Jim Van Verth2aa535e2017-02-06 14:36:01 -050090 fZDelta -= 0.5f;
jvanverthe1a3bc62016-08-12 10:40:38 -070091 break;
Robert Phillips95304e32016-10-07 14:44:07 -040092 case '?':
93 fIgnoreShadowAlpha = !fIgnoreShadowAlpha;
94 break;
jvanverthe1a3bc62016-08-12 10:40:38 -070095 default:
96 break;
97 }
98 this->inval(nullptr);
99 }
100 return this->INHERITED::onQuery(evt);
101 }
102
103 void drawBG(SkCanvas* canvas) {
104 canvas->drawColor(0xFFDDDDDD);
105 }
106
107 static void GetOcclRect(const SkPath& path, SkRect* occlRect) {
108 SkRect pathRect;
109 SkRRect pathRRect;
110 if (path.isOval(&pathRect)) {
111 *occlRect = sk_tool_utils::compute_central_occluder(SkRRect::MakeOval(pathRect));
112 } else if (path.isRRect(&pathRRect)) {
113 *occlRect = sk_tool_utils::compute_central_occluder(pathRRect);
114 } else if (path.isRect(occlRect)) {
115 // the inverse transform for the spot shadow occluder doesn't always get us
116 // back to exactly the same position, so deducting a little slop
117 occlRect->inset(1, 1);
118 } else {
119 *occlRect = SkRect::MakeEmpty();
120 }
121 }
122
123 void drawAmbientShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
124 SkScalar ambientAlpha) {
125
126 if (ambientAlpha <= 0) {
127 return;
128 }
129
130 const SkScalar kHeightFactor = 1.f / 128.f;
131 const SkScalar kGeomFactor = 64;
132
133 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
134 SkScalar radius = zValue*kHeightFactor*kGeomFactor;
135
136 // occlude blur
137 SkRect occlRect;
138 GetOcclRect(path, &occlRect);
139 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
140 SkBlurMask::ConvertRadiusToSigma(radius),
141 occlRect,
142 SkBlurMaskFilter::kNone_BlurFlag);
143
144 SkPaint paint;
145 paint.setAntiAlias(true);
146 paint.setMaskFilter(std::move(mf));
Robert Phillips95304e32016-10-07 14:44:07 -0400147 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
148 ? 255
149 : (unsigned char)(ambientAlpha*umbraAlpha*255.999f), 0, 0, 0));
jvanverthe1a3bc62016-08-12 10:40:38 -0700150 canvas->drawPath(path, paint);
151
152 // draw occlusion rect
jvanverth6c177a12016-08-17 07:59:41 -0700153#if DRAW_OCCL_RECT
jvanverthe1a3bc62016-08-12 10:40:38 -0700154 SkPaint stroke;
155 stroke.setStyle(SkPaint::kStroke_Style);
156 stroke.setColor(SK_ColorBLUE);
157 canvas->drawRect(occlRect, stroke);
jvanverth6c177a12016-08-17 07:59:41 -0700158#endif
159 }
160
161 void drawAmbientShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
162 SkScalar ambientAlpha) {
163
164 if (ambientAlpha <= 0) {
165 return;
166 }
167
168 const SkScalar kHeightFactor = 1.f / 128.f;
169 const SkScalar kGeomFactor = 64;
170
171 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
172 SkScalar radius = zValue*kHeightFactor*kGeomFactor;
jvanverthd99858a2016-09-12 07:51:04 -0700173 // distance to outer of edge of geometry from original shape edge
174 SkScalar offset = radius*umbraAlpha;
jvanverth6c177a12016-08-17 07:59:41 -0700175
jvanvertha4f1af82016-08-29 07:17:47 -0700176 SkRect pathRect;
177 SkRRect pathRRect;
jvanverthd99858a2016-09-12 07:51:04 -0700178 SkScalar scaleFactors[2];
179 if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
180 return;
181 }
182 if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 64 ||
jvanvertha4f1af82016-08-29 07:17:47 -0700183 !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
184 (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
185 path.isRect(&pathRect))) {
186 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
187 return;
188 }
189
jvanverthd99858a2016-09-12 07:51:04 -0700190 // For all of these, we inset the offset rect by half the radius to get our stroke shape.
191 SkScalar strokeOutset = offset - SK_ScalarHalf*radius;
192 // Make sure we'll have a radius of at least 0.5 after xform
193 if (strokeOutset*scaleFactors[0] < 0.5f) {
194 strokeOutset = 0.5f / scaleFactors[0];
195 }
jvanverthd7315f912016-08-17 10:06:18 -0700196 if (path.isOval(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700197 pathRect.outset(strokeOutset, strokeOutset);
jvanverthd7315f912016-08-17 10:06:18 -0700198 pathRRect = SkRRect::MakeOval(pathRect);
199 } else if (path.isRect(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700200 pathRect.outset(strokeOutset, strokeOutset);
201 pathRRect = SkRRect::MakeRectXY(pathRect, strokeOutset, strokeOutset);
jvanverth6c177a12016-08-17 07:59:41 -0700202 } else {
jvanverthd99858a2016-09-12 07:51:04 -0700203 pathRRect.outset(strokeOutset, strokeOutset);
jvanverth6c177a12016-08-17 07:59:41 -0700204 }
205
jvanverthd7315f912016-08-17 10:06:18 -0700206 SkPaint paint;
207 paint.setAntiAlias(true);
jvanvertha4f1af82016-08-29 07:17:47 -0700208 paint.setStyle(SkPaint::kStroke_Style);
209 // we outset the stroke a little to cover up AA on the interior edge
jvanverthd99858a2016-09-12 07:51:04 -0700210 SkScalar pad = 0.5f;
211 paint.setStrokeWidth(radius + 2*pad);
212 // handle scale of radius and pad due to CTM
213 radius *= scaleFactors[0];
214 pad *= scaleFactors[0];
215 SkASSERT(radius < 16384);
216 SkASSERT(pad < 64);
217 // Convert radius to 14.2 fixed point and place in the R & G components.
218 // Convert pad to 6.2 fixed point and place in the B component.
219 uint16_t iRadius = (uint16_t)(radius*4.0f);
220 unsigned char alpha = (unsigned char)(ambientAlpha*255.999f);
Robert Phillips95304e32016-10-07 14:44:07 -0400221 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
222 iRadius >> 8, iRadius & 0xff,
jvanverthd99858a2016-09-12 07:51:04 -0700223 (unsigned char)(4.0f*pad)));
jvanverthd7315f912016-08-17 10:06:18 -0700224
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500225 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLACK, SkBlendMode::kModulate));
jvanverthc20c0c02016-09-14 07:04:49 -0700226 paint.setShader(SkGaussianEdgeShader::Make());
jvanverthd7315f912016-08-17 10:06:18 -0700227 canvas->drawRRect(pathRRect, paint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700228 }
229
230 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
231 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
232 if (spotAlpha <= 0) {
233 return;
234 }
235
236 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
237 if (zRatio < 0.0f) {
238 zRatio = 0.0f;
239 } else if (zRatio > 0.95f) {
240 zRatio = 0.95f;
241 }
jvanverthd99858a2016-09-12 07:51:04 -0700242 SkScalar blurRadius = lightWidth*zRatio;
jvanverthe1a3bc62016-08-12 10:40:38 -0700243
244 // compute the transformation params
245 SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY());
jvanverthd99858a2016-09-12 07:51:04 -0700246 SkMatrix ctmInverse;
247 if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
248 return;
jvanverthe1a3bc62016-08-12 10:40:38 -0700249 }
jvanverthd99858a2016-09-12 07:51:04 -0700250 SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
251 ctmInverse.mapPoints(&lightPos2D, 1);
252 SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
253 zRatio*(center.fY - lightPos2D.fY));
254 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
jvanverthe1a3bc62016-08-12 10:40:38 -0700255
256 SkAutoCanvasRestore acr(canvas, true);
257
jvanverthe1a3bc62016-08-12 10:40:38 -0700258 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
jvanverthd99858a2016-09-12 07:51:04 -0700259 SkBlurMask::ConvertRadiusToSigma(blurRadius),
jvanverthe1a3bc62016-08-12 10:40:38 -0700260 SkBlurMaskFilter::kNone_BlurFlag);
261
262 SkPaint paint;
263 paint.setAntiAlias(true);
264 paint.setMaskFilter(std::move(mf));
Robert Phillips95304e32016-10-07 14:44:07 -0400265 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha
266 ? 255
267 : (unsigned char)(spotAlpha*255.999f), 0, 0, 0));
jvanverthe1a3bc62016-08-12 10:40:38 -0700268
269 // apply transformation to shadow
jvanverthe1a3bc62016-08-12 10:40:38 -0700270 canvas->scale(scale, scale);
jvanverthd99858a2016-09-12 07:51:04 -0700271 canvas->translate(offset.fX, offset.fY);
jvanverthe1a3bc62016-08-12 10:40:38 -0700272 canvas->drawPath(path, paint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700273 }
274
jvanverthd7315f912016-08-17 10:06:18 -0700275 void drawSpotShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
276 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
277 if (spotAlpha <= 0) {
278 return;
279 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700280
jvanverthd7315f912016-08-17 10:06:18 -0700281 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
282 if (zRatio < 0.0f) {
283 zRatio = 0.0f;
284 } else if (zRatio > 0.95f) {
285 zRatio = 0.95f;
286 }
jvanverthd99858a2016-09-12 07:51:04 -0700287 SkScalar radius = 2.0f*lightWidth*zRatio;
jvanverthd7315f912016-08-17 10:06:18 -0700288
jvanvertha4f1af82016-08-29 07:17:47 -0700289 SkRect pathRect;
290 SkRRect pathRRect;
jvanverthd99858a2016-09-12 07:51:04 -0700291 SkScalar scaleFactors[2];
292 if (!canvas->getTotalMatrix().getMinMaxScales(scaleFactors)) {
293 return;
294 }
295 if (scaleFactors[0] != scaleFactors[1] || radius*scaleFactors[0] >= 16384 ||
jvanvertha4f1af82016-08-29 07:17:47 -0700296 !((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) ||
297 (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) ||
298 path.isRect(&pathRect))) {
299 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
300 return;
301 }
302
jvanverthd99858a2016-09-12 07:51:04 -0700303 // 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 -0400304 const SkScalar minRadius = SK_ScalarHalf/scaleFactors[0];
jvanverthd7315f912016-08-17 10:06:18 -0700305 if (path.isOval(nullptr)) {
jvanverthd7315f912016-08-17 10:06:18 -0700306 pathRRect = SkRRect::MakeOval(pathRect);
307 } else if (path.isRect(nullptr)) {
jvanverthd99858a2016-09-12 07:51:04 -0700308 pathRRect = SkRRect::MakeRectXY(pathRect, minRadius, minRadius);
jvanverthd7315f912016-08-17 10:06:18 -0700309 } else {
jvanverthd99858a2016-09-12 07:51:04 -0700310 if (pathRRect.getSimpleRadii().fX < minRadius) {
311 pathRRect.setRectXY(pathRRect.rect(), minRadius, minRadius);
312 }
jvanverthd7315f912016-08-17 10:06:18 -0700313 }
314
jvanverthd99858a2016-09-12 07:51:04 -0700315 // compute the scale and translation for the shadow
316 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
317 SkRRect shadowRRect;
318 pathRRect.transform(SkMatrix::MakeScale(scale, scale), &shadowRRect);
319 SkPoint center = SkPoint::Make(shadowRRect.rect().centerX(), shadowRRect.rect().centerY());
320 SkMatrix ctmInverse;
321 if (!canvas->getTotalMatrix().invert(&ctmInverse)) {
322 return;
323 }
324 SkPoint lightPos2D = SkPoint::Make(lightPos.fX, lightPos.fY);
325 ctmInverse.mapPoints(&lightPos2D, 1);
326 SkPoint offset = SkPoint::Make(zRatio*(center.fX - lightPos2D.fX),
327 zRatio*(center.fY - lightPos2D.fY));
jvanverthd7315f912016-08-17 10:06:18 -0700328 SkAutoCanvasRestore acr(canvas, true);
329
330 SkPaint paint;
331 paint.setAntiAlias(true);
Robert Phillips95304e32016-10-07 14:44:07 -0400332 // We want to extend the stroked area in so that it meets up with the caster
333 // geometry. The stroked geometry will, by definition already be inset half the
334 // stroke width but we also have to account for the scaling.
335 // We also add 1/2 to cover up AA on the interior edge.
336 SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(pathRect.fLeft),
337 SkTAbs(pathRect.fRight)),
338 SkTMax(SkTAbs(pathRect.fTop),
339 SkTAbs(pathRect.fBottom)));
340 SkScalar insetAmount = offset.length() - (0.5f * radius) + scaleOffset + 0.5f;
341
jvanvertha4f1af82016-08-29 07:17:47 -0700342 // compute area
Robert Phillips95304e32016-10-07 14:44:07 -0400343 SkScalar strokeWidth = radius + insetAmount;
jvanverthd99858a2016-09-12 07:51:04 -0700344 SkScalar strokedArea = 2.0f*strokeWidth*(shadowRRect.width() + shadowRRect.height());
345 SkScalar filledArea = (shadowRRect.height() + radius)*(shadowRRect.width() + radius);
jvanvertha4f1af82016-08-29 07:17:47 -0700346 // If the area of the stroked geometry is larger than the fill geometry, or
347 // if our pad is too big to convert to 6.2 fixed point, just fill it.
Robert Phillips95304e32016-10-07 14:44:07 -0400348 if (strokedArea > filledArea) {
jvanvertha4f1af82016-08-29 07:17:47 -0700349 paint.setStyle(SkPaint::kStrokeAndFill_Style);
350 paint.setStrokeWidth(radius);
351 } else {
Robert Phillips95304e32016-10-07 14:44:07 -0400352 // Since we can't have unequal strokes, inset the shadow rect so the inner
353 // and outer edges of the stroke will land where we want.
354 SkRect insetRect = shadowRRect.rect().makeInset(insetAmount/2.0f, insetAmount/2.0f);
355 SkScalar insetRad = SkTMax(shadowRRect.getSimpleRadii().fX - insetAmount/2.0f,
356 minRadius);
357
358 shadowRRect = SkRRect::MakeRectXY(insetRect, insetRad, insetRad);
jvanvertha4f1af82016-08-29 07:17:47 -0700359 paint.setStyle(SkPaint::kStroke_Style);
360 paint.setStrokeWidth(strokeWidth);
361 }
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500362 paint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorBLACK, SkBlendMode::kModulate));
jvanverthc20c0c02016-09-14 07:04:49 -0700363 paint.setShader(SkGaussianEdgeShader::Make());
jvanverthd7315f912016-08-17 10:06:18 -0700364 // handle scale of radius due to CTM
jvanverthd99858a2016-09-12 07:51:04 -0700365 radius *= scaleFactors[0];
366 // don't need to scale pad as it was computed from the transformed offset
367 SkASSERT(radius < 16384);
Robert Phillips95304e32016-10-07 14:44:07 -0400368 SkScalar pad = 0;
jvanvertha4f1af82016-08-29 07:17:47 -0700369 SkASSERT(pad < 64);
jvanverthd99858a2016-09-12 07:51:04 -0700370 // Convert radius to 14.2 fixed point and place in the R & G components.
371 // Convert pad to 6.2 fixed point and place in the B component.
372 uint16_t iRadius = (uint16_t)(radius*4.0f);
373 unsigned char alpha = (unsigned char)(spotAlpha*255.999f);
Robert Phillips95304e32016-10-07 14:44:07 -0400374 paint.setColor(SkColorSetARGB(fIgnoreShadowAlpha ? 255 : alpha,
375 iRadius >> 8, iRadius & 0xff,
jvanverthd99858a2016-09-12 07:51:04 -0700376 (unsigned char)(4.0f*pad)));
jvanverthd7315f912016-08-17 10:06:18 -0700377
378 // apply transformation to shadow
379 canvas->translate(offset.fX, offset.fY);
jvanverthd99858a2016-09-12 07:51:04 -0700380 canvas->drawRRect(shadowRRect, paint);
jvanverthd7315f912016-08-17 10:06:18 -0700381 }
382
383 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
384 const SkPaint& paint, SkScalar ambientAlpha,
385 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) {
Jim Van Verth43475ad2017-01-13 14:37:37 -0500386#ifdef USE_SHADOW_UTILS
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400387 if (fUseAlt) {
388 if (fShowAmbient) {
389 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
390 }
391 if (fShowSpot) {
392 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
393 }
394 } else {
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400395 if (!fShowAmbient) {
396 ambientAlpha = 0;
397 }
398 if (!fShowSpot) {
399 spotAlpha = 0;
400 }
Jim Van Verth43475ad2017-01-13 14:37:37 -0500401 SkShadowUtils::DrawShadow(canvas, path, zValue, lightPos, lightWidth,
402 ambientAlpha, spotAlpha, SK_ColorBLACK);
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400403 }
404#else
jvanverthe1a3bc62016-08-12 10:40:38 -0700405 if (fShowAmbient) {
jvanverthd7315f912016-08-17 10:06:18 -0700406 if (fUseAlt) {
407 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
jvanverth6c177a12016-08-17 07:59:41 -0700408 } else {
jvanverthd7315f912016-08-17 10:06:18 -0700409 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
jvanverth6c177a12016-08-17 07:59:41 -0700410 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700411 }
412 if (fShowSpot) {
jvanverthd7315f912016-08-17 10:06:18 -0700413 if (fUseAlt) {
414 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
415 } else {
416 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
417 }
jvanverthe1a3bc62016-08-12 10:40:38 -0700418 }
Jim Van Verth3c1b7db2016-10-31 16:06:51 -0400419#endif
420
jvanverthe1a3bc62016-08-12 10:40:38 -0700421 if (fShowObject) {
422 canvas->drawPath(path, paint);
Robert Phillips95304e32016-10-07 14:44:07 -0400423 } else {
424 SkPaint strokePaint;
425
426 strokePaint.setColor(paint.getColor());
427 strokePaint.setStyle(SkPaint::kStroke_Style);
428
429 canvas->drawPath(path, strokePaint);
jvanverthe1a3bc62016-08-12 10:40:38 -0700430 }
431 }
432
433 void onDrawContent(SkCanvas* canvas) override {
434 this->drawBG(canvas);
jvanverthd99858a2016-09-12 07:51:04 -0700435 const SkScalar kLightWidth = 2800;
jvanverthd7315f912016-08-17 10:06:18 -0700436 const SkScalar kAmbientAlpha = 0.25f;
437 const SkScalar kSpotAlpha = 0.25f;
jvanverthe1a3bc62016-08-12 10:40:38 -0700438
439 SkPaint paint;
440 paint.setAntiAlias(true);
441
jvanverthd7315f912016-08-17 10:06:18 -0700442 SkPoint3 lightPos = fLightPos;
443
jvanverthe1a3bc62016-08-12 10:40:38 -0700444 paint.setColor(SK_ColorWHITE);
445 canvas->translate(200, 90);
jvanverthd7315f912016-08-17 10:06:18 -0700446 lightPos.fX += 200;
447 lightPos.fY += 90;
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500448 this->drawShadowedPath(canvas, fRRPath, SkTMax(1.0f, 2+fZDelta), paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700449 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700450
451 paint.setColor(SK_ColorRED);
452 canvas->translate(250, 0);
jvanverthd7315f912016-08-17 10:06:18 -0700453 lightPos.fX += 250;
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500454 this->drawShadowedPath(canvas, fRectPath, SkTMax(1.0f, 4+fZDelta), paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700455 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700456
457 paint.setColor(SK_ColorBLUE);
458 canvas->translate(-250, 110);
jvanverthd7315f912016-08-17 10:06:18 -0700459 lightPos.fX -= 250;
460 lightPos.fY += 110;
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500461 this->drawShadowedPath(canvas, fCirclePath, SkTMax(1.0f, 8+fZDelta), paint, 0,
jvanverthd7315f912016-08-17 10:06:18 -0700462 lightPos, kLightWidth, 0.5f);
jvanverth6c177a12016-08-17 07:59:41 -0700463
464 paint.setColor(SK_ColorGREEN);
465 canvas->translate(250, 0);
jvanverthd7315f912016-08-17 10:06:18 -0700466 lightPos.fX += 250;
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500467 this->drawShadowedPath(canvas, fRRPath, SkTMax(1.0f, 64+fZDelta), paint, kAmbientAlpha,
jvanverthd7315f912016-08-17 10:06:18 -0700468 lightPos, kLightWidth, kSpotAlpha);
Jim Van Verthbce74962017-01-25 09:39:46 -0500469
470 paint.setColor(SK_ColorYELLOW);
471 canvas->translate(-250, 110);
472 lightPos.fX -= 250;
473 lightPos.fY += 110;
Jim Van Verth2aa535e2017-02-06 14:36:01 -0500474 this->drawShadowedPath(canvas, fFunkyRRPath, SkTMax(1.0f, 8+fZDelta), paint, kAmbientAlpha,
Jim Van Verthbce74962017-01-25 09:39:46 -0500475 lightPos, kLightWidth, kSpotAlpha);
476
477 paint.setColor(SK_ColorCYAN);
478 canvas->translate(250, 0);
479 lightPos.fX += 250;
480 this->drawShadowedPath(canvas, fCubicPath, 16, paint, kAmbientAlpha,
481 lightPos, kLightWidth, kSpotAlpha);
jvanverthe1a3bc62016-08-12 10:40:38 -0700482 }
483
484protected:
485 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) override {
486 return new SkView::Click(this);
487 }
488
489 bool onClick(Click *click) override {
490 SkScalar x = click->fCurr.fX;
491 SkScalar y = click->fCurr.fY;
492
493 SkScalar dx = x - click->fPrev.fX;
494 SkScalar dy = y - click->fPrev.fY;
495
496 if (dx != 0 || dy != 0) {
497 fLightPos.fX += dx;
498 fLightPos.fY += dy;
499 this->inval(nullptr);
500 }
501
502 return true;
503 }
504
505private:
506 typedef SkView INHERITED;
507};
508
509//////////////////////////////////////////////////////////////////////////////
510
511static SkView* MyFactory() { return new ShadowsView; }
512static SkViewRegister reg(MyFactory);