blob: 958c29cd080327e3faa50114276457140268f281 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "fuzz/Fuzz.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkSurface.h"
11#include "include/effects/SkGradientShader.h"
Kevin Lubick1b3aa8b2023-01-19 14:03:31 -050012#include "src/base/SkTLazy.h"
Robert Phillipsbf489ab2022-01-11 10:41:44 -050013#include "src/core/SkDebugUtils.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "tools/flags/CommandLineFlags.h"
kjlubick1eda1eb2016-08-12 06:26:03 -070015
16#include <algorithm>
Kevin Lubick2f535ce2016-11-01 15:01:12 -040017#include <vector>
kjlubick1eda1eb2016-08-12 06:26:03 -070018
Mike Kleinc6142d82019-03-25 10:54:59 -050019static DEFINE_bool2(verbose, v, false, "log verbose linear gradient description");
20
kjlubick1eda1eb2016-08-12 06:26:03 -070021const int MAX_COUNT = 400;
22
Kevin Lubick2f535ce2016-11-01 15:01:12 -040023void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
Kevin Lubick416b2482016-11-10 16:17:49 -050024 SkScalar mat[9];
25 fuzz->nextN(mat, 9);
26 m->set9(mat);
kjlubick1eda1eb2016-08-12 06:26:03 -070027}
28
Kevin Lubick2f535ce2016-11-01 15:01:12 -040029void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
Mike Reedfae8fce2019-04-03 10:27:45 -040030 std::vector<SkScalar>* pos, SkTileMode* mode) {
Kevin Lubick416b2482016-11-10 16:17:49 -050031 int count;
32 fuzz->nextRange(&count, 0, MAX_COUNT);
kjlubick1eda1eb2016-08-12 06:26:03 -070033
Kevin Lubick416b2482016-11-10 16:17:49 -050034 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
35 // smaller, which leads to more efficient fuzzing.
36 uint8_t m;
37 fuzz->nextRange(&m, 0, 2);
Mike Reedfae8fce2019-04-03 10:27:45 -040038 *mode = static_cast<SkTileMode>(m);
kjlubick840f12a2016-10-25 06:11:05 -070039
40 colors->clear();
41 pos ->clear();
Kevin Lubick2f535ce2016-11-01 15:01:12 -040042 for (int i = 0; i < count; i++) {
Kevin Lubick416b2482016-11-10 16:17:49 -050043 SkColor c;
44 SkScalar s;
45 fuzz->next(&c, &s);
46 colors->push_back(c);
47 pos ->push_back(s);
kjlubick840f12a2016-10-25 06:11:05 -070048 }
49 if (count) {
50 std::sort(pos->begin(), pos->end());
51 // The order matters. If count == 1, we want pos == 0.
52 (*pos)[count - 1] = 1;
53 (*pos)[0] = 0;
54 }
kjlubick1eda1eb2016-08-12 06:26:03 -070055}
56
Florin Malita75435bf2017-02-09 11:31:32 -050057static void logOptionalMatrix(const char* label, const SkMatrix* m) {
58 if (!m) {
59 return;
60 }
61
Hal Canary2b0e6cd2018-07-09 12:43:39 -040062 SkDEBUGF(" %s: [ ", label);
Florin Malita75435bf2017-02-09 11:31:32 -050063 for (int i = 0; i < 9; ++i) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -040064 SkDEBUGF("%.9g ", m->get(i));
Florin Malita75435bf2017-02-09 11:31:32 -050065 }
Hal Canary2b0e6cd2018-07-09 12:43:39 -040066 SkDEBUGF("]\n");
Florin Malita75435bf2017-02-09 11:31:32 -050067}
68
69static void logLinearGradient(const SkPoint pts[2],
70 const std::vector<SkColor>& colors,
John Stiles04a9f722023-10-19 11:46:34 -040071 const std::vector<SkScalar>& pos,
Mike Reedfae8fce2019-04-03 10:27:45 -040072 SkTileMode mode,
Florin Malita75435bf2017-02-09 11:31:32 -050073 uint32_t flags,
74 const SkMatrix* localMatrix,
75 const SkMatrix* globalMatrix) {
76 if (!FLAGS_verbose) {
77 return;
78 }
79
80 SkDebugf("--- fuzzLinearGradient ---\n");
Florin Malita3d1a6bc2017-02-09 15:05:15 -050081 SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
Florin Malita75435bf2017-02-09 11:31:32 -050082 pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
83 SkDebugf(" colors:\t[ ");
84 for (auto color : colors) {
85 SkDebugf("0x%x ", color);
86 }
87
88 SkDebugf("]\n pos:\t\t");
89 if (pos.empty()) {
90 SkDebugf("nullptr");
91 } else {
92 SkDebugf("[ ");
93 for (auto p : pos) {
94 SkDebugf("%f ", p);
95 }
96 }
97 SkDebugf("]\n");
98
Robert Phillipsbf489ab2022-01-11 10:41:44 -050099 SkDebugf(" mode:\t\t%s\n", SkTileModeToStr(mode));
Florin Malita75435bf2017-02-09 11:31:32 -0500100 SkDebugf(" flags:\t0x%x\n", flags);
101 logOptionalMatrix("local matrix", localMatrix);
102 logOptionalMatrix("global matrix", globalMatrix);
103}
104
kjlubick1eda1eb2016-08-12 06:26:03 -0700105void fuzzLinearGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500106 SkPoint pts[2];
107 fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
108 bool useLocalMatrix, useGlobalMatrix;
109 fuzz->next(&useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700110
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400111 std::vector<SkColor> colors;
112 std::vector<SkScalar> pos;
Mike Reedfae8fce2019-04-03 10:27:45 -0400113 SkTileMode mode;
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400114 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700115
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400116 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500117 uint32_t flags;
118 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700119
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400120 SkTLazy<SkMatrix> localMatrix;
121 if (useLocalMatrix) {
122 makeMatrix(fuzz, localMatrix.init());
123 }
124 p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
125 colors.size(), mode, flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700126
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400127 sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400128 if (useGlobalMatrix) {
129 SkMatrix gm;
130 makeMatrix(fuzz, &gm);
Florin Malita75435bf2017-02-09 11:31:32 -0500131 logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400132 SkCanvas* c = surface->getCanvas();
133 c->setMatrix(gm);
134 c->drawPaint(p);
135 } else {
Florin Malita75435bf2017-02-09 11:31:32 -0500136 logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400137 surface->getCanvas()->drawPaint(p);
138 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700139}
140
141void fuzzRadialGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500142 SkPoint center;
143 fuzz->next(&center.fX, &center.fY);
144 SkScalar radius;
145 bool useLocalMatrix, useGlobalMatrix;
146 fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700147
148
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400149 std::vector<SkColor> colors;
150 std::vector<SkScalar> pos;
Mike Reedfae8fce2019-04-03 10:27:45 -0400151 SkTileMode mode;
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400152 initGradientParams(fuzz, &colors, &pos, &mode);
153
154 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500155 uint32_t flags;
156 fuzz->next(&flags);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400157
158 SkTLazy<SkMatrix> localMatrix;
159 if (useLocalMatrix) {
160 makeMatrix(fuzz, localMatrix.init());
161 }
162 p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
163 pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
164
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400165 sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400166 if (useGlobalMatrix) {
167 SkMatrix gm;
168 makeMatrix(fuzz, &gm);
169 SkCanvas* c = surface->getCanvas();
170 c->setMatrix(gm);
171 c->drawPaint(p);
172 } else {
173 surface->getCanvas()->drawPaint(p);
174 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700175}
176
177void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500178 SkPoint start;
179 fuzz->next(&start.fX, &start.fY);
180 SkPoint end;
181 fuzz->next(&end.fX, &end.fY);
182 SkScalar startRadius, endRadius;
183 bool useLocalMatrix, useGlobalMatrix;
184 fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700185
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400186 std::vector<SkColor> colors;
187 std::vector<SkScalar> pos;
Mike Reedfae8fce2019-04-03 10:27:45 -0400188 SkTileMode mode;
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400189 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700190
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400191 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500192 uint32_t flags;
193 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700194
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400195 SkTLazy<SkMatrix> localMatrix;
196 if (useLocalMatrix) {
197 makeMatrix(fuzz, localMatrix.init());
198 }
199 p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
200 end, endRadius, colors.data(), pos.data(), colors.size(), mode,
201 flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700202
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400203 sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400204 if (useGlobalMatrix) {
205 SkMatrix gm;
206 makeMatrix(fuzz, &gm);
207 SkCanvas* c = surface->getCanvas();
208 c->setMatrix(gm);
209 c->drawPaint(p);
210 } else {
211 surface->getCanvas()->drawPaint(p);
212 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700213}
214
215void fuzzSweepGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500216 SkScalar cx, cy;
217 bool useLocalMatrix, useGlobalMatrix;
218 fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700219
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400220 std::vector<SkColor> colors;
221 std::vector<SkScalar> pos;
Mike Reedfae8fce2019-04-03 10:27:45 -0400222 SkTileMode mode;
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400223 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700224
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400225 SkPaint p;
226 if (useLocalMatrix) {
227 SkMatrix m;
228 makeMatrix(fuzz, &m);
Kevin Lubick416b2482016-11-10 16:17:49 -0500229 uint32_t flags;
230 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700231
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400232 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
233 pos.data(), colors.size(), flags, &m));
234 } else {
235 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
236 pos.data(), colors.size()));
237 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700238
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400239 sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400240 if (useGlobalMatrix) {
241 SkMatrix gm;
242 makeMatrix(fuzz, &gm);
243 SkCanvas* c = surface->getCanvas();
244 c->setMatrix(gm);
245 c->drawPaint(p);
246 } else {
247 surface->getCanvas()->drawPaint(p);
248 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700249}
250
251DEF_FUZZ(Gradients, fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500252 uint8_t i;
253 fuzz->next(&i);
kjlubick1eda1eb2016-08-12 06:26:03 -0700254
255 switch(i) {
256 case 0:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400257 SkDEBUGF("LinearGradient\n");
kjlubick1eda1eb2016-08-12 06:26:03 -0700258 fuzzLinearGradient(fuzz);
259 return;
260 case 1:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400261 SkDEBUGF("RadialGradient\n");
kjlubick1eda1eb2016-08-12 06:26:03 -0700262 fuzzRadialGradient(fuzz);
263 return;
264 case 2:
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400265 SkDEBUGF("TwoPointConicalGradient\n");
kjlubick1eda1eb2016-08-12 06:26:03 -0700266 fuzzTwoPointConicalGradient(fuzz);
267 return;
268 }
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400269 SkDEBUGF("SweepGradient\n");
kjlubick1eda1eb2016-08-12 06:26:03 -0700270 fuzzSweepGradient(fuzz);
271 return;
272}