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