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 11 #include "SkCanvas.h" 12 #include "SkFont.h" 13 #include "SkImage.h" 14 #include "SkPath.h" 15 #include "SkPoint3.h" 16 #include "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 onQuery(Sample::Event * evt)47 bool onQuery(Sample::Event* evt) override { 48 if (Sample::TitleQ(*evt)) { 49 Sample::TitleR(evt, "ShadowColor"); 50 return true; 51 } 52 53 SkUnichar uni; 54 if (Sample::CharQ(*evt, &uni)) { 55 bool handled = false; 56 switch (uni) { 57 case 'W': 58 fShowAmbient = !fShowAmbient; 59 handled = true; 60 break; 61 case 'S': 62 fShowSpot = !fShowSpot; 63 handled = true; 64 break; 65 case 'T': 66 fUseAlt = !fUseAlt; 67 handled = true; 68 break; 69 case 'O': 70 fShowObject = !fShowObject; 71 handled = true; 72 break; 73 case 'X': 74 fTwoPassColor = !fTwoPassColor; 75 handled = true; 76 break; 77 case 'Z': 78 fDarkBackground = !fDarkBackground; 79 handled = true; 80 break; 81 case '>': 82 fZIndex = SkTMin(9, fZIndex+1); 83 handled = true; 84 break; 85 case '<': 86 fZIndex = SkTMax(0, fZIndex-1); 87 handled = true; 88 break; 89 default: 90 break; 91 } 92 if (handled) { 93 return true; 94 } 95 } 96 return this->INHERITED::onQuery(evt); 97 } 98 drawShadowedPath(SkCanvas * canvas,const SkPath & path,const SkPoint3 & zPlaneParams,const SkPaint & paint,SkScalar ambientAlpha,const SkPoint3 & lightPos,SkScalar lightWidth,SkScalar spotAlpha)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 SkColor ambientColor = SkColorSetARGB(ambientAlpha*255, 0, 0, 0); 116 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 117 lightPos, lightWidth, 118 ambientColor, SK_ColorTRANSPARENT, flags); 119 120 if (paint.getColor() != SK_ColorBLACK) { 121 SkColor color = paint.getColor(); 122 123 uint8_t max = SkTMax(SkTMax(SkColorGetR(color), SkColorGetG(color)), 124 SkColorGetB(color)); 125 uint8_t min = SkTMin(SkTMin(SkColorGetR(color), SkColorGetG(color)), 126 SkColorGetB(color)); 127 SkScalar luminance = 0.5f*(max + min) / 255.f; 128 SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f; 129 spotAlpha -= (alpha - 0.3f)*.5f; 130 SkColor spotColor = SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color), 131 SkColorGetG(color), SkColorGetB(color)); 132 133 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 134 lightPos, lightWidth, 135 SK_ColorTRANSPARENT, spotColor, flags); 136 } 137 138 SkColor spotGreyscale = SkColorSetARGB(spotAlpha * 255, 0, 0, 0); 139 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 140 lightPos, lightWidth, 141 SK_ColorTRANSPARENT, spotGreyscale, flags); 142 } else { 143 SkColor color = paint.getColor(); 144 SkColor baseAmbient = SkColorSetARGB(ambientAlpha*SkColorGetA(color), 145 SkColorGetR(color), SkColorGetG(color), 146 SkColorGetB(color)); 147 SkColor baseSpot = SkColorSetARGB(spotAlpha*SkColorGetA(color), 148 SkColorGetR(color), SkColorGetG(color), 149 SkColorGetB(color)); 150 SkColor tonalAmbient, tonalSpot; 151 SkShadowUtils::ComputeTonalColors(baseAmbient, baseSpot, &tonalAmbient, &tonalSpot); 152 SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, 153 lightPos, lightWidth, 154 tonalAmbient, tonalSpot, flags); 155 } 156 if (fShowObject) { 157 canvas->drawPath(path, paint); 158 } else { 159 SkPaint strokePaint; 160 161 strokePaint.setColor(paint.getColor()); 162 strokePaint.setStyle(SkPaint::kStroke_Style); 163 164 canvas->drawPath(path, strokePaint); 165 } 166 } 167 onDrawContent(SkCanvas * canvas)168 void onDrawContent(SkCanvas* canvas) override { 169 const SkScalar kLightWidth = 600; 170 const SkScalar kAmbientAlpha = 0.03f; 171 const SkScalar kSpotAlpha = 0.25f; 172 173 const SkScalar kZValues[10] = { 1, 2, 3, 4, 6, 8, 9, 12, 16, 24 }; 174 175 const SkColor kColors[30] = { 176 // purples 177 0xFF3A0072, 0xFF5D0099, 0xFF7F12B2, 0xFFA02AD1, 0xFFC245E5, 178 0xFFE95AF9, 0xFFFC79F0, 0xFFFDA6F0, 0xFFFFCCF8, 0xFFFFE1F9, 179 // oranges 180 0xFFEA3200, 0xFFFF4E00, 0xFFFF7300, 0xFFFF9100, 0xFFFFB000, 181 0xFFFFCE00, 0xFFFFE000, 0xFFFFF64D, 0xFFFFF98F, 0xFFFFFBCC, 182 // teals 183 0xFF004D51, 0xFF066266, 0xFF057F7F, 0xFF009999, 0xFF00B2B2, 184 0xFF15CCBE, 0xFF25E5CE, 0xFF2CFFE0, 0xFF80FFEA, 0xFFB3FFF0 185 }; 186 187 SkFont font; 188 SkPaint paint; 189 paint.setAntiAlias(true); 190 if (fDarkBackground) { 191 canvas->drawColor(0xFF111111); 192 paint.setColor(SK_ColorWHITE); 193 } else { 194 canvas->drawColor(0xFFEAEAEA); 195 paint.setColor(SK_ColorBLACK); 196 } 197 if (fTwoPassColor) { 198 canvas->drawString("Two pass", 10, 15, font, paint); 199 } else { 200 canvas->drawString("One pass", 10, 15, font, paint); 201 } 202 203 SkPoint3 lightPos = { 75, -400, 600 }; 204 SkPoint3 zPlaneParams = SkPoint3::Make(0, 0, kZValues[fZIndex]); 205 SkScalar yPos = 75; 206 207 for (int row = 0; row < 3; ++row) { 208 lightPos.fX = 75; 209 SkScalar xPos = 75; 210 for (int col = 0; col < 10; ++col) { 211 paint.setColor(kColors[10*row + col]); 212 213 canvas->save(); 214 canvas->translate(xPos, yPos); 215 this->drawShadowedPath(canvas, fRectPath, zPlaneParams, paint, kAmbientAlpha, 216 lightPos, kLightWidth, kSpotAlpha); 217 canvas->restore(); 218 219 lightPos.fX += 120; 220 xPos += 120; 221 } 222 223 lightPos.fY += 200; 224 yPos += 200; 225 } 226 } 227 228 private: 229 typedef Sample INHERITED; 230 }; 231 232 ////////////////////////////////////////////////////////////////////////////// 233 234 DEF_SAMPLE( return new ShadowColorView(); ) 235