xref: /aosp_15_r20/external/skia/fuzz/FuzzGradients.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
8 #include "fuzz/Fuzz.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkSurface.h"
11 #include "include/effects/SkGradientShader.h"
12 #include "src/base/SkTLazy.h"
13 #include "src/core/SkDebugUtils.h"
14 #include "tools/flags/CommandLineFlags.h"
15 
16 #include <algorithm>
17 #include <vector>
18 
19 static DEFINE_bool2(verbose, v, false, "log verbose linear gradient description");
20 
21 const int MAX_COUNT = 400;
22 
makeMatrix(Fuzz * fuzz,SkMatrix * m)23 void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
24     SkScalar mat[9];
25     fuzz->nextN(mat, 9);
26     m->set9(mat);
27 }
28 
initGradientParams(Fuzz * fuzz,std::vector<SkColor> * colors,std::vector<SkScalar> * pos,SkTileMode * mode)29 void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
30                         std::vector<SkScalar>* pos, SkTileMode* mode) {
31     int count;
32     fuzz->nextRange(&count, 0, MAX_COUNT);
33 
34     // 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);
38     *mode = static_cast<SkTileMode>(m);
39 
40     colors->clear();
41     pos   ->clear();
42     for (int i = 0; i < count; i++) {
43         SkColor c;
44         SkScalar s;
45         fuzz->next(&c, &s);
46         colors->push_back(c);
47         pos   ->push_back(s);
48     }
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     }
55 }
56 
logOptionalMatrix(const char * label,const SkMatrix * m)57 static void logOptionalMatrix(const char* label, const SkMatrix* m) {
58     if (!m) {
59         return;
60     }
61 
62     SkDEBUGF("  %s: [ ", label);
63     for (int i = 0; i < 9; ++i) {
64         SkDEBUGF("%.9g ", m->get(i));
65     }
66     SkDEBUGF("]\n");
67 }
68 
logLinearGradient(const SkPoint pts[2],const std::vector<SkColor> & colors,const std::vector<SkScalar> & pos,SkTileMode mode,uint32_t flags,const SkMatrix * localMatrix,const SkMatrix * globalMatrix)69 static void logLinearGradient(const SkPoint pts[2],
70                               const std::vector<SkColor>& colors,
71                               const std::vector<SkScalar>& pos,
72                               SkTileMode mode,
73                               uint32_t flags,
74                               const SkMatrix* localMatrix,
75                               const SkMatrix* globalMatrix) {
76     if (!FLAGS_verbose) {
77         return;
78     }
79 
80     SkDebugf("--- fuzzLinearGradient ---\n");
81     SkDebugf("  pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
82              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 
99     SkDebugf("  mode:\t\t%s\n", SkTileModeToStr(mode));
100     SkDebugf("  flags:\t0x%x\n", flags);
101     logOptionalMatrix("local matrix", localMatrix);
102     logOptionalMatrix("global matrix", globalMatrix);
103 }
104 
fuzzLinearGradient(Fuzz * fuzz)105 void fuzzLinearGradient(Fuzz* fuzz) {
106     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);
110 
111     std::vector<SkColor> colors;
112     std::vector<SkScalar> pos;
113     SkTileMode mode;
114     initGradientParams(fuzz, &colors, &pos, &mode);
115 
116     SkPaint p;
117     uint32_t flags;
118     fuzz->next(&flags);
119 
120     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()));
126 
127     sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
128     if (useGlobalMatrix) {
129         SkMatrix gm;
130         makeMatrix(fuzz, &gm);
131         logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
132         SkCanvas* c = surface->getCanvas();
133         c->setMatrix(gm);
134         c->drawPaint(p);
135     } else {
136         logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
137         surface->getCanvas()->drawPaint(p);
138     }
139 }
140 
fuzzRadialGradient(Fuzz * fuzz)141 void fuzzRadialGradient(Fuzz* fuzz) {
142     SkPoint center;
143     fuzz->next(&center.fX, &center.fY);
144     SkScalar radius;
145     bool useLocalMatrix, useGlobalMatrix;
146     fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
147 
148 
149     std::vector<SkColor> colors;
150     std::vector<SkScalar> pos;
151     SkTileMode mode;
152     initGradientParams(fuzz, &colors, &pos, &mode);
153 
154     SkPaint p;
155     uint32_t flags;
156     fuzz->next(&flags);
157 
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 
165     sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
166     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     }
175 }
176 
fuzzTwoPointConicalGradient(Fuzz * fuzz)177 void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
178     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);
185 
186     std::vector<SkColor> colors;
187     std::vector<SkScalar> pos;
188     SkTileMode mode;
189     initGradientParams(fuzz, &colors, &pos, &mode);
190 
191     SkPaint p;
192     uint32_t flags;
193     fuzz->next(&flags);
194 
195     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()));
202 
203     sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
204     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     }
213 }
214 
fuzzSweepGradient(Fuzz * fuzz)215 void fuzzSweepGradient(Fuzz* fuzz) {
216     SkScalar cx, cy;
217     bool useLocalMatrix, useGlobalMatrix;
218     fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
219 
220     std::vector<SkColor> colors;
221     std::vector<SkScalar> pos;
222     SkTileMode mode;
223     initGradientParams(fuzz, &colors, &pos, &mode);
224 
225     SkPaint p;
226     if (useLocalMatrix) {
227         SkMatrix m;
228         makeMatrix(fuzz, &m);
229         uint32_t flags;
230         fuzz->next(&flags);
231 
232         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     }
238 
239     sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
240     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     }
249 }
250 
DEF_FUZZ(Gradients,fuzz)251 DEF_FUZZ(Gradients, fuzz) {
252     uint8_t i;
253     fuzz->next(&i);
254 
255     switch(i) {
256         case 0:
257             SkDEBUGF("LinearGradient\n");
258             fuzzLinearGradient(fuzz);
259             return;
260         case 1:
261             SkDEBUGF("RadialGradient\n");
262             fuzzRadialGradient(fuzz);
263             return;
264         case 2:
265             SkDEBUGF("TwoPointConicalGradient\n");
266             fuzzTwoPointConicalGradient(fuzz);
267             return;
268     }
269     SkDEBUGF("SweepGradient\n");
270     fuzzSweepGradient(fuzz);
271     return;
272 }
273