gradients_2pt_conical.cpp revision 83f23d87f1d67e6e73873e1ef7cda621c43703a0
1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "gm.h" 9#include "SkGradientShader.h" 10 11namespace skiagm { 12 13struct GradData { 14 int fCount; 15 const SkColor* fColors; 16 const SkScalar* fPos; 17}; 18 19static const SkColor gColors[] = { 20 SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE, SK_ColorBLACK 21}; 22static const SkScalar gPos0[] = { 0, SK_Scalar1 }; 23static const SkScalar gPos1[] = { SK_Scalar1/4, SK_Scalar1*3/4 }; 24static const SkScalar gPos2[] = { 25 0, SK_Scalar1/8, SK_Scalar1/2, SK_Scalar1*7/8, SK_Scalar1 26}; 27 28static const SkScalar gPosClamp[] = {0.0f, 0.0f, 1.0f, 1.0f}; 29static const SkColor gColorClamp[] = { 30 SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorBLUE 31}; 32 33static const GradData gGradData[] = { 34 { 2, gColors, gPos0 }, 35 { 2, gColors, gPos1 }, 36 { 5, gColors, gPos2 }, 37 { 4, gColorClamp, gPosClamp } 38}; 39 40static SkShader* Make2ConicalOutside(const SkPoint pts[2], const GradData& data, 41 SkShader::TileMode tm, const SkMatrix& localMatrix) { 42 SkPoint center0, center1; 43 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10); 44 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 45 center0.set(pts[0].fX + radius0, pts[0].fY + radius0); 46 center1.set(pts[1].fX - radius1, pts[1].fY - radius1); 47 return SkGradientShader::CreateTwoPointConical(center0, radius0, 48 center1, radius1, 49 data.fColors, data.fPos, 50 data.fCount, tm, 0, &localMatrix); 51} 52 53static SkShader* Make2ConicalOutsideFlip(const SkPoint pts[2], const GradData& data, 54 SkShader::TileMode tm, const SkMatrix& localMatrix) { 55 SkPoint center0, center1; 56 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 10); 57 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 58 center0.set(pts[0].fX + radius0, pts[0].fY + radius0); 59 center1.set(pts[1].fX - radius1, pts[1].fY - radius1); 60 return SkGradientShader::CreateTwoPointConical(center1, radius1, 61 center0, radius0, 62 data.fColors, data.fPos, 63 data.fCount, tm, 0, &localMatrix); 64} 65 66static SkShader* Make2ConicalInside(const SkPoint pts[2], const GradData& data, 67 SkShader::TileMode tm, const SkMatrix& localMatrix) { 68 SkPoint center0, center1; 69 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 70 SkScalarAve(pts[0].fY, pts[1].fY)); 71 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 72 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 73 return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 7, 74 center0, (pts[1].fX - pts[0].fX) / 2, 75 data.fColors, data.fPos, data.fCount, tm, 76 0, &localMatrix); 77} 78 79static SkShader* Make2ConicalInsideFlip(const SkPoint pts[2], const GradData& data, 80 SkShader::TileMode tm, const SkMatrix& localMatrix) { 81 SkPoint center0, center1; 82 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 83 SkScalarAve(pts[0].fY, pts[1].fY)); 84 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 85 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 86 return SkGradientShader::CreateTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2, 87 center1, (pts[1].fX - pts[0].fX) / 7, 88 data.fColors, data.fPos, data.fCount, tm, 89 0, &localMatrix); 90} 91 92static SkShader* Make2ConicalInsideCenter(const SkPoint pts[2], const GradData& data, 93 SkShader::TileMode tm, const SkMatrix& localMatrix) { 94 SkPoint center0, center1; 95 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 96 SkScalarAve(pts[0].fY, pts[1].fY)); 97 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 98 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 99 return SkGradientShader::CreateTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 7, 100 center0, (pts[1].fX - pts[0].fX) / 2, 101 data.fColors, data.fPos, data.fCount, tm, 102 0, &localMatrix); 103} 104 105static SkShader* Make2ConicalZeroRad(const SkPoint pts[2], const GradData& data, 106 SkShader::TileMode tm, const SkMatrix& localMatrix) { 107 SkPoint center0, center1; 108 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 109 SkScalarAve(pts[0].fY, pts[1].fY)); 110 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 111 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 112 return SkGradientShader::CreateTwoPointConical(center1, 0.f, 113 center0, (pts[1].fX - pts[0].fX) / 2, 114 data.fColors, data.fPos, data.fCount, tm, 115 0, &localMatrix); 116} 117 118static SkShader* Make2ConicalZeroRadFlip(const SkPoint pts[2], const GradData& data, 119 SkShader::TileMode tm, const SkMatrix& localMatrix) { 120 SkPoint center0, center1; 121 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 122 SkScalarAve(pts[0].fY, pts[1].fY)); 123 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 124 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 125 return SkGradientShader::CreateTwoPointConical(center1, (pts[1].fX - pts[0].fX) / 2, 126 center0, 0.f, 127 data.fColors, data.fPos, data.fCount, tm, 128 0, &localMatrix); 129} 130 131static SkShader* Make2ConicalZeroRadCenter(const SkPoint pts[2], const GradData& data, 132 SkShader::TileMode tm, const SkMatrix& localMatrix) { 133 SkPoint center0, center1; 134 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 135 SkScalarAve(pts[0].fY, pts[1].fY)); 136 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 137 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 138 return SkGradientShader::CreateTwoPointConical(center0, 0.f, 139 center0, (pts[1].fX - pts[0].fX) / 2, 140 data.fColors, data.fPos, data.fCount, tm, 141 0, &localMatrix); 142} 143 144static SkShader* Make2ConicalZeroRadOutside(const SkPoint pts[2], const GradData& data, 145 SkShader::TileMode tm, const SkMatrix& localMatrix) { 146 SkPoint center0, center1; 147 SkScalar radius0 = 0.f; 148 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 149 center0.set(pts[0].fX + radius0, pts[0].fY + radius0); 150 center1.set(pts[1].fX - radius1, pts[1].fY - radius1); 151 return SkGradientShader::CreateTwoPointConical(center0, radius0, 152 center1, radius1, 153 data.fColors, data.fPos, 154 data.fCount, tm, 0, &localMatrix); 155} 156 157static SkShader* Make2ConicalZeroRadFlipOutside(const SkPoint pts[2], const GradData& data, 158 SkShader::TileMode tm, const SkMatrix& localMatrix) { 159 SkPoint center0, center1; 160 SkScalar radius0 = 0.f; 161 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 162 center0.set(pts[0].fX + radius0, pts[0].fY + radius0); 163 center1.set(pts[1].fX - radius1, pts[1].fY - radius1); 164 return SkGradientShader::CreateTwoPointConical(center1, radius1, 165 center0, radius0, 166 data.fColors, data.fPos, 167 data.fCount, tm, 0, &localMatrix); 168} 169 170static SkShader* Make2ConicalEdgeX(const SkPoint pts[2], const GradData& data, 171 SkShader::TileMode tm, const SkMatrix& localMatrix) { 172 SkPoint center0, center1; 173 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7); 174 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 175 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 176 SkScalarAve(pts[0].fY, pts[1].fY)); 177 center0.set(center1.fX + radius1, center1.fY); 178 return SkGradientShader::CreateTwoPointConical(center0, radius0, 179 center1, radius1, 180 data.fColors, data.fPos, 181 data.fCount, tm, 0, &localMatrix); 182} 183 184static SkShader* Make2ConicalEdgeY(const SkPoint pts[2], const GradData& data, 185 SkShader::TileMode tm, const SkMatrix& localMatrix) { 186 SkPoint center0, center1; 187 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7); 188 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 189 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 190 SkScalarAve(pts[0].fY, pts[1].fY)); 191 center0.set(center1.fX, center1.fY + radius1); 192 return SkGradientShader::CreateTwoPointConical(center0, radius0, 193 center1, radius1, 194 data.fColors, data.fPos, 195 data.fCount, tm, 0, &localMatrix); 196} 197static SkShader* Make2ConicalZeroRadEdgeX(const SkPoint pts[2], const GradData& data, 198 SkShader::TileMode tm, const SkMatrix& localMatrix) { 199 SkPoint center0, center1; 200 SkScalar radius0 = 0.f; 201 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 202 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 203 SkScalarAve(pts[0].fY, pts[1].fY)); 204 center0.set(center1.fX + radius1, center1.fY); 205 return SkGradientShader::CreateTwoPointConical(center0, radius0, 206 center1, radius1, 207 data.fColors, data.fPos, 208 data.fCount, tm, 0, &localMatrix); 209} 210 211static SkShader* Make2ConicalZeroRadEdgeY(const SkPoint pts[2], const GradData& data, 212 SkShader::TileMode tm, const SkMatrix& localMatrix) { 213 SkPoint center0, center1; 214 SkScalar radius0 = 0.f; 215 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 216 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 217 SkScalarAve(pts[0].fY, pts[1].fY)); 218 center0.set(center1.fX, center1.fY + radius1); 219 return SkGradientShader::CreateTwoPointConical(center0, radius0, 220 center1, radius1, 221 data.fColors, data.fPos, 222 data.fCount, tm, 0, &localMatrix); 223} 224 225static SkShader* Make2ConicalTouchX(const SkPoint pts[2], const GradData& data, 226 SkShader::TileMode tm, const SkMatrix& localMatrix) { 227 SkPoint center0, center1; 228 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7); 229 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 230 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 231 SkScalarAve(pts[0].fY, pts[1].fY)); 232 center0.set(center1.fX - radius1 + radius0, center1.fY); 233 return SkGradientShader::CreateTwoPointConical(center0, radius0, 234 center1, radius1, 235 data.fColors, data.fPos, 236 data.fCount, tm, 0, &localMatrix); 237} 238 239static SkShader* Make2ConicalTouchY(const SkPoint pts[2], const GradData& data, 240 SkShader::TileMode tm, const SkMatrix& localMatrix) { 241 SkPoint center0, center1; 242 SkScalar radius0 = SkScalarDiv(pts[1].fX - pts[0].fX, 7); 243 SkScalar radius1 = SkScalarDiv(pts[1].fX - pts[0].fX, 3); 244 center1.set(SkScalarAve(pts[0].fX, pts[1].fX), 245 SkScalarAve(pts[0].fY, pts[1].fY)); 246 center0.set(center1.fX, center1.fY + radius1 - radius0); 247 return SkGradientShader::CreateTwoPointConical(center0, radius0, 248 center1, radius1, 249 data.fColors, data.fPos, 250 data.fCount, tm, 0, &localMatrix); 251} 252 253static SkShader* Make2ConicalInsideSmallRad(const SkPoint pts[2], const GradData& data, 254 SkShader::TileMode tm, const SkMatrix& localMatrix) { 255 SkPoint center0, center1; 256 center0.set(SkScalarAve(pts[0].fX, pts[1].fX), 257 SkScalarAve(pts[0].fY, pts[1].fY)); 258 center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), 259 SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); 260 return SkGradientShader::CreateTwoPointConical(center0, 0.0000000000000000001f, 261 center0, (pts[1].fX - pts[0].fX) / 2, 262 data.fColors, data.fPos, data.fCount, tm, 263 0, &localMatrix); 264} 265 266typedef SkShader* (*GradMaker)(const SkPoint pts[2], const GradData& data, 267 SkShader::TileMode tm, const SkMatrix& localMatrix); 268 269static const GradMaker gGradMakersOutside[] = { 270 Make2ConicalOutside, Make2ConicalOutsideFlip, 271 Make2ConicalZeroRadOutside, Make2ConicalZeroRadFlipOutside 272}; 273 274static const GradMaker gGradMakersInside[] = { 275 Make2ConicalInside, Make2ConicalInsideFlip, Make2ConicalInsideCenter, 276 Make2ConicalZeroRad, Make2ConicalZeroRadFlip, Make2ConicalZeroRadCenter, 277}; 278 279static const GradMaker gGradMakersEdgeCases[] = { 280 Make2ConicalEdgeX, Make2ConicalEdgeY, 281 Make2ConicalZeroRadEdgeX, Make2ConicalZeroRadEdgeY, 282 Make2ConicalTouchX, Make2ConicalTouchY, 283 Make2ConicalInsideSmallRad 284}; 285 286 287static const struct { 288 const GradMaker* fMaker; 289 const int fCount; 290 const char* fName; 291} gGradCases[] = { 292 { gGradMakersOutside, SK_ARRAY_COUNT(gGradMakersOutside), "outside" }, 293 { gGradMakersInside, SK_ARRAY_COUNT(gGradMakersInside), "inside" }, 294 { gGradMakersEdgeCases, SK_ARRAY_COUNT(gGradMakersEdgeCases), "edge" }, 295}; 296 297enum GradCaseType { // these must match the order in gGradCases 298 kOutside_GradCaseType, 299 kInside_GradCaseType, 300 kEdge_GradCaseType, 301}; 302 303/////////////////////////////////////////////////////////////////////////////// 304 305class ConicalGradientsGM : public GM { 306public: 307 ConicalGradientsGM(GradCaseType gradCaseType) { 308 this->setBGColor(0xFFDDDDDD); 309 fName.printf("gradients_2pt_conical_%s", gGradCases[gradCaseType].fName); 310 fGradCaseType = gradCaseType; 311 } 312 313protected: 314 virtual uint32_t onGetFlags() const SK_OVERRIDE { 315 if (fGradCaseType != kInside_GradCaseType) { 316 return kSkipTiled_Flag; 317 } 318 return 0; 319 } 320 321 SkString onShortName() { 322 return fName; 323 } 324 325 virtual SkISize onISize() { return SkISize::Make(840, 815); } 326 327 virtual void onDraw(SkCanvas* canvas) { 328 329 SkPoint pts[2] = { 330 { 0, 0 }, 331 { SkIntToScalar(100), SkIntToScalar(100) } 332 }; 333 SkShader::TileMode tm = SkShader::kClamp_TileMode; 334 SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) }; 335 SkPaint paint; 336 paint.setAntiAlias(true); 337 338 canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); 339 340 const GradMaker* gradMaker = gGradCases[fGradCaseType].fMaker; 341 const int count = gGradCases[fGradCaseType].fCount; 342 343 for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) { 344 canvas->save(); 345 for (int j = 0; j < count; j++) { 346 SkMatrix scale = SkMatrix::I(); 347 348 if (i == 3) { // if the clamp case 349 scale.setScale(0.5f, 0.5f); 350 scale.postTranslate(25.f, 25.f); 351 } 352 353 SkShader* shader = gradMaker[j](pts, gGradData[i], tm, scale); 354 paint.setShader(shader); 355 canvas->drawRect(r, paint); 356 shader->unref(); 357 canvas->translate(0, SkIntToScalar(120)); 358 } 359 canvas->restore(); 360 canvas->translate(SkIntToScalar(120), 0); 361 } 362 } 363 364private: 365 typedef GM INHERITED; 366 367 GradCaseType fGradCaseType; 368 SkString fName; 369}; 370/////////////////////////////////////////////////////////////////////////////// 371 372static GM* MyFactory1(void*) { return new ConicalGradientsGM(kInside_GradCaseType); } 373static GMRegistry reg1(MyFactory1); 374 375static GM* MyFactory2(void*) { return new ConicalGradientsGM(kOutside_GradCaseType); } 376static GMRegistry reg2(MyFactory2); 377 378static GM* MyFactory3(void*) { return new ConicalGradientsGM(kEdge_GradCaseType); } 379static GMRegistry reg3(MyFactory3); 380} 381