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 demonstrate tonal color shadows 18 19 class ShadowColorView : public SampleView { 20 SkPath fRectPath; 21 int fZIndex; 22 23 bool fShowAmbient; 24 bool fShowSpot; 25 bool fUseAlt; 26 bool fShowObject; 27 bool fTwoPassColor; 28 bool fDarkBackground; 29 30 public: 31 ShadowColorView() 32 : fZIndex(8) 33 , fShowAmbient(true) 34 , fShowSpot(true) 35 , fUseAlt(false) 36 , fShowObject(true) 37 , fTwoPassColor(false) 38 , fDarkBackground(false) {} 39 40 protected: 41 void onOnceBeforeDraw() override { 42 fRectPath.addRect(SkRect::MakeXYWH(-50, -50, 100, 100)); 43 } 44 45 // overrides from SkEventSink 46 bool onQuery(SkEvent* evt) override { 47 if (SampleCode::TitleQ(*evt)) { 48 SampleCode::TitleR(evt, "ShadowColor"); 49 return true; 50 } 51 52 SkUnichar uni; 53 if (SampleCode::CharQ(*evt, &uni)) { 54 bool handled = false; 55 switch (uni) { 56 case 'W': 57 fShowAmbient = !fShowAmbient; 58 handled = true; 59 break; 60 case 'S': 61 fShowSpot = !fShowSpot; 62 handled = true; 63 break; 64 case 'T': 65 fUseAlt = !fUseAlt; 66 handled = true; 67 break; 68 case 'O': 69 fShowObject = !fShowObject; 70 handled = true; 71 break; 72 case 'X': 73 fTwoPassColor = !fTwoPassColor; 74 handled = true; 75 break; 76 case 'Z': 77 fDarkBackground = !fDarkBackground; 78 handled = true; 79 break; 80 case '>': 81 fZIndex = SkTMin(9, fZIndex+1); 82 handled = true; 83 break; 84 case '<': 85 fZIndex = SkTMax(0, fZIndex-1); 86 handled = true; 87 break; 88 default: 89 break; 90 } 91 if (handled) { 92 this->inval(nullptr); 93 return true; 94 } 95 } 96 return this->INHERITED::onQuery(evt); 97 } 98 99 void drawShadowedPath(SkCanvas* canvas, const SkPath& path, 100 const SkPoint3& zPlaneParams, 101 const SkPaint& paint, SkScalar ambientAlpha, 102 const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { 103 if (!fShowAmbient) { 104 ambientAlpha = 0; 105 } 106 if (!fShowSpot) { 107 spotAlpha = 0; 108 } 109 uint32_t flags = 0; 110 if (fUseAlt) { 111 flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; 112 } 113 114 if (fTwoPassColor) { 115 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 116 lightPos, lightWidth, 117 ambientAlpha, 0, SK_ColorBLACK, flags); 118 119 if (paint.getColor() != SK_ColorBLACK) { 120 SkColor color = paint.getColor(); 121 122 uint8_t max = SkTMax(SkTMax(SkColorGetR(color), SkColorGetG(color)), 123 SkColorGetB(color)); 124 uint8_t min = SkTMin(SkTMin(SkColorGetR(color), SkColorGetG(color)), 125 SkColorGetB(color)); 126 SkScalar luminance = 0.5f*(max + min) / 255.f; 127 SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f; 128 spotAlpha -= (alpha - 0.3f)*.5f; 129 130 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 131 lightPos, lightWidth, 132 0, alpha, paint.getColor(), flags); 133 } 134 135 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 136 lightPos, lightWidth, 137 0, spotAlpha, SK_ColorBLACK, flags); 138 } else { 139 flags |= SkShadowFlags::kTonalColor_ShadowFlag; 140 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 141 lightPos, lightWidth, 142 ambientAlpha, spotAlpha, paint.getColor(), flags); 143 } 144 if (fShowObject) { 145 canvas->drawPath(path, paint); 146 } else { 147 SkPaint strokePaint; 148 149 strokePaint.setColor(paint.getColor()); 150 strokePaint.setStyle(SkPaint::kStroke_Style); 151 152 canvas->drawPath(path, strokePaint); 153 } 154 } 155 156 void onDrawContent(SkCanvas* canvas) override { 157 const SkScalar kLightWidth = 600; 158 const SkScalar kAmbientAlpha = 0.03f; 159 const SkScalar kSpotAlpha = 0.25f; 160 161 const SkScalar kZValues[10] = { 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 }; 162 163 const SkColor kColors[30] = { 164 // purples 165 0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5, 166 0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9, 167 // oranges 168 0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000, 169 0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC, 170 // teals 171 0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2, 172 0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0 173 }; 174 175 SkPaint paint; 176 paint.setAntiAlias(true); 177 if (fDarkBackground) { 178 canvas->drawColor(0xFF111111); 179 paint.setColor(SK_ColorWHITE); 180 } else { 181 canvas->drawColor(0xFFEAEAEA); 182 paint.setColor(SK_ColorBLACK); 183 } 184 185 if (fTwoPassColor) { 186 canvas->drawText("Two pass", 8, 10, 15, paint); 187 } else { 188 canvas->drawText("One pass", 8, 10, 15, paint); 189 } 190 191 SkPoint3 lightPos = { 75, -400, 600 }; 192 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kZValues[fZIndex]); 193 SkScalar yPos = 75; 194 195 for (int row = 0; row < 3; ++row) { 196 lightPos.fX = 75; 197 SkScalar xPos = 75; 198 for (int col = 0; col < 10; ++col) { 199 paint.setColor(kColors[10*row + col]); 200 201 canvas->save(); 202 canvas->translate(xPos, yPos); 203 this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha, 204 lightPos, kLightWidth, kSpotAlpha); 205 canvas->restore(); 206 207 lightPos.fX += 120; 208 xPos += 120; 209 } 210 211 lightPos.fY += 200; 212 yPos += 200; 213 } 214 } 215 216 private: 217 typedef SampleView INHERITED; 218 }; 219 220 ////////////////////////////////////////////////////////////////////////////// 221 222 static SkView* MyFactory() { return new ShadowColorView; } 223 static SkViewRegister reg(MyFactory); 224