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

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: 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)) {
robertphillips 2016/08/17 15:44:40 this-> ?
jvanverth1 2016/08/17 16:19:27 Done.
151 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
robertphillips 2016/08/17 15:44:39 stroke shape -> "coverage" RRect ?
jvanverth1 2016/08/17 16:19:28 Done. And thanks -- there was a bug here.
152 // fast path 161 // For all of these, we outset the rect by half the radius to get our st roke shape.
153 SkRect pathRect; 162 if (path.isOval(nullptr)) {
154 SkRRect pathRRect; 163 pathRect.outset(0.5f*radius, 0.5f*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(0.5f*radius, 0.5f*radius);
158 167 pathRRect = SkRRect::MakeRectXY(pathRect, 0.5f*radius, 0.5f*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(0.5f*radius, 0.5f*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;
robertphillips 2016/08/17 15:44:40 Can this be BW ? Does that give us any advantage ?
jvanverth1 2016/08/17 16:19:27 No, it can't. We need the anti-aliased rrect rende
173 paint.setAntiAlias(true);
174 // TODO: handle scale of radius due to CTM
175 unsigned char gray = (unsigned char)(ambientAlpha*umbraAlpha*255.999f);
robertphillips 2016/08/17 15:44:39 // convert the radius to fixed point 8.8 & place i
jvanverth1 2016/08/17 16:19:28 Done.
176 SkASSERT(radius < 256);
177 unsigned char intPart = (unsigned char)radius;
178 SkScalar fracPart = radius - intPart;
179 paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart *256.f)));
180
181 sk_sp<SkShader> gaussShader = std::move(SkGaussianEdgeShader::Make());
182 paint.setShader(gaussShader);
183 canvas->drawRRect(pathRRect, paint);
204 } 184 }
205 185
206 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue, 186 void drawSpotShadow(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
207 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) { 187 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) {
208 if (spotAlpha <= 0) { 188 if (spotAlpha <= 0) {
209 return; 189 return;
210 } 190 }
211 191
212 SkScalar zRatio = zValue / (lightPos.fZ - zValue); 192 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
213 if (zRatio < 0.0f) { 193 if (zRatio < 0.0f) {
(...skipping 14 matching lines...) Expand all
228 } else if (scale > 1024.f) { 208 } else if (scale > 1024.f) {
229 scale = 1024.f; 209 scale = 1024.f;
230 } 210 }
231 211
232 SkAutoCanvasRestore acr(canvas, true); 212 SkAutoCanvasRestore acr(canvas, true);
233 213
234 SkRect occlRect; 214 SkRect occlRect;
235 GetOcclRect(path, &occlRect); 215 GetOcclRect(path, &occlRect);
236 // apply inverse transform 216 // apply inverse transform
237 occlRect.offset(-offset); 217 occlRect.offset(-offset);
218 #if 0
219 // It looks like the scale may be invalid
220 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
221 if (scale < 1.0f) {
222 scale = 1.0f;
223 } else if (scale > 1024.f) {
224 scale = 1024.f;
225 }
238 occlRect.fLeft /= scale; 226 occlRect.fLeft /= scale;
239 occlRect.fRight /= scale; 227 occlRect.fRight /= scale;
240 occlRect.fTop /= scale; 228 occlRect.fTop /= scale;
241 occlRect.fBottom /= scale; 229 occlRect.fBottom /= scale;
230 #endif
242 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle, 231 sk_sp<SkMaskFilter> mf = SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
243 SkBlurMask::ConvertRadiu sToSigma(radius), 232 SkBlurMask::ConvertRadiu sToSigma(radius),
244 occlRect, 233 occlRect,
245 SkBlurMaskFilter::kNone_ BlurFlag); 234 SkBlurMaskFilter::kNone_ BlurFlag);
246 235
247 SkPaint paint; 236 SkPaint paint;
248 paint.setAntiAlias(true); 237 paint.setAntiAlias(true);
249 paint.setMaskFilter(std::move(mf)); 238 paint.setMaskFilter(std::move(mf));
250 paint.setColor(SkColorSetARGB((unsigned char)(spotAlpha*255.999f), 0, 0, 0)); 239 paint.setColor(SkColorSetARGB((unsigned char)(spotAlpha*255.999f), 0, 0, 0));
251 240
252 // apply transformation to shadow 241 // apply transformation to shadow
253 canvas->translate(offset.fX, offset.fY); 242 canvas->translate(offset.fX, offset.fY);
243 #if 0
244 // It looks like the scale may be invalid
254 canvas->scale(scale, scale); 245 canvas->scale(scale, scale);
246 #endif
255 canvas->drawPath(path, paint); 247 canvas->drawPath(path, paint);
256 248
257 // draw occlusion rect 249 // draw occlusion rect
258 #if DRAW_OCCL_RECT 250 #if DRAW_OCCL_RECT
259 SkPaint stroke; 251 SkPaint stroke;
260 stroke.setStyle(SkPaint::kStroke_Style); 252 stroke.setStyle(SkPaint::kStroke_Style);
261 stroke.setColor(SK_ColorRED); 253 stroke.setColor(SK_ColorRED);
262 canvas->drawRect(occlRect, stroke) 254 canvas->drawRect(occlRect, stroke)
263 #endif 255 #endif
264 } 256 }
265 257
266 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue, 258 void drawSpotShadowAlt(SkCanvas* canvas, const SkPath& path, SkScalar zValue ,
267 const SkPaint& paint) { 259 SkPoint3 lightPos, SkScalar lightWidth, SkScalar spotAlp ha) {
268 const SkScalar kLightWidth = 3; 260 if (spotAlpha <= 0) {
269 const SkScalar kAmbientAlpha = 0.25f; 261 return;
270 const SkScalar kSpotAlpha = 0.25f; 262 }
271 263
264 SkRect pathRect;
265 SkRRect pathRRect;
266 if ((!path.isOval(&pathRect) || pathRect.width() != pathRect.height()) & &
267 (!path.isRRect(&pathRRect) || !pathRRect.allCornersCircular()) &&
268 !path.isRect(&pathRect)) {
robertphillips 2016/08/17 15:44:39 this->
jvanverth1 2016/08/17 16:19:28 Done.
269 drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha );
270 return;
271 }
272
273 SkScalar zRatio = zValue / (lightPos.fZ - zValue);
274 if (zRatio < 0.0f) {
275 zRatio = 0.0f;
276 } else if (zRatio > 0.95f) {
277 zRatio = 0.95f;
278 }
279 SkScalar radius = lightWidth*zRatio;
280
281 // For all of these, we outset the rect by half the radius to get our st roke shape.
282 if (path.isOval(nullptr)) {
283 pathRect.outset(0.5f*radius, 0.5f*radius);
284 pathRRect = SkRRect::MakeOval(pathRect);
285 } else if (path.isRect(nullptr)) {
286 pathRect.outset(0.5f*radius, 0.5f*radius);
287 pathRRect = SkRRect::MakeRectXY(pathRect, 0.5f*radius, 0.5f*radius);
288 } else {
289 pathRRect.outset(0.5f*radius, 0.5f*radius);
290 }
291
292 // compute the transformation params
293 SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBound s().centerY());
294 canvas->getTotalMatrix().mapPoints(&center, 1);
295 SkPoint offset = SkPoint::Make(-zRatio*(lightPos.fX - center.fX),
296 -zRatio*(lightPos.fY - center.fY));
297 SkAutoCanvasRestore acr(canvas, true);
298
299 SkPaint paint;
robertphillips 2016/08/17 15:44:40 same Q here
jvanverth1 2016/08/17 16:19:28 Same answer. :-)
300 paint.setAntiAlias(true);
301 sk_sp<SkShader> gaussShader = std::move(SkGaussianEdgeShader::Make());
302 paint.setShader(gaussShader);
robertphillips 2016/08/17 15:44:40 Maybe make_super_color(grey, radius) ?
jvanverth1 2016/08/17 16:19:27 Good idea, I'll add something like that to SkGauss
303 // TODO: handle scale of radius due to CTM
304 unsigned char gray = (unsigned char)(spotAlpha*255.999f);
305 SkASSERT(radius < 256);
306 unsigned char intPart = (unsigned char)radius;
307 SkScalar fracPart = radius - intPart;
308 paint.setColor(SkColorSetARGB(1, gray, intPart, (unsigned char)(fracPart *256.f)));
309
310 // apply transformation to shadow
311 canvas->translate(offset.fX, offset.fY);
312 #if 0
313 // It looks like the scale may be invalid
314 SkScalar scale = lightPos.fZ / (lightPos.fZ - zValue);
315 if (scale < 1.0f) {
316 scale = 1.0f;
317 } else if (scale > 1024.f) {
318 scale = 1024.f;
319 }
320 canvas->scale(scale, scale);
321 #endif
322 canvas->drawRRect(pathRRect, paint);
323 }
324
325 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, SkScalar zValue,
326 const SkPaint& paint, SkScalar ambientAlpha,
327 const SkPoint3& lightPos, SkScalar lightWidth, SkScala r spotAlpha) {
272 if (fShowAmbient) { 328 if (fShowAmbient) {
273 if (fUseAltAmbient) { 329 if (fUseAlt) {
274 this->drawAmbientShadowAlt(canvas, path, zValue, kAmbientAlpha); 330 this->drawAmbientShadowAlt(canvas, path, zValue, ambientAlpha);
275 } else { 331 } else {
276 this->drawAmbientShadow(canvas, path, zValue, kAmbientAlpha); 332 this->drawAmbientShadow(canvas, path, zValue, ambientAlpha);
277 } 333 }
278 } 334 }
279 if (fShowSpot) { 335 if (fShowSpot) {
280 this->drawSpotShadow(canvas, path, zValue, fLightPos, kLightWidth, k SpotAlpha); 336 if (fUseAlt) {
337 this->drawSpotShadowAlt(canvas, path, zValue, lightPos, lightWid th, spotAlpha);
338 } else {
339 this->drawSpotShadow(canvas, path, zValue, lightPos, lightWidth, spotAlpha);
340 }
281 } 341 }
282 if (fShowObject) { 342 if (fShowObject) {
283 canvas->drawPath(path, paint); 343 canvas->drawPath(path, paint);
284 } 344 }
285 } 345 }
286 346
287 void onDrawContent(SkCanvas* canvas) override { 347 void onDrawContent(SkCanvas* canvas) override {
288 this->drawBG(canvas); 348 this->drawBG(canvas);
349 const SkScalar kLightWidth = 6;
350 const SkScalar kAmbientAlpha = 0.25f;
351 const SkScalar kSpotAlpha = 0.25f;
289 352
290 SkPaint paint; 353 SkPaint paint;
291 paint.setAntiAlias(true); 354 paint.setAntiAlias(true);
292 355
356 SkPoint3 lightPos = fLightPos;
357
293 paint.setColor(SK_ColorWHITE); 358 paint.setColor(SK_ColorWHITE);
294 canvas->translate(200, 90); 359 canvas->translate(200, 90);
295 this->drawShadowedPath(canvas, fRectPath, 5, paint); 360 lightPos.fX += 200;
361 lightPos.fY += 90;
362 this->drawShadowedPath(canvas, fRectPath, 5, paint, kAmbientAlpha,
363 lightPos, kLightWidth, kSpotAlpha);
296 364
297 paint.setColor(SK_ColorRED); 365 paint.setColor(SK_ColorRED);
298 canvas->translate(250, 0); 366 canvas->translate(250, 0);
299 this->drawShadowedPath(canvas, fRRPath, 5, paint); 367 lightPos.fX += 250;
368 this->drawShadowedPath(canvas, fRRPath, 5, paint, kAmbientAlpha,
369 lightPos, kLightWidth, kSpotAlpha);
300 370
301 paint.setColor(SK_ColorBLUE); 371 paint.setColor(SK_ColorBLUE);
302 canvas->translate(-250, 110); 372 canvas->translate(-250, 110);
303 this->drawShadowedPath(canvas, fCirclePath, 5, paint); 373 lightPos.fX -= 250;
374 lightPos.fY += 110;
375 this->drawShadowedPath(canvas, fCirclePath, 5, paint, 0.0f,
376 lightPos, kLightWidth, 0.5f);
304 377
305 paint.setColor(SK_ColorGREEN); 378 paint.setColor(SK_ColorGREEN);
306 canvas->translate(250, 0); 379 canvas->translate(250, 0);
307 this->drawShadowedPath(canvas, fRRPath, 5, paint); 380 lightPos.fX += 250;
381 this->drawShadowedPath(canvas, fRRPath, 5, paint, kAmbientAlpha,
382 lightPos, kLightWidth, kSpotAlpha);
308 } 383 }
309 384
310 protected: 385 protected:
311 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride { 386 SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) ove rride {
312 return new SkView::Click(this); 387 return new SkView::Click(this);
313 } 388 }
314 389
315 bool onClick(Click *click) override { 390 bool onClick(Click *click) override {
316 SkScalar x = click->fCurr.fX; 391 SkScalar x = click->fCurr.fX;
317 SkScalar y = click->fCurr.fY; 392 SkScalar y = click->fCurr.fY;
(...skipping 11 matching lines...) Expand all
329 } 404 }
330 405
331 private: 406 private:
332 typedef SkView INHERITED; 407 typedef SkView INHERITED;
333 }; 408 };
334 409
335 ////////////////////////////////////////////////////////////////////////////// 410 //////////////////////////////////////////////////////////////////////////////
336 411
337 static SkView* MyFactory() { return new ShadowsView; } 412 static SkView* MyFactory() { return new ShadowsView; }
338 static SkViewRegister reg(MyFactory); 413 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