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