Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(532)

Side by Side Diff: samplecode/SampleAndroidShadows.cpp

Issue 2256713002: Add alternative spot shadow to Android shadow sample (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments; fix scale Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/effects/SkGaussianEdgeShader.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2016 Google Inc. 3 * Copyright 2016 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 #include "SampleCode.h" 8 #include "SampleCode.h"
9 #include "SkBlurMask.h" 9 #include "SkBlurMask.h"
10 #include "SkBlurMaskFilter.h" 10 #include "SkBlurMaskFilter.h"
11 #include "SkCanvas.h" 11 #include "SkCanvas.h"
12 #include "SkGaussianEdgeShader.h" 12 #include "SkGaussianEdgeShader.h"
13 #include "SkPath.h" 13 #include "SkPath.h"
14 #include "SkPoint3.h" 14 #include "SkPoint3.h"
15 #include "SkUtils.h" 15 #include "SkUtils.h"
16 #include "SkView.h" 16 #include "SkView.h"
17 #include "sk_tool_utils.h" 17 #include "sk_tool_utils.h"
18 18
19 //////////////////////////////////////////////////////////////////////////// 19 ////////////////////////////////////////////////////////////////////////////
20 20
21 class ShadowsView : public SampleView { 21 class ShadowsView : public SampleView {
22 SkPath fRectPath; 22 SkPath fRectPath;
23 SkPath fRRPath; 23 SkPath fRRPath;
24 SkPath fCirclePath; 24 SkPath fCirclePath;
25 SkPoint3 fLightPos; 25 SkPoint3 fLightPos;
26 26
27 bool fShowAmbient; 27 bool fShowAmbient;
28 bool fUseAltAmbient;
29 bool fShowSpot; 28 bool fShowSpot;
29 bool fUseAlt;
30 bool fShowObject; 30 bool fShowObject;
31 31
32 public: 32 public:
33 ShadowsView() 33 ShadowsView()
34 : fShowAmbient(true) 34 : fShowAmbient(true)
35 , fUseAltAmbient(true)
36 , fShowSpot(true) 35 , fShowSpot(true)
36 , fUseAlt(true)
37 , fShowObject(true) {} 37 , fShowObject(true) {}
38 38
39 protected: 39 protected:
40 void onOnceBeforeDraw() override { 40 void onOnceBeforeDraw() override {
41 fCirclePath.addCircle(0, 0, 50); 41 fCirclePath.addCircle(0, 0, 50);
42 fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100)); 42 fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100));
43 fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 10 0), 4, 4)); 43 fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 10 0), 4, 4));
44 fLightPos = SkPoint3::Make(-220, -330, 150); 44 fLightPos = SkPoint3::Make(-2, -2, 6);
45 } 45 }
46 46
47 // overrides from SkEventSink 47 // overrides from SkEventSink
48 bool onQuery(SkEvent* evt) override { 48 bool onQuery(SkEvent* evt) override {
49 if (SampleCode::TitleQ(*evt)) { 49 if (SampleCode::TitleQ(*evt)) {
50 SampleCode::TitleR(evt, "AndroidShadows"); 50 SampleCode::TitleR(evt, "AndroidShadows");
51 return true; 51 return true;
52 } 52 }
53 53
54 SkUnichar uni; 54 SkUnichar uni;
55 if (SampleCode::CharQ(*evt, &uni)) { 55 if (SampleCode::CharQ(*evt, &uni)) {
56 switch (uni) { 56 switch (uni) {
57 case 'B': 57 case 'B':
58 fShowAmbient = !fShowAmbient; 58 fShowAmbient = !fShowAmbient;
59 break; 59 break;
60 case 'T':
61 fUseAltAmbient = !fUseAltAmbient;
62 break;
63 case 'S': 60 case 'S':
64 fShowSpot = !fShowSpot; 61 fShowSpot = !fShowSpot;
65 break; 62 break;
63 case 'T':
64 fUseAlt = !fUseAlt;
65 break;
66 case 'O': 66 case 'O':
67 fShowObject = !fShowObject; 67 fShowObject = !fShowObject;
68 break; 68 break;
69 case '>': 69 case '>':
70 fLightPos.fZ += 10; 70 fLightPos.fZ += 10;
71 break; 71 break;
72 case '<': 72 case '<':
73 fLightPos.fZ -= 10; 73 fLightPos.fZ -= 10;
74 break; 74 break;
75 default: 75 default:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 #endif 136 #endif
137 } 137 }
138 138
139 void drawAmbientShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zVa lue, 139 void drawAmbientShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zVa lue,
140 SkScalar ambientAlpha) { 140 SkScalar ambientAlpha) {
141 141
142 if (ambientAlpha <= 0) { 142 if (ambientAlpha <= 0) {
143 return; 143 return;
144 } 144 }
145 145
146 SkRect pathRect;
147 SkRRect pathRRect;
148 if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) & &
149 (!path.isRRect(&pathRRect) || !pathRRect.allCornersCircular()) &&
150 !path.isRect(&pathRect)) {
151 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
152 return;
153 }
154
146 const SkScalar kHeightFactor = 1.f / 128.f; 155 const SkScalar kHeightFactor = 1.f / 128.f;
147 const SkScalar kGeomFactor = 64; 156 const SkScalar kGeomFactor = 64;
148 157
149 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0)); 158 SkScalar umbraAlpha = 1 / (1 + SkMaxScalar(zValue*kHeightFactor, 0));
150 SkScalar radius = zValue*kHeightFactor*kGeomFactor; 159 SkScalar radius = zValue*kHeightFactor*kGeomFactor;
151 160
152 // fast path 161 // For all of these, we outset the rect by the radius to get our coverag e shape.
153 SkRect pathRect; 162 if (path.isOval(nullptr)) {
154 SkRRect pathRRect; 163 pathRect.outset(radius, radius);
155 if ((path.isOval(&pathRect) && pathRect.width() == pathRect.height()) || 164 pathRRect = SkRRect::MakeOval(pathRect);
156 (path.isRRect(&pathRRect) && pathRRect.allCornersCircular()) || 165 } else if (path.isRect(nullptr)) {
157 path.isRect(&pathRect)) { 166 pathRect.outset(radius, radius);
158 167 pathRRect = SkRRect::MakeRectXY(pathRect, radius, radius);
159 // For all of these, we outset the rect by half the radius to get ou r stroke shape.
160 if (path.isOval(nullptr)) {
161 pathRect.outset(0.5f*radius, 0.5f*radius);
162 pathRRect = SkRRect::MakeOval(pathRect);
163 } else if (path.isRect(nullptr)) {
164 pathRect.outset(0.5f*radius, 0.5f*radius);
165 pathRRect = SkRRect::MakeRectXY(pathRect, 0.5f*radius, 0.5f*radi us);
166 } else {
167 pathRRect.outset(0.5f*radius, 0.5f*radius);
168 }
169
170 SkPaint paint;
171 paint.setAntiAlias(true);
172 paint.setColor(SkColorSetARGB((unsigned char)(ambientAlpha*umbraAlph a*255.999f),
173 0, 0, 0));
174 paint.setStrokeWidth(radius);
175 paint.setStyle(SkPaint::kStroke_Style);
176
177 paint.setShader(SkGaussianEdgeShader::Make());
178 canvas->drawRRect(pathRRect, paint);
179 } else { 168 } else {
180 // occlude blur 169 pathRRect.outset(radius, radius);
181 SkRect occlRect;
182 GetOcclRect(path, &occlRect);
183 sk_sp<SkMaskFilter> f = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
184 SkBlurMask::ConvertRa diusToSigma(radius),
185 occlRect,
186 SkBlurMaskFilter::kNo ne_BlurFlag);
187
188 SkPaint paint;
189 paint.setAntiAlias(true);
190 paint.setMaskFilter(std::move(f));
191 paint.setColor(SkColorSetARGB((unsigned char)(ambientAlpha*umbraAlph a*255.999f),
192 0, 0, 0));
193 canvas->drawPath(path, paint);
194
195 // draw occlusion rect
196 #if DRAW_OCCL_RECT
197 SkPaint stroke;
198 stroke.setStyle(SkPaint::kStroke_Style);
199 stroke.setColor(SK_ColorBLUE);
200 canvas->drawRect(occlRect, stroke);
201 #endif
202 } 170 }
203 171
172 SkPaint paint;
173 paint.setAntiAlias(true);
174 // handle scale of radius due to CTM
175 SkScalar maxScale = canvas->getTotalMatrix().getMaxScale();
176 radius *= maxScale;
177 unsigned char gray = (unsigned char)(ambientAlpha*umbraAlpha*255.999f);
178 SkASSERT(radius < 256);
179 // convert the radius to fixed point 8.8 and
180 // place it in the G,B components of the color
181 unsigned char intPart = (unsigned char)radius;
182 SkScalar fracPart = radius - intPart;
183 paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart *256.f)));
184
185 sk_sp<SkShader> gaussShader = std::move(SkGaussianEdgeShader::Make());
186 paint.setShader(gaussShader);
187 canvas->drawRRect(pathRRect, paint);
204 } 188 }
205 189
206 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue, 190 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
207 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) { 191 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) {
208 if (spotAlpha <= 0) { 192 if (spotAlpha <= 0) {
209 return; 193 return;
210 } 194 }
211 195
212 SkScalar zRatio = zValue / (lightPos.fZ - zValue); 196 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
213 if (zRatio < 0.0f) { 197 if (zRatio < 0.0f) {
(...skipping 14 matching lines...) Expand all
228 } else if (scale > 1024.f) { 212 } else if (scale > 1024.f) {
229 scale = 1024.f; 213 scale = 1024.f;
230 } 214 }
231 215
232 SkAutoCanvasRestore acr(canvas, true); 216 SkAutoCanvasRestore acr(canvas, true);
233 217
234 SkRect occlRect; 218 SkRect occlRect;
235 GetOcclRect(path, &occlRect); 219 GetOcclRect(path, &occlRect);
236 // apply inverse transform 220 // apply inverse transform
237 occlRect.offset(-offset); 221 occlRect.offset(-offset);
222 #if 0
223 // It looks like the scale may be invalid
224 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
225 if (scale < 1.0f) {
226 scale = 1.0f;
227 } else if (scale > 1024.f) {
228 scale = 1024.f;
229 }
238 occlRect.fLeft /= scale; 230 occlRect.fLeft /= scale;
239 occlRect.fRight /= scale; 231 occlRect.fRight /= scale;
240 occlRect.fTop /= scale; 232 occlRect.fTop /= scale;
241 occlRect.fBottom /= scale; 233 occlRect.fBottom /= scale;
234 #endif
242 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 235 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
243 SkBlurMask::ConvertRadiu sToSigma(radius), 236 SkBlurMask::ConvertRadiu sToSigma(radius),
244 occlRect, 237 occlRect,
245 SkBlurMaskFilter::kNone_ BlurFlag); 238 SkBlurMaskFilter::kNone_ BlurFlag);
246 239
247 SkPaint paint; 240 SkPaint paint;
248 paint.setAntiAlias(true); 241 paint.setAntiAlias(true);
249 paint.setMaskFilter(std::move(mf)); 242 paint.setMaskFilter(std::move(mf));
250 paint.setColor(SkColorSetARGB((unsigned char)(spotAlpha*255.999f), 0, 0, 0)); 243 paint.setColor(SkColorSetARGB((unsigned char)(spotAlpha*255.999f), 0, 0, 0));
251 244
252 // apply transformation to shadow 245 // apply transformation to shadow
253 canvas->translate(offset.fX, offset.fY); 246 canvas->translate(offset.fX, offset.fY);
247 #if 0
248 // It looks like the scale may be invalid
254 canvas->scale(scale, scale); 249 canvas->scale(scale, scale);
250 #endif
255 canvas->drawPath(path, paint); 251 canvas->drawPath(path, paint);
256 252
257 // draw occlusion rect 253 // draw occlusion rect
258 #if DRAW_OCCL_RECT 254 #if DRAW_OCCL_RECT
259 SkPaint stroke; 255 SkPaint stroke;
260 stroke.setStyle(SkPaint::kStroke_Style); 256 stroke.setStyle(SkPaint::kStroke_Style);
261 stroke.setColor(SK_ColorRED); 257 stroke.setColor(SK_ColorRED);
262 canvas->drawRect(occlRect, stroke) 258 canvas->drawRect(occlRect, stroke)
263 #endif 259 #endif
264 } 260 }
265 261
266 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue, 262 void drawSpotShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue ,
267 const SkPaint& paint) { 263 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) {
268 const SkScalar kLightWidth = 3; 264 if (spotAlpha <= 0) {
269 const SkScalar kAmbientAlpha = 0.25f; 265 return;
270 const SkScalar kSpotAlpha = 0.25f; 266 }
271 267
268 SkRect pathRect;
269 SkRRect pathRRect;
270 if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) & &
271 (!path.isRRect(&pathRRect) || !pathRRect.allCornersCircular()) &&
272 !path.isRect(&pathRect)) {
273 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spo tAlpha);
274 return;
275 }
276
277 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
278 if (zRatio < 0.0f) {
279 zRatio = 0.0f;
280 } else if (zRatio > 0.95f) {
281 zRatio = 0.95f;
282 }
283 SkScalar radius = lightWidth*zRatio;
284
285 // For all of these, we outset the rect by the radius to get our coverag e shape.
286 if (path.isOval(nullptr)) {
287 pathRect.outset(radius, radius);
288 pathRRect = SkRRect::MakeOval(pathRect);
289 } else if (path.isRect(nullptr)) {
290 pathRect.outset(radius, radius);
291 pathRRect = SkRRect::MakeRectXY(pathRect, radius, radius);
292 } else {
293 pathRRect.outset(radius, radius);
294 }
295
296 // compute the transformation params
297 SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBound s().centerY());
298 canvas->getTotalMatrix().mapPoints(&center, 1);
299 SkPoint offset = SkPoint::Make(-zRatio*(lightPos.fX - center.fX),
300 -zRatio*(lightPos.fY - center.fY));
301 SkAutoCanvasRestore acr(canvas, true);
302
303 SkPaint paint;
304 paint.setAntiAlias(true);
305 sk_sp<SkShader> gaussShader = std::move(SkGaussianEdgeShader::Make());
306 paint.setShader(gaussShader);
307 // handle scale of radius due to CTM
308 SkScalar maxScale = canvas->getTotalMatrix().getMaxScale();
309 radius *= maxScale;
310 unsigned char gray = (unsigned char)(spotAlpha*255.999f);
311 SkASSERT(radius < 256);
312 // convert the radius to fixed point 8.8 and
313 // place it in the G,B components of the color
314 unsigned char intPart = (unsigned char)radius;
315 SkScalar fracPart = radius - intPart;
316 paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart *256.f)));
317
318 // apply transformation to shadow
319 canvas->translate(offset.fX, offset.fY);
320 #if 0
321 // It looks like the scale may be invalid
322 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
323 if (scale < 1.0f) {
324 scale = 1.0f;
325 } else if (scale > 1024.f) {
326 scale = 1024.f;
327 }
328 canvas->scale(scale, scale);
329 #endif
330 canvas->drawRRect(pathRRect, paint);
331 }
332
333 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
334 const SkPaint& paint, SkScalar ambientAlpha,
335 const SkPoint3& lightPos, SkScalar lightWidth, SkScala r spotAlpha) {
272 if (fShowAmbient) { 336 if (fShowAmbient) {
273 if (fUseAltAmbient) { 337 if (fUseAlt) {
274 this->drawAmbientShadowAlt(canvas, path, zValue, kAmbientAlpha); 338 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
275 } else { 339 } else {
276 this->drawAmbientShadow(canvas, path, zValue, kAmbientAlpha); 340 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
277 } 341 }
278 } 342 }
279 if (fShowSpot) { 343 if (fShowSpot) {
280 this->drawSpotShadow(canvas, path, zValue, fLightPos, kLightWidth, k SpotAlpha); 344 if (fUseAlt) {
345 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWid th, spotAlpha);
346 } else {
347 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
348 }
281 } 349 }
282 if (fShowObject) { 350 if (fShowObject) {
283 canvas->drawPath(path, paint); 351 canvas->drawPath(path, paint);
284 } 352 }
285 } 353 }
286 354
287 void onDrawContent(SkCanvas* canvas) override { 355 void onDrawContent(SkCanvas* canvas) override {
288 this->drawBG(canvas); 356 this->drawBG(canvas);
357 const SkScalar kLightWidth = 3;
358 const SkScalar kAmbientAlpha = 0.25f;
359 const SkScalar kSpotAlpha = 0.25f;
289 360
290 SkPaint paint; 361 SkPaint paint;
291 paint.setAntiAlias(true); 362 paint.setAntiAlias(true);
292 363
364 SkPoint3 lightPos = fLightPos;
365
293 paint.setColor(SK_ColorWHITE); 366 paint.setColor(SK_ColorWHITE);
294 canvas->translate(200, 90); 367 canvas->translate(200, 90);
295 this->drawShadowedPath(canvas, fRectPath, 5, paint); 368 lightPos.fX += 200;
369 lightPos.fY += 90;
370 this->drawShadowedPath(canvas, fRectPath, 5, paint, kAmbientAlpha,
371 lightPos, kLightWidth, kSpotAlpha);
296 372
297 paint.setColor(SK_ColorRED); 373 paint.setColor(SK_ColorRED);
298 canvas->translate(250, 0); 374 canvas->translate(250, 0);
299 this->drawShadowedPath(canvas, fRRPath, 5, paint); 375 lightPos.fX += 250;
376 this->drawShadowedPath(canvas, fRRPath, 5, paint, kAmbientAlpha,
377 lightPos, kLightWidth, kSpotAlpha);
300 378
301 paint.setColor(SK_ColorBLUE); 379 paint.setColor(SK_ColorBLUE);
302 canvas->translate(-250, 110); 380 canvas->translate(-250, 110);
303 this->drawShadowedPath(canvas, fCirclePath, 5, paint); 381 lightPos.fX -= 250;
382 lightPos.fY += 110;
383 this->drawShadowedPath(canvas, fCirclePath, 5, paint, 0.0f,
384 lightPos, kLightWidth, 0.5f);
304 385
305 paint.setColor(SK_ColorGREEN); 386 paint.setColor(SK_ColorGREEN);
306 canvas->translate(250, 0); 387 canvas->translate(250, 0);
307 this->drawShadowedPath(canvas, fRRPath, 5, paint); 388 lightPos.fX += 250;
389 this->drawShadowedPath(canvas, fRRPath, 5, paint, kAmbientAlpha,
390 lightPos, kLightWidth, kSpotAlpha);
308 } 391 }
309 392
310 protected: 393 protected:
311 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { 394 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride {
312 return new SkView::Click(this); 395 return new SkView::Click(this);
313 } 396 }
314 397
315 bool onClick(Click *click) override { 398 bool onClick(Click *click) override {
316 SkScalar x = click->fCurr.fX; 399 SkScalar x = click->fCurr.fX;
317 SkScalar y = click->fCurr.fY; 400 SkScalar y = click->fCurr.fY;
(...skipping 11 matching lines...) Expand all
329 } 412 }
330 413
331 private: 414 private:
332 typedef SkView INHERITED; 415 typedef SkView INHERITED;
333 }; 416 };
334 417
335 ////////////////////////////////////////////////////////////////////////////// 418 //////////////////////////////////////////////////////////////////////////////
336 419
337 static SkView* MyFactory() { return new ShadowsView; } 420 static SkView* MyFactory() { return new ShadowsView; }
338 static SkViewRegister reg(MyFactory); 421 static SkViewRegister reg(MyFactory);
OLDNEW
« no previous file with comments | « no previous file | src/effects/SkGaussianEdgeShader.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698