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