GradientTest.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. /*
  2. * Copyright 2011 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. #include "include/core/SkCanvas.h"
  8. #include "include/core/SkColorPriv.h"
  9. #include "include/core/SkShader.h"
  10. #include "include/core/SkSurface.h"
  11. #include "include/effects/SkGradientShader.h"
  12. #include "include/private/SkTemplates.h"
  13. #include "src/core/SkTLazy.h"
  14. #include "src/shaders/SkColorShader.h"
  15. #include "tests/Test.h"
  16. // https://code.google.com/p/chromium/issues/detail?id=448299
  17. // Giant (inverse) matrix causes overflow when converting/computing using 32.32
  18. // Before the fix, we would assert (and then crash).
  19. static void test_big_grad(skiatest::Reporter* reporter) {
  20. const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
  21. const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }};
  22. SkPaint paint;
  23. paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
  24. SkBitmap bm;
  25. bm.allocN32Pixels(2000, 1);
  26. SkCanvas c(bm);
  27. const SkScalar affine[] = {
  28. 1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f
  29. };
  30. SkMatrix matrix;
  31. matrix.setAffine(affine);
  32. c.concat(matrix);
  33. c.drawPaint(paint);
  34. }
  35. struct GradRec {
  36. int fColorCount;
  37. const SkColor* fColors;
  38. const SkScalar* fPos;
  39. const SkPoint* fPoint; // 2
  40. const SkScalar* fRadius; // 2
  41. SkTileMode fTileMode;
  42. void gradCheck(skiatest::Reporter* reporter, const sk_sp<SkShader>& shader,
  43. SkShader::GradientInfo* info,
  44. SkShader::GradientType gt) const {
  45. SkAutoTMalloc<SkColor> colorStorage(fColorCount);
  46. SkAutoTMalloc<SkScalar> posStorage(fColorCount);
  47. info->fColorCount = fColorCount;
  48. info->fColors = colorStorage;
  49. info->fColorOffsets = posStorage.get();
  50. REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt);
  51. REPORTER_ASSERT(reporter, info->fColorCount == fColorCount);
  52. REPORTER_ASSERT(reporter,
  53. !memcmp(info->fColors, fColors, fColorCount * sizeof(SkColor)));
  54. REPORTER_ASSERT(reporter,
  55. !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(SkScalar)));
  56. REPORTER_ASSERT(reporter, fTileMode == (SkTileMode)info->fTileMode);
  57. }
  58. };
  59. static void none_gradproc(skiatest::Reporter* reporter, const GradRec&, const GradRec&) {
  60. sk_sp<SkShader> s(SkShaders::Empty());
  61. REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(nullptr));
  62. }
  63. static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec, const GradRec&) {
  64. sk_sp<SkShader> s(new SkColorShader(rec.fColors[0]));
  65. REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(nullptr));
  66. SkShader::GradientInfo info;
  67. info.fColors = nullptr;
  68. info.fColorCount = 0;
  69. s->asAGradient(&info);
  70. REPORTER_ASSERT(reporter, 1 == info.fColorCount);
  71. }
  72. static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
  73. const GradRec& checkRec) {
  74. sk_sp<SkShader> s(SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fColors, buildRec.fPos,
  75. buildRec.fColorCount, buildRec.fTileMode));
  76. SkShader::GradientInfo info;
  77. checkRec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType);
  78. REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
  79. }
  80. static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
  81. const GradRec& checkRec) {
  82. sk_sp<SkShader> s(SkGradientShader::MakeRadial(buildRec.fPoint[0], buildRec.fRadius[0],
  83. buildRec.fColors, buildRec.fPos,
  84. buildRec.fColorCount, buildRec.fTileMode));
  85. SkShader::GradientInfo info;
  86. checkRec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType);
  87. REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]);
  88. REPORTER_ASSERT(reporter, info.fRadius[0] == checkRec.fRadius[0]);
  89. }
  90. static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
  91. const GradRec& checkRec) {
  92. sk_sp<SkShader> s(SkGradientShader::MakeSweep(buildRec.fPoint[0].fX, buildRec.fPoint[0].fY,
  93. buildRec.fColors, buildRec.fPos,
  94. buildRec.fColorCount));
  95. SkShader::GradientInfo info;
  96. checkRec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType);
  97. REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]);
  98. }
  99. static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
  100. const GradRec& checkRec) {
  101. sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(buildRec.fPoint[0],
  102. buildRec.fRadius[0],
  103. buildRec.fPoint[1],
  104. buildRec.fRadius[1],
  105. buildRec.fColors,
  106. buildRec.fPos,
  107. buildRec.fColorCount,
  108. buildRec.fTileMode));
  109. SkShader::GradientInfo info;
  110. checkRec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType);
  111. REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
  112. REPORTER_ASSERT(reporter, !memcmp(info.fRadius, checkRec.fRadius, 2 * sizeof(SkScalar)));
  113. }
  114. // Ensure that repeated color gradients behave like drawing a single color
  115. static void TestConstantGradient(skiatest::Reporter*) {
  116. const SkPoint pts[] = {
  117. { 0, 0 },
  118. { SkIntToScalar(10), 0 }
  119. };
  120. SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE };
  121. const SkScalar pos[] = { 0, SK_Scalar1 };
  122. SkPaint paint;
  123. paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
  124. SkBitmap outBitmap;
  125. outBitmap.allocN32Pixels(10, 1);
  126. SkCanvas canvas(outBitmap);
  127. canvas.drawPaint(paint);
  128. for (int i = 0; i < 10; i++) {
  129. // The following is commented out because it currently fails
  130. // Related bug: https://code.google.com/p/skia/issues/detail?id=1098
  131. // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0));
  132. }
  133. }
  134. typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&, const GradRec&);
  135. static void TestGradientShaders(skiatest::Reporter* reporter) {
  136. static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
  137. static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
  138. static const SkPoint gPts[] = {
  139. { 0, 0 },
  140. { SkIntToScalar(10), SkIntToScalar(20) }
  141. };
  142. static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) };
  143. GradRec rec;
  144. rec.fColorCount = SK_ARRAY_COUNT(gColors);
  145. rec.fColors = gColors;
  146. rec.fPos = gPos;
  147. rec.fPoint = gPts;
  148. rec.fRadius = gRad;
  149. rec.fTileMode = SkTileMode::kClamp;
  150. static const GradProc gProcs[] = {
  151. none_gradproc,
  152. color_gradproc,
  153. linear_gradproc,
  154. radial_gradproc,
  155. sweep_gradproc,
  156. conical_gradproc,
  157. };
  158. for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) {
  159. gProcs[i](reporter, rec, rec);
  160. }
  161. }
  162. static void TestGradientOptimization(skiatest::Reporter* reporter) {
  163. static const struct {
  164. GradProc fProc;
  165. bool fIsClampRestricted;
  166. } gProcInfo[] = {
  167. { linear_gradproc , false },
  168. { radial_gradproc , false },
  169. { sweep_gradproc , true }, // sweep is funky in that it always pretends to be kClamp.
  170. { conical_gradproc, false },
  171. };
  172. static const SkColor gC_00[] = { 0xff000000, 0xff000000 };
  173. static const SkColor gC_01[] = { 0xff000000, 0xffffffff };
  174. static const SkColor gC_11[] = { 0xffffffff, 0xffffffff };
  175. static const SkColor gC_001[] = { 0xff000000, 0xff000000, 0xffffffff };
  176. static const SkColor gC_011[] = { 0xff000000, 0xffffffff, 0xffffffff };
  177. static const SkColor gC_0011[] = { 0xff000000, 0xff000000, 0xffffffff, 0xffffffff };
  178. static const SkScalar gP_01[] = { 0, 1 };
  179. static const SkScalar gP_001[] = { 0, 0, 1 };
  180. static const SkScalar gP_011[] = { 0, 1, 1 };
  181. static const SkScalar gP_0x1[] = { 0, .5f, 1 };
  182. static const SkScalar gP_0011[] = { 0, 0, 1, 1 };
  183. static const SkPoint gPts[] = { {0, 0}, {1, 1} };
  184. static const SkScalar gRadii[] = { 1, 2 };
  185. static const struct {
  186. const SkColor* fCol;
  187. const SkScalar* fPos;
  188. int fCount;
  189. const SkColor* fExpectedCol;
  190. const SkScalar* fExpectedPos;
  191. int fExpectedCount;
  192. bool fRequiresNonClamp;
  193. } gTests[] = {
  194. { gC_001, gP_001, 3, gC_01, gP_01, 2, false },
  195. { gC_001, gP_011, 3, gC_00, gP_01, 2, true },
  196. { gC_001, gP_0x1, 3, gC_001, gP_0x1, 3, false },
  197. { gC_001, nullptr, 3, gC_001, gP_0x1, 3, false },
  198. { gC_011, gP_001, 3, gC_11, gP_01, 2, true },
  199. { gC_011, gP_011, 3, gC_01, gP_01, 2, false },
  200. { gC_011, gP_0x1, 3, gC_011, gP_0x1, 3, false },
  201. { gC_011, nullptr, 3, gC_011, gP_0x1, 3, false },
  202. { gC_0011, gP_0011, 4, gC_0011, gP_0011, 4, false },
  203. };
  204. const SkTileMode modes[] = {
  205. SkTileMode::kClamp, SkTileMode::kRepeat, SkTileMode::kMirror,
  206. // TODO: add kDecal_TileMode when it is implemented
  207. };
  208. for (size_t i = 0; i < SK_ARRAY_COUNT(gProcInfo); ++i) {
  209. for (auto mode : modes) {
  210. if (gProcInfo[i].fIsClampRestricted && mode != SkTileMode::kClamp) {
  211. continue;
  212. }
  213. for (size_t t = 0; t < SK_ARRAY_COUNT(gTests); ++t) {
  214. GradRec rec;
  215. rec.fColorCount = gTests[t].fCount;
  216. rec.fColors = gTests[t].fCol;
  217. rec.fPos = gTests[t].fPos;
  218. rec.fTileMode = mode;
  219. rec.fPoint = gPts;
  220. rec.fRadius = gRadii;
  221. GradRec expected = rec;
  222. if (!gTests[t].fRequiresNonClamp || mode != SkTileMode::kClamp) {
  223. expected.fColorCount = gTests[t].fExpectedCount;
  224. expected.fColors = gTests[t].fExpectedCol;
  225. expected.fPos = gTests[t].fExpectedPos;
  226. }
  227. gProcInfo[i].fProc(reporter, rec, expected);
  228. }
  229. }
  230. }
  231. }
  232. static void test_nearly_vertical(skiatest::Reporter* reporter) {
  233. auto surface(SkSurface::MakeRasterN32Premul(200, 200));
  234. const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }};
  235. const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
  236. const SkScalar pos[] = { 0, 1 };
  237. SkPaint paint;
  238. paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
  239. surface->getCanvas()->drawPaint(paint);
  240. }
  241. static void test_vertical(skiatest::Reporter* reporter) {
  242. auto surface(SkSurface::MakeRasterN32Premul(200, 200));
  243. const SkPoint pts[] = {{ 100, 50 }, { 100, 50 }};
  244. const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
  245. const SkScalar pos[] = { 0, 1 };
  246. SkPaint paint;
  247. paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
  248. surface->getCanvas()->drawPaint(paint);
  249. }
  250. // A linear gradient interval can, due to numerical imprecision (likely in the divide)
  251. // finish an interval with the final fx not landing outside of [p0...p1].
  252. // The old code had an assert which this test triggered.
  253. // We now explicitly clamp the resulting fx value.
  254. static void test_linear_fuzz(skiatest::Reporter* reporter) {
  255. auto surface(SkSurface::MakeRasterN32Premul(1300, 630));
  256. const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }};
  257. const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE };
  258. const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 };
  259. SkPaint paint;
  260. paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 4, SkTileMode::kClamp));
  261. SkRect r = {0, 83, 1254, 620};
  262. surface->getCanvas()->drawRect(r, paint);
  263. }
  264. // https://bugs.chromium.org/p/skia/issues/detail?id=5023
  265. // We should still shade pixels for which the radius is exactly 0.
  266. static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) {
  267. auto surface(SkSurface::MakeRasterN32Premul(5, 5));
  268. surface->getCanvas()->clear(SK_ColorRED);
  269. const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE };
  270. SkPaint p;
  271. p.setShader(SkGradientShader::MakeTwoPointConical(
  272. SkPoint::Make(2.5f, 2.5f), 0,
  273. SkPoint::Make(3.0f, 3.0f), 10,
  274. colors, nullptr, SK_ARRAY_COUNT(colors), SkTileMode::kClamp));
  275. surface->getCanvas()->drawPaint(p);
  276. // r == 0 for the center pixel.
  277. // verify that we draw it (no red bleed)
  278. SkPMColor centerPMColor;
  279. surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), &centerPMColor, sizeof(SkPMColor), 2, 2);
  280. REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0);
  281. }
  282. // http://crbug.com/599458
  283. static void test_clamping_overflow(skiatest::Reporter*) {
  284. SkPaint p;
  285. const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
  286. const SkPoint pts1[] = { SkPoint::Make(1001, 1000001), SkPoint::Make(1000.99f, 1000000) };
  287. p.setShader(SkGradientShader::MakeLinear(pts1, colors, nullptr, 2, SkTileMode::kClamp));
  288. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  289. surface->getCanvas()->scale(100, 100);
  290. surface->getCanvas()->drawPaint(p);
  291. const SkPoint pts2[] = { SkPoint::Make(10000.99f, 1000000), SkPoint::Make(10001, 1000001) };
  292. p.setShader(SkGradientShader::MakeLinear(pts2, colors, nullptr, 2, SkTileMode::kClamp));
  293. surface->getCanvas()->drawPaint(p);
  294. // Passes if we don't trigger asserts.
  295. }
  296. // http://crbug.com/636194
  297. static void test_degenerate_linear(skiatest::Reporter*) {
  298. SkPaint p;
  299. const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
  300. const SkPoint pts[] = {
  301. SkPoint::Make(-46058024627067344430605278824628224.0f, 0),
  302. SkPoint::Make(SK_ScalarMax, 0)
  303. };
  304. p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
  305. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  306. surface->getCanvas()->drawPaint(p);
  307. // Passes if we don't trigger asserts.
  308. }
  309. // "Interesting" fuzzer values.
  310. static void test_linear_fuzzer(skiatest::Reporter*) {
  311. static const SkColor gColors0[] = { 0x30303030, 0x30303030 };
  312. static const SkColor gColors1[] = { 0x30303030, 0x30303030, 0x30303030 };
  313. static const SkScalar gPos1[] = { 0, 0, 1 };
  314. static const SkScalar gMatrix0[9] = {
  315. 6.40969056e-10f, 0 , 6.40969056e-10f,
  316. 0 , 4.42539023e-39f, 6.40969056e-10f,
  317. 0 , 0 , 1
  318. };
  319. static const SkScalar gMatrix1[9] = {
  320. -2.75294113f , 6.40969056e-10f, 6.40969056e-10f,
  321. 6.40969056e-10f, 6.40969056e-10f, -3.32810161e+24f,
  322. 6.40969056e-10f, 6.40969056e-10f, 0
  323. };
  324. static const SkScalar gMatrix2[9] = {
  325. 7.93481258e+17f, 6.40969056e-10f, 6.40969056e-10f,
  326. 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f,
  327. 6.40969056e-10f, 6.40969056e-10f, 0.688235283f
  328. };
  329. static const SkScalar gMatrix3[9] = {
  330. 1.89180674e+11f, 6.40969056e-10f, 6.40969056e-10f,
  331. 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f,
  332. 6.40969056e-10f, 11276.0469f , 8.12524808e+20f
  333. };
  334. static const struct {
  335. SkPoint fPts[2];
  336. const SkColor* fColors;
  337. const SkScalar* fPos;
  338. int fCount;
  339. SkTileMode fTileMode;
  340. uint32_t fFlags;
  341. const SkScalar* fLocalMatrix;
  342. const SkScalar* fGlobalMatrix;
  343. } gConfigs[] = {
  344. {
  345. {{0, -2.752941f}, {0, 0}},
  346. gColors0,
  347. nullptr,
  348. SK_ARRAY_COUNT(gColors0),
  349. SkTileMode::kClamp,
  350. 0,
  351. gMatrix0,
  352. nullptr
  353. },
  354. {
  355. {{4.42539023e-39f, -4.42539023e-39f}, {9.78041162e-15f, 4.42539023e-39f}},
  356. gColors1,
  357. gPos1,
  358. SK_ARRAY_COUNT(gColors1),
  359. SkTileMode::kClamp,
  360. 0,
  361. nullptr,
  362. gMatrix1
  363. },
  364. {
  365. {{4.42539023e-39f, 6.40969056e-10f}, {6.40969056e-10f, 1.49237238e-19f}},
  366. gColors1,
  367. gPos1,
  368. SK_ARRAY_COUNT(gColors1),
  369. SkTileMode::kClamp,
  370. 0,
  371. nullptr,
  372. gMatrix2
  373. },
  374. {
  375. {{6.40969056e-10f, 6.40969056e-10f}, {6.40969056e-10f, -0.688235283f}},
  376. gColors0,
  377. nullptr,
  378. SK_ARRAY_COUNT(gColors0),
  379. SkTileMode::kClamp,
  380. 0,
  381. gMatrix3,
  382. nullptr
  383. },
  384. };
  385. sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
  386. SkColorSpace* colorSpaces[] = {
  387. nullptr, // hits the legacy gradient impl
  388. srgb.get(), // triggers 4f/raster-pipeline
  389. };
  390. SkPaint paint;
  391. for (auto colorSpace : colorSpaces) {
  392. sk_sp<SkSurface> surface = SkSurface::MakeRaster(SkImageInfo::Make(100, 100,
  393. kN32_SkColorType,
  394. kPremul_SkAlphaType,
  395. sk_ref_sp(colorSpace)));
  396. SkCanvas* canvas = surface->getCanvas();
  397. for (const auto& config : gConfigs) {
  398. SkAutoCanvasRestore acr(canvas, false);
  399. SkTLazy<SkMatrix> localMatrix;
  400. if (config.fLocalMatrix) {
  401. localMatrix.init();
  402. localMatrix.get()->set9(config.fLocalMatrix);
  403. }
  404. paint.setShader(SkGradientShader::MakeLinear(config.fPts,
  405. config.fColors,
  406. config.fPos,
  407. config.fCount,
  408. config.fTileMode,
  409. config.fFlags,
  410. localMatrix.getMaybeNull()));
  411. if (config.fGlobalMatrix) {
  412. SkMatrix m;
  413. m.set9(config.fGlobalMatrix);
  414. canvas->save();
  415. canvas->concat(m);
  416. }
  417. canvas->drawPaint(paint);
  418. }
  419. }
  420. }
  421. static void test_sweep_fuzzer(skiatest::Reporter*) {
  422. static const SkColor gColors0[] = { 0x30303030, 0x30303030, 0x30303030 };
  423. static const SkScalar gPos0[] = { -47919293023455565225163489280.0f, 0, 1 };
  424. static const SkScalar gMatrix0[9] = {
  425. 1.12116716e-13f, 0 , 8.50489682e+16f,
  426. 4.1917041e-41f , 3.51369881e-23f, -2.54344271e-26f,
  427. 9.61111907e+17f, -3.35263808e-29f, -1.35659403e+14f
  428. };
  429. static const struct {
  430. SkPoint fCenter;
  431. const SkColor* fColors;
  432. const SkScalar* fPos;
  433. int fCount;
  434. const SkScalar* fGlobalMatrix;
  435. } gConfigs[] = {
  436. {
  437. { 0, 0 },
  438. gColors0,
  439. gPos0,
  440. SK_ARRAY_COUNT(gColors0),
  441. gMatrix0
  442. },
  443. };
  444. sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(100, 100);
  445. SkCanvas* canvas = surface->getCanvas();
  446. SkPaint paint;
  447. for (const auto& config : gConfigs) {
  448. paint.setShader(SkGradientShader::MakeSweep(config.fCenter.x(),
  449. config.fCenter.y(),
  450. config.fColors,
  451. config.fPos,
  452. config.fCount));
  453. SkAutoCanvasRestore acr(canvas, false);
  454. if (config.fGlobalMatrix) {
  455. SkMatrix m;
  456. m.set9(config.fGlobalMatrix);
  457. canvas->save();
  458. canvas->concat(m);
  459. }
  460. canvas->drawPaint(paint);
  461. }
  462. }
  463. DEF_TEST(Gradient, reporter) {
  464. TestGradientShaders(reporter);
  465. TestGradientOptimization(reporter);
  466. TestConstantGradient(reporter);
  467. test_big_grad(reporter);
  468. test_nearly_vertical(reporter);
  469. test_vertical(reporter);
  470. test_linear_fuzz(reporter);
  471. test_two_point_conical_zero_radius(reporter);
  472. test_clamping_overflow(reporter);
  473. test_degenerate_linear(reporter);
  474. test_linear_fuzzer(reporter);
  475. test_sweep_fuzzer(reporter);
  476. }