blob: 88f3429d50a3777dd868efb88a26a10587561760 [file] [log] [blame]
kjlubick1eda1eb2016-08-12 06:26:03 -07001/*
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
8#include "Fuzz.h"
9#include "SkCanvas.h"
Florin Malita75435bf2017-02-09 11:31:32 -050010#include "SkCommonFlags.h"
kjlubick1eda1eb2016-08-12 06:26:03 -070011#include "SkGradientShader.h"
12#include "SkSurface.h"
13#include "SkTLazy.h"
14
15#include <algorithm>
Kevin Lubick2f535ce2016-11-01 15:01:12 -040016#include <vector>
kjlubick1eda1eb2016-08-12 06:26:03 -070017
18const int MAX_COUNT = 400;
19
Kevin Lubick2f535ce2016-11-01 15:01:12 -040020void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
Kevin Lubick416b2482016-11-10 16:17:49 -050021 SkScalar mat[9];
22 fuzz->nextN(mat, 9);
23 m->set9(mat);
kjlubick1eda1eb2016-08-12 06:26:03 -070024}
25
Kevin Lubick2f535ce2016-11-01 15:01:12 -040026void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
27 std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
Kevin Lubick416b2482016-11-10 16:17:49 -050028 int count;
29 fuzz->nextRange(&count, 0, MAX_COUNT);
kjlubick1eda1eb2016-08-12 06:26:03 -070030
Kevin Lubick416b2482016-11-10 16:17:49 -050031 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
32 // smaller, which leads to more efficient fuzzing.
33 uint8_t m;
34 fuzz->nextRange(&m, 0, 2);
35 *mode = static_cast<SkShader::TileMode>(m);
kjlubick840f12a2016-10-25 06:11:05 -070036
37 colors->clear();
38 pos ->clear();
Kevin Lubick2f535ce2016-11-01 15:01:12 -040039 for (int i = 0; i < count; i++) {
Kevin Lubick416b2482016-11-10 16:17:49 -050040 SkColor c;
41 SkScalar s;
42 fuzz->next(&c, &s);
43 colors->push_back(c);
44 pos ->push_back(s);
kjlubick840f12a2016-10-25 06:11:05 -070045 }
46 if (count) {
47 std::sort(pos->begin(), pos->end());
48 // The order matters. If count == 1, we want pos == 0.
49 (*pos)[count - 1] = 1;
50 (*pos)[0] = 0;
51 }
kjlubick1eda1eb2016-08-12 06:26:03 -070052}
53
Florin Malita75435bf2017-02-09 11:31:32 -050054static void logOptionalMatrix(const char* label, const SkMatrix* m) {
55 if (!m) {
56 return;
57 }
58
59 SkDebugf(" %s: [ ", label);
60 for (int i = 0; i < 9; ++i) {
61 SkDebugf("%.9g ", m->get(i));
62 }
63 SkDebugf("]\n");
64}
65
66static void logLinearGradient(const SkPoint pts[2],
67 const std::vector<SkColor>& colors,
68 const std::vector<SkScalar> pos,
69 SkShader::TileMode mode,
70 uint32_t flags,
71 const SkMatrix* localMatrix,
72 const SkMatrix* globalMatrix) {
73 if (!FLAGS_verbose) {
74 return;
75 }
76
77 SkDebugf("--- fuzzLinearGradient ---\n");
Florin Malita3d1a6bc2017-02-09 15:05:15 -050078 SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
Florin Malita75435bf2017-02-09 11:31:32 -050079 pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
80 SkDebugf(" colors:\t[ ");
81 for (auto color : colors) {
82 SkDebugf("0x%x ", color);
83 }
84
85 SkDebugf("]\n pos:\t\t");
86 if (pos.empty()) {
87 SkDebugf("nullptr");
88 } else {
89 SkDebugf("[ ");
90 for (auto p : pos) {
91 SkDebugf("%f ", p);
92 }
93 }
94 SkDebugf("]\n");
95
96 static const char* gModeName[] = {
97 "kClamp_TileMode", "kRepeat_TileMode", "kMirror_TileMode"
98 };
99 SkASSERT(mode < SK_ARRAY_COUNT(gModeName));
100 SkDebugf(" mode:\t\t%s\n", gModeName[mode]);
101 SkDebugf(" flags:\t0x%x\n", flags);
102 logOptionalMatrix("local matrix", localMatrix);
103 logOptionalMatrix("global matrix", globalMatrix);
104}
105
kjlubick1eda1eb2016-08-12 06:26:03 -0700106void fuzzLinearGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500107 SkPoint pts[2];
108 fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
109 bool useLocalMatrix, useGlobalMatrix;
110 fuzz->next(&useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700111
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400112 std::vector<SkColor> colors;
113 std::vector<SkScalar> pos;
114 SkShader::TileMode mode;
115 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700116
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400117 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500118 uint32_t flags;
119 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700120
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400121 SkTLazy<SkMatrix> localMatrix;
122 if (useLocalMatrix) {
123 makeMatrix(fuzz, localMatrix.init());
124 }
125 p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
126 colors.size(), mode, flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700127
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400128 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
129 if (useGlobalMatrix) {
130 SkMatrix gm;
131 makeMatrix(fuzz, &gm);
Florin Malita75435bf2017-02-09 11:31:32 -0500132 logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400133 SkCanvas* c = surface->getCanvas();
134 c->setMatrix(gm);
135 c->drawPaint(p);
136 } else {
Florin Malita75435bf2017-02-09 11:31:32 -0500137 logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400138 surface->getCanvas()->drawPaint(p);
139 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700140}
141
142void fuzzRadialGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500143 SkPoint center;
144 fuzz->next(&center.fX, &center.fY);
145 SkScalar radius;
146 bool useLocalMatrix, useGlobalMatrix;
147 fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700148
149
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400150 std::vector<SkColor> colors;
151 std::vector<SkScalar> pos;
152 SkShader::TileMode mode;
153 initGradientParams(fuzz, &colors, &pos, &mode);
154
155 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500156 uint32_t flags;
157 fuzz->next(&flags);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400158
159 SkTLazy<SkMatrix> localMatrix;
160 if (useLocalMatrix) {
161 makeMatrix(fuzz, localMatrix.init());
162 }
163 p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
164 pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
165
166
167 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
168 if (useGlobalMatrix) {
169 SkMatrix gm;
170 makeMatrix(fuzz, &gm);
171 SkCanvas* c = surface->getCanvas();
172 c->setMatrix(gm);
173 c->drawPaint(p);
174 } else {
175 surface->getCanvas()->drawPaint(p);
176 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700177}
178
179void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500180 SkPoint start;
181 fuzz->next(&start.fX, &start.fY);
182 SkPoint end;
183 fuzz->next(&end.fX, &end.fY);
184 SkScalar startRadius, endRadius;
185 bool useLocalMatrix, useGlobalMatrix;
186 fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700187
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400188 std::vector<SkColor> colors;
189 std::vector<SkScalar> pos;
190 SkShader::TileMode mode;
191 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700192
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400193 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500194 uint32_t flags;
195 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700196
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400197 SkTLazy<SkMatrix> localMatrix;
198 if (useLocalMatrix) {
199 makeMatrix(fuzz, localMatrix.init());
200 }
201 p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
202 end, endRadius, colors.data(), pos.data(), colors.size(), mode,
203 flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700204
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400205 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
206 if (useGlobalMatrix) {
207 SkMatrix gm;
208 makeMatrix(fuzz, &gm);
209 SkCanvas* c = surface->getCanvas();
210 c->setMatrix(gm);
211 c->drawPaint(p);
212 } else {
213 surface->getCanvas()->drawPaint(p);
214 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700215}
216
217void fuzzSweepGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500218 SkScalar cx, cy;
219 bool useLocalMatrix, useGlobalMatrix;
220 fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700221
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400222 std::vector<SkColor> colors;
223 std::vector<SkScalar> pos;
224 SkShader::TileMode mode;
225 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700226
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400227 SkPaint p;
228 if (useLocalMatrix) {
229 SkMatrix m;
230 makeMatrix(fuzz, &m);
Kevin Lubick416b2482016-11-10 16:17:49 -0500231 uint32_t flags;
232 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700233
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400234 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
235 pos.data(), colors.size(), flags, &m));
236 } else {
237 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
238 pos.data(), colors.size()));
239 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700240
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400241 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
242 if (useGlobalMatrix) {
243 SkMatrix gm;
244 makeMatrix(fuzz, &gm);
245 SkCanvas* c = surface->getCanvas();
246 c->setMatrix(gm);
247 c->drawPaint(p);
248 } else {
249 surface->getCanvas()->drawPaint(p);
250 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700251}
252
253DEF_FUZZ(Gradients, fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500254 uint8_t i;
255 fuzz->next(&i);
kjlubick1eda1eb2016-08-12 06:26:03 -0700256
257 switch(i) {
258 case 0:
259 SkDebugf("LinearGradient\n");
260 fuzzLinearGradient(fuzz);
261 return;
262 case 1:
263 SkDebugf("RadialGradient\n");
264 fuzzRadialGradient(fuzz);
265 return;
266 case 2:
267 SkDebugf("TwoPointConicalGradient\n");
268 fuzzTwoPointConicalGradient(fuzz);
269 return;
270 }
271 SkDebugf("SweepGradient\n");
272 fuzzSweepGradient(fuzz);
273 return;
274}