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