• 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/SkDebugUtils.h"
13 #include "src/core/SkTLazy.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(SkSurface::MakeRasterN32Premul(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 
166     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
167     if (useGlobalMatrix) {
168         SkMatrix gm;
169         makeMatrix(fuzz, &gm);
170         SkCanvas* c = surface->getCanvas();
171         c->setMatrix(gm);
172         c->drawPaint(p);
173     } else {
174         surface->getCanvas()->drawPaint(p);
175     }
176 }
177 
fuzzTwoPointConicalGradient(Fuzz * fuzz)178 void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
179     SkPoint start;
180     fuzz->next(&start.fX, &start.fY);
181     SkPoint end;
182     fuzz->next(&end.fX, &end.fY);
183     SkScalar startRadius, endRadius;
184     bool useLocalMatrix, useGlobalMatrix;
185     fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
186 
187     std::vector<SkColor> colors;
188     std::vector<SkScalar> pos;
189     SkTileMode mode;
190     initGradientParams(fuzz, &colors, &pos, &mode);
191 
192     SkPaint p;
193     uint32_t flags;
194     fuzz->next(&flags);
195 
196     SkTLazy<SkMatrix> localMatrix;
197     if (useLocalMatrix) {
198         makeMatrix(fuzz, localMatrix.init());
199     }
200     p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
201         end, endRadius, colors.data(), pos.data(), colors.size(), mode,
202         flags, localMatrix.getMaybeNull()));
203 
204     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
205     if (useGlobalMatrix) {
206         SkMatrix gm;
207         makeMatrix(fuzz, &gm);
208         SkCanvas* c = surface->getCanvas();
209         c->setMatrix(gm);
210         c->drawPaint(p);
211     } else {
212         surface->getCanvas()->drawPaint(p);
213     }
214 }
215 
fuzzSweepGradient(Fuzz * fuzz)216 void fuzzSweepGradient(Fuzz* fuzz) {
217     SkScalar cx, cy;
218     bool useLocalMatrix, useGlobalMatrix;
219     fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
220 
221     std::vector<SkColor> colors;
222     std::vector<SkScalar> pos;
223     SkTileMode mode;
224     initGradientParams(fuzz, &colors, &pos, &mode);
225 
226     SkPaint p;
227     if (useLocalMatrix) {
228         SkMatrix m;
229         makeMatrix(fuzz, &m);
230         uint32_t flags;
231         fuzz->next(&flags);
232 
233         p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
234             pos.data(), colors.size(), flags, &m));
235     } else {
236         p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
237             pos.data(), colors.size()));
238     }
239 
240     sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
241     if (useGlobalMatrix) {
242         SkMatrix gm;
243         makeMatrix(fuzz, &gm);
244         SkCanvas* c = surface->getCanvas();
245         c->setMatrix(gm);
246         c->drawPaint(p);
247     } else {
248         surface->getCanvas()->drawPaint(p);
249     }
250 }
251 
DEF_FUZZ(Gradients,fuzz)252 DEF_FUZZ(Gradients, fuzz) {
253     uint8_t i;
254     fuzz->next(&i);
255 
256     switch(i) {
257         case 0:
258             SkDEBUGF("LinearGradient\n");
259             fuzzLinearGradient(fuzz);
260             return;
261         case 1:
262             SkDEBUGF("RadialGradient\n");
263             fuzzRadialGradient(fuzz);
264             return;
265         case 2:
266             SkDEBUGF("TwoPointConicalGradient\n");
267             fuzzTwoPointConicalGradient(fuzz);
268             return;
269     }
270     SkDEBUGF("SweepGradient\n");
271     fuzzSweepGradient(fuzz);
272     return;
273 }
274