1 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 "include/core/SkCanvas.h" 9 #include "include/core/SkColorFilter.h" 10 #include "include/core/SkPath.h" 11 #include "include/core/SkPoint3.h" 12 #include "include/core/SkRRect.h" 13 #include "include/pathops/SkPathOps.h" 14 #include "include/utils/SkCamera.h" 15 #include "include/utils/SkShadowUtils.h" 16 #include "src/base/SkUTF.h" 17 #include "src/core/SkBlurMask.h" 18 #include "tools/ToolUtils.h" 19 #include "tools/timer/TimeUtils.h" 20 #include "tools/viewer/Slide.h" 21 22 //////////////////////////////////////////////////////////////////////////// 23 24 class ShadowsSlide : public Slide { 25 SkPath fRectPath; 26 SkPath fRRPath; 27 SkPath fCirclePath; 28 SkPath fFunkyRRPath; 29 SkPath fCubicPath; 30 SkPath fStarPath; 31 SkPath fSquareRRectPath; 32 SkPath fWideRectPath; 33 SkPath fWideOvalPath; 34 SkPath fNotchPath; 35 SkPath fTabPath; 36 37 SkPoint3 fLightPos; 38 SkScalar fZDelta = 0; 39 SkScalar fAnimTranslate = 0; 40 SkScalar fAnimAngle = 0; 41 SkScalar fAnimAlpha = 1; 42 43 bool fShowAmbient = true; 44 bool fShowSpot = true; 45 bool fUseAlt = false; 46 bool fUseBlur = true; 47 bool fShowObject = true; 48 bool fIgnoreShadowAlpha = false; 49 bool fDoAlphaAnimation = false; 50 51 public: ShadowsSlide()52 ShadowsSlide() { fName = "AndroidShadows"; } 53 load(SkScalar w,SkScalar h)54 void load(SkScalar w, SkScalar h) override { 55 fCirclePath.addCircle(0, 0, 50); 56 fRectPath.addRect(SkRect::MakeXYWH(-100, -50, 200, 100)); 57 fRRPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-100, -50, 200, 100), 4, 4)); 58 fFunkyRRPath.addRoundRect(SkRect::MakeXYWH(-50, -50, SK_Scalar1 * 100, SK_Scalar1 * 100), 59 40 * SK_Scalar1, 20 * SK_Scalar1, 60 SkPathDirection::kCW); 61 fCubicPath.cubicTo(100 * SK_Scalar1, 50 * SK_Scalar1, 62 20 * SK_Scalar1, 100 * SK_Scalar1, 63 0 * SK_Scalar1, 0 * SK_Scalar1); 64 fStarPath.moveTo(0.0f, -50.0f); 65 fStarPath.lineTo(14.43f, -25.0f); 66 fStarPath.lineTo(43.30f, -25.0f); 67 fStarPath.lineTo(28.86f, 0.0f); 68 fStarPath.lineTo(43.30f, 25.0f); 69 fStarPath.lineTo(14.43f, 25.0f); 70 fStarPath.lineTo(0.0f, 50.0f); 71 fStarPath.lineTo(-14.43f, 25.0f); 72 fStarPath.lineTo(-43.30f, 25.0f); 73 fStarPath.lineTo(-28.86f, 0.0f); 74 fStarPath.lineTo(-43.30f, -25.0f); 75 fStarPath.lineTo(-14.43f, -25.0f); 76 fSquareRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-50, -50, 100, 100), 77 10, 10)); 78 fWideRectPath.addRect(SkRect::MakeXYWH(0, 0, 630, 70)); 79 fWideOvalPath.addOval(SkRect::MakeXYWH(0, 0, 630, 70)); 80 81 fNotchPath.moveTo(0, 80); 82 fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), -90, -90, false); 83 fNotchPath.lineTo(-75, 100); 84 fNotchPath.lineTo(-75, -100); 85 fNotchPath.lineTo(75, -100); 86 fNotchPath.lineTo(75, 100); 87 fNotchPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, -90, false); 88 89 fTabPath.moveTo(-75, -100); 90 fTabPath.lineTo(75, -100); 91 fTabPath.lineTo(75, 100); 92 fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 0, 90, false); 93 fTabPath.arcTo(SkRect::MakeLTRB(-20, 80, 20, 120), 90, 90, false); 94 fTabPath.lineTo(-75, 100); 95 96 fLightPos = SkPoint3::Make(350, 0, 600); 97 } 98 onChar(SkUnichar uni)99 bool onChar(SkUnichar uni) override { 100 bool handled = false; 101 switch (uni) { 102 case 'W': 103 fShowAmbient = !fShowAmbient; 104 handled = true; 105 break; 106 case 'S': 107 fShowSpot = !fShowSpot; 108 handled = true; 109 break; 110 case 'T': 111 fUseAlt = !fUseAlt; 112 handled = true; 113 break; 114 case 'B': 115 fUseBlur = !fUseBlur; 116 handled = true; 117 break; 118 case 'O': 119 fShowObject = !fShowObject; 120 handled = true; 121 break; 122 case 'N': 123 fDoAlphaAnimation = !fDoAlphaAnimation; 124 if (!fDoAlphaAnimation) { 125 fAnimAlpha = 1; 126 } 127 handled = true; 128 break; 129 case '>': 130 fZDelta += 0.5f; 131 handled = true; 132 break; 133 case '<': 134 fZDelta -= 0.5f; 135 handled = true; 136 break; 137 case '?': 138 fIgnoreShadowAlpha = !fIgnoreShadowAlpha; 139 handled = true; 140 break; 141 default: 142 break; 143 } 144 if (handled) { 145 return true; 146 } 147 return false; 148 } 149 150 animate(double nanos)151 bool animate(double nanos) override { 152 fAnimTranslate = TimeUtils::PingPong(1e-9 * nanos, 30, 0, 125, -125); 153 fAnimAngle = TimeUtils::PingPong(1e-9 * nanos, 15, 0, 0, 20); 154 if (fDoAlphaAnimation) { 155 fAnimAlpha = TimeUtils::PingPong(1e-9 * nanos, 5, 0, 1, 0); 156 } 157 return true; 158 } 159 draw(SkCanvas * canvas)160 void draw(SkCanvas* canvas) override { 161 canvas->drawColor(0xFFDDDDDD); 162 163 const SkScalar kLightWidth = 800; 164 const SkScalar kAmbientAlpha = 0.039f; 165 const SkScalar kSpotAlpha = 0.19f; 166 167 SkPaint paint; 168 paint.setAntiAlias(true); 169 170 SkPoint3 lightPos = fLightPos; 171 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, 0); 172 173 paint.setColor(SK_ColorWHITE); 174 canvas->translate(200, 90); 175 zPlaneParams.fZ = std::max(1.0f, 2 + fZDelta); 176 this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 177 lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); 178 179 paint.setColor(SK_ColorRED); 180 canvas->translate(250, 0); 181 zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta); 182 this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 183 lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); 184 185 paint.setColor(SK_ColorBLUE); 186 canvas->translate(-250, 110); 187 zPlaneParams.fZ = std::max(1.0f, 12 + fZDelta); 188 this->drawShadowedPath(canvas, fCirclePath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 189 lightPos, kLightWidth, fAnimAlpha*0.5f); 190 191 paint.setColor(SK_ColorGREEN); 192 canvas->translate(250, 0); 193 zPlaneParams.fZ = std::max(1.0f, 64 + fZDelta); 194 this->drawShadowedPath(canvas, fRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 195 lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); 196 197 paint.setColor(SK_ColorYELLOW); 198 canvas->translate(-250, 110); 199 zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta); 200 this->drawShadowedPath(canvas, fFunkyRRPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 201 lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); 202 203 paint.setColor(SK_ColorCYAN); 204 canvas->translate(250, 0); 205 zPlaneParams.fZ = std::max(1.0f, 16 + fZDelta); 206 this->drawShadowedPath(canvas, fCubicPath, zPlaneParams, paint, fAnimAlpha*kAmbientAlpha, 207 lightPos, kLightWidth, fAnimAlpha*kSpotAlpha); 208 209 paint.setColor(SK_ColorWHITE); 210 canvas->translate(250, -180); 211 zPlaneParams.fZ = std::max(1.0f, 8 + fZDelta); 212 this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, 213 kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); 214 215 paint.setColor(SK_ColorWHITE); 216 canvas->translate(150, 0); 217 zPlaneParams.fZ = std::max(1.0f, 2 + fZDelta); 218 this->drawShadowedPath(canvas, fNotchPath, zPlaneParams, paint, 219 kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); 220 221 paint.setColor(SK_ColorWHITE); 222 canvas->translate(200, 0); 223 zPlaneParams.fZ = std::max(1.0f, 16 + fZDelta); 224 this->drawShadowedPath(canvas, fTabPath, zPlaneParams, paint, 225 kAmbientAlpha, lightPos, kLightWidth, kSpotAlpha); 226 227 // circular reveal 228 SkPath tmpPath; 229 SkPath tmpClipPath; 230 tmpClipPath.addCircle(fAnimTranslate, 0, 60); 231 Op(fSquareRRectPath, tmpClipPath, kIntersect_SkPathOp, &tmpPath); 232 233 paint.setColor(SK_ColorMAGENTA); 234 canvas->translate(-725, 240); 235 zPlaneParams.fZ = std::max(1.0f, 32 + fZDelta); 236 this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f, 237 lightPos, kLightWidth, .5f); 238 239 // path ops bug 240 SkPath tmpClipPathBug; 241 tmpClipPathBug.addCircle(88.0344925f, 0, 60); 242 Op(fSquareRRectPath, tmpClipPathBug, kIntersect_SkPathOp, &tmpPath); 243 244 canvas->translate(250, 0); 245 zPlaneParams.fZ = std::max(1.0f, 32 + fZDelta); 246 this->drawShadowedPath(canvas, tmpPath, zPlaneParams, paint, .1f, 247 lightPos, kLightWidth, .5f); 248 249 // perspective paths 250 SkPoint pivot = SkPoint::Make(fWideRectPath.getBounds().width()/2, 251 fWideRectPath.getBounds().height()/2); 252 SkPoint translate = SkPoint::Make(100, 450); 253 paint.setColor(SK_ColorWHITE); 254 Sk3DView view; 255 view.save(); 256 view.rotateX(fAnimAngle); 257 SkMatrix persp; 258 view.getMatrix(&persp); 259 persp.preTranslate(-pivot.fX, -pivot.fY); 260 persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); 261 canvas->setMatrix(persp); 262 SkScalar radians = SkDegreesToRadians(fAnimAngle); 263 zPlaneParams = SkPoint3::Make(0, 264 SkScalarSin(radians), 265 std::max(1.0f, 16 + fZDelta) - SkScalarSin(radians)*pivot.fY); 266 this->drawShadowedPath(canvas, fWideRectPath, zPlaneParams, paint, .1f, 267 lightPos, kLightWidth, .5f); 268 269 pivot = SkPoint::Make(fWideOvalPath.getBounds().width() / 2, 270 fWideOvalPath.getBounds().height() / 2); 271 translate = SkPoint::Make(100, 600); 272 view.restore(); 273 view.save(); 274 view.rotateY(fAnimAngle); 275 view.getMatrix(&persp); 276 persp.preTranslate(-pivot.fX, -pivot.fY); 277 persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); 278 canvas->setMatrix(persp); 279 zPlaneParams = SkPoint3::Make(-SkScalarSin(radians), 280 0, 281 std::max(1.0f, 32 + fZDelta) + SkScalarSin(radians)*pivot.fX); 282 this->drawShadowedPath(canvas, fWideOvalPath, zPlaneParams, paint, .1f, 283 lightPos, kLightWidth, .5f); 284 285 pivot = SkPoint::Make(fStarPath.getBounds().width() / 2, 286 fStarPath.getBounds().height() / 2); 287 translate = SkPoint::Make(700, 250); 288 view.restore(); 289 view.rotateY(fAnimAngle); 290 view.getMatrix(&persp); 291 persp.preTranslate(-pivot.fX, -pivot.fY); 292 persp.postTranslate(pivot.fX + translate.fX, pivot.fY + translate.fY); 293 canvas->setMatrix(persp); 294 zPlaneParams = SkPoint3::Make(-SkScalarSin(radians), 295 0, 296 std::max(1.0f, 8 + fZDelta) + SkScalarSin(radians)*pivot.fX); 297 this->drawShadowedPath(canvas, fStarPath, zPlaneParams, paint, .1f, 298 lightPos, kLightWidth, .5f); 299 } 300 301 private: drawShadowedPath(SkCanvas * canvas,const SkPath & path,const SkPoint3 & zPlaneParams,const SkPaint & paint,SkScalar ambientAlpha,const SkPoint3 & lightPos,SkScalar lightWidth,SkScalar spotAlpha)302 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, 303 const SkPoint3& zPlaneParams, 304 const SkPaint& paint, SkScalar ambientAlpha, 305 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { 306 if (fIgnoreShadowAlpha) { 307 ambientAlpha = 1; 308 spotAlpha = 1; 309 } 310 if (!fShowAmbient) { 311 ambientAlpha = 0; 312 } 313 if (!fShowSpot) { 314 spotAlpha = 0; 315 } 316 uint32_t flags = 0; 317 if (fUseAlt) { 318 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; 319 } 320 if (fUseBlur) { 321 flags |= SkShadowFlags::kConcaveBlurOnly_ShadowFlag; 322 } 323 324 SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0); 325 SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0); 326 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, 327 ambientColor, spotColor, flags); 328 329 if (fShowObject) { 330 canvas->drawPath(path, paint); 331 } else { 332 SkPaint strokePaint; 333 334 strokePaint.setColor(paint.getColor()); 335 strokePaint.setStyle(SkPaint::kStroke_Style); 336 337 canvas->drawPath(path, strokePaint); 338 } 339 } 340 }; 341 342 ////////////////////////////////////////////////////////////////////////////// 343 344 DEF_SLIDE( return new ShadowsSlide(); ) 345