FuzzGradients.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright 2016 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 "fuzz/Fuzz.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkSurface.h"
  10. #include "include/effects/SkGradientShader.h"
  11. #include "src/core/SkTLazy.h"
  12. #include "tools/flags/CommandLineFlags.h"
  13. #include <algorithm>
  14. #include <vector>
  15. static DEFINE_bool2(verbose, v, false, "log verbose linear gradient description");
  16. const int MAX_COUNT = 400;
  17. void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
  18. SkScalar mat[9];
  19. fuzz->nextN(mat, 9);
  20. m->set9(mat);
  21. }
  22. void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
  23. std::vector<SkScalar>* pos, SkTileMode* mode) {
  24. int count;
  25. fuzz->nextRange(&count, 0, MAX_COUNT);
  26. // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
  27. // smaller, which leads to more efficient fuzzing.
  28. uint8_t m;
  29. fuzz->nextRange(&m, 0, 2);
  30. *mode = static_cast<SkTileMode>(m);
  31. colors->clear();
  32. pos ->clear();
  33. for (int i = 0; i < count; i++) {
  34. SkColor c;
  35. SkScalar s;
  36. fuzz->next(&c, &s);
  37. colors->push_back(c);
  38. pos ->push_back(s);
  39. }
  40. if (count) {
  41. std::sort(pos->begin(), pos->end());
  42. // The order matters. If count == 1, we want pos == 0.
  43. (*pos)[count - 1] = 1;
  44. (*pos)[0] = 0;
  45. }
  46. }
  47. static void logOptionalMatrix(const char* label, const SkMatrix* m) {
  48. if (!m) {
  49. return;
  50. }
  51. SkDEBUGF(" %s: [ ", label);
  52. for (int i = 0; i < 9; ++i) {
  53. SkDEBUGF("%.9g ", m->get(i));
  54. }
  55. SkDEBUGF("]\n");
  56. }
  57. static void logLinearGradient(const SkPoint pts[2],
  58. const std::vector<SkColor>& colors,
  59. const std::vector<SkScalar> pos,
  60. SkTileMode mode,
  61. uint32_t flags,
  62. const SkMatrix* localMatrix,
  63. const SkMatrix* globalMatrix) {
  64. if (!FLAGS_verbose) {
  65. return;
  66. }
  67. SkDebugf("--- fuzzLinearGradient ---\n");
  68. SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
  69. pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
  70. SkDebugf(" colors:\t[ ");
  71. for (auto color : colors) {
  72. SkDebugf("0x%x ", color);
  73. }
  74. SkDebugf("]\n pos:\t\t");
  75. if (pos.empty()) {
  76. SkDebugf("nullptr");
  77. } else {
  78. SkDebugf("[ ");
  79. for (auto p : pos) {
  80. SkDebugf("%f ", p);
  81. }
  82. }
  83. SkDebugf("]\n");
  84. static const char* gModeName[] = {
  85. "kClamp_TileMode", "kRepeat_TileMode", "kMirror_TileMode", "kDecal_TileMode"
  86. };
  87. SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gModeName));
  88. SkDebugf(" mode:\t\t%s\n", gModeName[(unsigned)mode]);
  89. SkDebugf(" flags:\t0x%x\n", flags);
  90. logOptionalMatrix("local matrix", localMatrix);
  91. logOptionalMatrix("global matrix", globalMatrix);
  92. }
  93. void fuzzLinearGradient(Fuzz* fuzz) {
  94. SkPoint pts[2];
  95. fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
  96. bool useLocalMatrix, useGlobalMatrix;
  97. fuzz->next(&useLocalMatrix, &useGlobalMatrix);
  98. std::vector<SkColor> colors;
  99. std::vector<SkScalar> pos;
  100. SkTileMode mode;
  101. initGradientParams(fuzz, &colors, &pos, &mode);
  102. SkPaint p;
  103. uint32_t flags;
  104. fuzz->next(&flags);
  105. SkTLazy<SkMatrix> localMatrix;
  106. if (useLocalMatrix) {
  107. makeMatrix(fuzz, localMatrix.init());
  108. }
  109. p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
  110. colors.size(), mode, flags, localMatrix.getMaybeNull()));
  111. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  112. if (useGlobalMatrix) {
  113. SkMatrix gm;
  114. makeMatrix(fuzz, &gm);
  115. logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
  116. SkCanvas* c = surface->getCanvas();
  117. c->setMatrix(gm);
  118. c->drawPaint(p);
  119. } else {
  120. logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
  121. surface->getCanvas()->drawPaint(p);
  122. }
  123. }
  124. void fuzzRadialGradient(Fuzz* fuzz) {
  125. SkPoint center;
  126. fuzz->next(&center.fX, &center.fY);
  127. SkScalar radius;
  128. bool useLocalMatrix, useGlobalMatrix;
  129. fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
  130. std::vector<SkColor> colors;
  131. std::vector<SkScalar> pos;
  132. SkTileMode mode;
  133. initGradientParams(fuzz, &colors, &pos, &mode);
  134. SkPaint p;
  135. uint32_t flags;
  136. fuzz->next(&flags);
  137. SkTLazy<SkMatrix> localMatrix;
  138. if (useLocalMatrix) {
  139. makeMatrix(fuzz, localMatrix.init());
  140. }
  141. p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
  142. pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
  143. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  144. if (useGlobalMatrix) {
  145. SkMatrix gm;
  146. makeMatrix(fuzz, &gm);
  147. SkCanvas* c = surface->getCanvas();
  148. c->setMatrix(gm);
  149. c->drawPaint(p);
  150. } else {
  151. surface->getCanvas()->drawPaint(p);
  152. }
  153. }
  154. void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
  155. SkPoint start;
  156. fuzz->next(&start.fX, &start.fY);
  157. SkPoint end;
  158. fuzz->next(&end.fX, &end.fY);
  159. SkScalar startRadius, endRadius;
  160. bool useLocalMatrix, useGlobalMatrix;
  161. fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
  162. std::vector<SkColor> colors;
  163. std::vector<SkScalar> pos;
  164. SkTileMode mode;
  165. initGradientParams(fuzz, &colors, &pos, &mode);
  166. SkPaint p;
  167. uint32_t flags;
  168. fuzz->next(&flags);
  169. SkTLazy<SkMatrix> localMatrix;
  170. if (useLocalMatrix) {
  171. makeMatrix(fuzz, localMatrix.init());
  172. }
  173. p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
  174. end, endRadius, colors.data(), pos.data(), colors.size(), mode,
  175. flags, localMatrix.getMaybeNull()));
  176. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  177. if (useGlobalMatrix) {
  178. SkMatrix gm;
  179. makeMatrix(fuzz, &gm);
  180. SkCanvas* c = surface->getCanvas();
  181. c->setMatrix(gm);
  182. c->drawPaint(p);
  183. } else {
  184. surface->getCanvas()->drawPaint(p);
  185. }
  186. }
  187. void fuzzSweepGradient(Fuzz* fuzz) {
  188. SkScalar cx, cy;
  189. bool useLocalMatrix, useGlobalMatrix;
  190. fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
  191. std::vector<SkColor> colors;
  192. std::vector<SkScalar> pos;
  193. SkTileMode mode;
  194. initGradientParams(fuzz, &colors, &pos, &mode);
  195. SkPaint p;
  196. if (useLocalMatrix) {
  197. SkMatrix m;
  198. makeMatrix(fuzz, &m);
  199. uint32_t flags;
  200. fuzz->next(&flags);
  201. p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
  202. pos.data(), colors.size(), flags, &m));
  203. } else {
  204. p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
  205. pos.data(), colors.size()));
  206. }
  207. sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
  208. if (useGlobalMatrix) {
  209. SkMatrix gm;
  210. makeMatrix(fuzz, &gm);
  211. SkCanvas* c = surface->getCanvas();
  212. c->setMatrix(gm);
  213. c->drawPaint(p);
  214. } else {
  215. surface->getCanvas()->drawPaint(p);
  216. }
  217. }
  218. DEF_FUZZ(Gradients, fuzz) {
  219. uint8_t i;
  220. fuzz->next(&i);
  221. switch(i) {
  222. case 0:
  223. SkDEBUGF("LinearGradient\n");
  224. fuzzLinearGradient(fuzz);
  225. return;
  226. case 1:
  227. SkDEBUGF("RadialGradient\n");
  228. fuzzRadialGradient(fuzz);
  229. return;
  230. case 2:
  231. SkDEBUGF("TwoPointConicalGradient\n");
  232. fuzzTwoPointConicalGradient(fuzz);
  233. return;
  234. }
  235. SkDEBUGF("SweepGradient\n");
  236. fuzzSweepGradient(fuzz);
  237. return;
  238. }