1 2 /* 3 * Copyright 2017 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/SkImage.h" 10 #include "include/core/SkPath.h" 11 #include "include/core/SkPoint3.h" 12 #include "include/core/SkRRect.h" 13 #include "include/utils/SkShadowUtils.h" 14 #include "tools/Resources.h" 15 #include "tools/viewer/Slide.h" 16 17 //////////////////////////////////////////////////////////////////////////// 18 // Sample to compare the Material Design shadow reference to our results 19 20 class ShadowRefSlide : public Slide { 21 SkPath fRRectPath; 22 sk_sp<SkImage> fReferenceImage; 23 24 bool fShowAmbient; 25 bool fShowSpot; 26 bool fUseAlt; 27 bool fShowObject; 28 29 public: ShadowRefSlide()30 ShadowRefSlide() 31 : fShowAmbient(true) 32 , fShowSpot(true) 33 , fUseAlt(false) 34 , fShowObject(true) { 35 fName = "ShadowReference"; 36 } 37 load(SkScalar w,SkScalar h)38 void load(SkScalar w, SkScalar h) override { 39 fRRectPath.addRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(-130, -128.5, 130, 128.5), 4, 4)); 40 fReferenceImage = GetResourceAsImage("images/shadowreference.png"); 41 } 42 onChar(SkUnichar uni)43 bool onChar(SkUnichar uni) override { 44 bool handled = false; 45 switch (uni) { 46 case 'W': 47 fShowAmbient = !fShowAmbient; 48 handled = true; 49 break; 50 case 'S': 51 fShowSpot = !fShowSpot; 52 handled = true; 53 break; 54 case 'T': 55 fUseAlt = !fUseAlt; 56 handled = true; 57 break; 58 case 'O': 59 fShowObject = !fShowObject; 60 handled = true; 61 break; 62 default: 63 break; 64 } 65 if (handled) { 66 return true; 67 } 68 return false; 69 } 70 draw(SkCanvas * canvas)71 void draw(SkCanvas* canvas) override { 72 this->drawBG(canvas); 73 const SkScalar kDP = 4; // the reference image is 4x bigger than it is displayed on 74 // on the web page, so we need to reflect that here and 75 // multiply the heights and light params accordingly 76 const SkScalar kLightWidth = kDP*400; 77 const SkScalar kAmbientAlpha = 0.03f; 78 const SkScalar kSpotAlpha = 0.35f; 79 80 SkPaint paint; 81 paint.setAntiAlias(true); 82 paint.setColor(SK_ColorWHITE); 83 84 SkPoint3 lightPos = { 175, -800, kDP * 600 }; 85 SkScalar xPos = 230; 86 SkScalar yPos = 254.25f; 87 SkRect clipRect = SkRect::MakeXYWH(45, 75, 122, 250); 88 SkPoint clipDelta = SkPoint::Make(320, 0); 89 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kDP * 2); 90 91 canvas->save(); 92 canvas->clipRect(clipRect); 93 canvas->translate(xPos, yPos); 94 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 95 lightPos, kLightWidth, kSpotAlpha); 96 canvas->restore(); 97 98 lightPos.fX += 320; 99 xPos += 320; 100 clipRect.offset(clipDelta); 101 zPlaneParams.fZ = kDP * 3; 102 canvas->save(); 103 canvas->clipRect(clipRect); 104 canvas->translate(xPos, yPos); 105 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 106 lightPos, kLightWidth, kSpotAlpha); 107 canvas->restore(); 108 109 lightPos.fX += 320; 110 xPos += 320; 111 clipRect.offset(clipDelta); 112 zPlaneParams.fZ = kDP * 4; 113 canvas->save(); 114 canvas->clipRect(clipRect); 115 canvas->translate(xPos, yPos); 116 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 117 lightPos, kLightWidth, kSpotAlpha); 118 canvas->restore(); 119 120 lightPos.fX += 320; 121 xPos += 320; 122 clipRect.offset(clipDelta); 123 zPlaneParams.fZ = kDP * 6; 124 canvas->save(); 125 canvas->clipRect(clipRect); 126 canvas->translate(xPos, yPos); 127 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 128 lightPos, kLightWidth, kSpotAlpha); 129 canvas->restore(); 130 131 lightPos.fX += 320; 132 xPos += 320; 133 clipRect.offset(clipDelta); 134 zPlaneParams.fZ = kDP * 8; 135 canvas->save(); 136 canvas->clipRect(clipRect); 137 canvas->translate(xPos, yPos); 138 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 139 lightPos, kLightWidth, kSpotAlpha); 140 canvas->restore(); 141 142 lightPos.fX += 320; 143 xPos += 320; 144 clipRect.offset(clipDelta); 145 zPlaneParams.fZ = kDP * 16; 146 canvas->save(); 147 canvas->clipRect(clipRect); 148 canvas->translate(xPos, yPos); 149 this->drawShadowedPath(canvas, fRRectPath, zPlaneParams, paint, kAmbientAlpha, 150 lightPos, kLightWidth, kSpotAlpha); 151 canvas->restore(); 152 153 } 154 155 private: drawBG(SkCanvas * canvas)156 void drawBG(SkCanvas* canvas) { 157 canvas->drawColor(0xFFFFFFFF); 158 canvas->drawImage(fReferenceImage, 10, 30); 159 } 160 drawShadowedPath(SkCanvas * canvas,const SkPath & path,const SkPoint3 & zPlaneParams,const SkPaint & paint,SkScalar ambientAlpha,const SkPoint3 & lightPos,SkScalar lightWidth,SkScalar spotAlpha)161 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, 162 const SkPoint3& zPlaneParams, 163 const SkPaint& paint, SkScalar ambientAlpha, 164 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { 165 if (!fShowAmbient) { 166 ambientAlpha = 0; 167 } 168 if (!fShowSpot) { 169 spotAlpha = 0; 170 } 171 uint32_t flags = 0; 172 if (fUseAlt) { 173 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; 174 } 175 176 SkColor ambientColor = SkColorSetARGB(ambientAlpha * 255, 0, 0, 0); 177 SkColor spotColor = SkColorSetARGB(spotAlpha * 255, 0, 0, 0); 178 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 179 lightPos, lightWidth, 180 ambientColor, spotColor, flags); 181 182 if (fShowObject) { 183 canvas->drawPath(path, paint); 184 } else { 185 SkPaint strokePaint; 186 187 strokePaint.setColor(paint.getColor()); 188 strokePaint.setStyle(SkPaint::kStroke_Style); 189 190 canvas->drawPath(path, strokePaint); 191 } 192 } 193 }; 194 195 ////////////////////////////////////////////////////////////////////////////// 196 197 DEF_SLIDE( return new ShadowRefSlide(); ) 198