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