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