/src/skia/fuzz/FuzzGradients.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
23 | 453 | void makeMatrix(Fuzz* fuzz, SkMatrix* m) { |
24 | 453 | SkScalar mat[9]; |
25 | 453 | fuzz->nextN(mat, 9); |
26 | 453 | m->set9(mat); |
27 | 453 | } |
28 | | |
29 | | void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors, |
30 | 877 | std::vector<SkScalar>* pos, SkTileMode* mode) { |
31 | 877 | int count; |
32 | 877 | 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 | 877 | uint8_t m; |
37 | 877 | fuzz->nextRange(&m, 0, 2); |
38 | 877 | *mode = static_cast<SkTileMode>(m); |
39 | | |
40 | 877 | colors->clear(); |
41 | 877 | pos ->clear(); |
42 | 133k | for (int i = 0; i < count; i++) { |
43 | 132k | SkColor c; |
44 | 132k | SkScalar s; |
45 | 132k | fuzz->next(&c, &s); |
46 | 132k | colors->push_back(c); |
47 | 132k | pos ->push_back(s); |
48 | 132k | } |
49 | 877 | if (count) { |
50 | 814 | std::sort(pos->begin(), pos->end()); |
51 | | // The order matters. If count == 1, we want pos == 0. |
52 | 814 | (*pos)[count - 1] = 1; |
53 | 814 | (*pos)[0] = 0; |
54 | 814 | } |
55 | 877 | } |
56 | | |
57 | 0 | static void logOptionalMatrix(const char* label, const SkMatrix* m) { |
58 | 0 | if (!m) { |
59 | 0 | return; |
60 | 0 | } |
61 | | |
62 | 0 | SkDEBUGF(" %s: [ ", label); |
63 | 0 | for (int i = 0; i < 9; ++i) { |
64 | 0 | SkDEBUGF("%.9g ", m->get(i)); |
65 | 0 | } |
66 | 0 | SkDEBUGF("]\n"); |
67 | 0 | } |
68 | | |
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 | 125 | const SkMatrix* globalMatrix) { |
76 | 125 | if (!FLAGS_verbose) { |
77 | 125 | return; |
78 | 125 | } |
79 | | |
80 | 0 | SkDebugf("--- fuzzLinearGradient ---\n"); |
81 | 0 | SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n", |
82 | 0 | pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y()); |
83 | 0 | SkDebugf(" colors:\t[ "); |
84 | 0 | for (auto color : colors) { |
85 | 0 | SkDebugf("0x%x ", color); |
86 | 0 | } |
87 | |
|
88 | 0 | SkDebugf("]\n pos:\t\t"); |
89 | 0 | if (pos.empty()) { |
90 | 0 | SkDebugf("nullptr"); |
91 | 0 | } else { |
92 | 0 | SkDebugf("[ "); |
93 | 0 | for (auto p : pos) { |
94 | 0 | SkDebugf("%f ", p); |
95 | 0 | } |
96 | 0 | } |
97 | 0 | SkDebugf("]\n"); |
98 | |
|
99 | 0 | SkDebugf(" mode:\t\t%s\n", SkTileModeToStr(mode)); |
100 | 0 | SkDebugf(" flags:\t0x%x\n", flags); |
101 | 0 | logOptionalMatrix("local matrix", localMatrix); |
102 | 0 | logOptionalMatrix("global matrix", globalMatrix); |
103 | 0 | } |
104 | | |
105 | 125 | void fuzzLinearGradient(Fuzz* fuzz) { |
106 | 125 | SkPoint pts[2]; |
107 | 125 | fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY); |
108 | 125 | bool useLocalMatrix, useGlobalMatrix; |
109 | 125 | fuzz->next(&useLocalMatrix, &useGlobalMatrix); |
110 | | |
111 | 125 | std::vector<SkColor> colors; |
112 | 125 | std::vector<SkScalar> pos; |
113 | 125 | SkTileMode mode; |
114 | 125 | initGradientParams(fuzz, &colors, &pos, &mode); |
115 | | |
116 | 125 | SkPaint p; |
117 | 125 | uint32_t flags; |
118 | 125 | fuzz->next(&flags); |
119 | | |
120 | 125 | SkTLazy<SkMatrix> localMatrix; |
121 | 125 | if (useLocalMatrix) { |
122 | 7 | makeMatrix(fuzz, localMatrix.init()); |
123 | 7 | } |
124 | 125 | p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), |
125 | 125 | colors.size(), mode, flags, localMatrix.getMaybeNull())); |
126 | | |
127 | 125 | sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50))); |
128 | 125 | if (useGlobalMatrix) { |
129 | 38 | SkMatrix gm; |
130 | 38 | makeMatrix(fuzz, &gm); |
131 | 38 | logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm); |
132 | 38 | SkCanvas* c = surface->getCanvas(); |
133 | 38 | c->setMatrix(gm); |
134 | 38 | c->drawPaint(p); |
135 | 87 | } else { |
136 | 87 | logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr); |
137 | 87 | surface->getCanvas()->drawPaint(p); |
138 | 87 | } |
139 | 125 | } |
140 | | |
141 | 86 | void fuzzRadialGradient(Fuzz* fuzz) { |
142 | 86 | SkPoint center; |
143 | 86 | fuzz->next(¢er.fX, ¢er.fY); |
144 | 86 | SkScalar radius; |
145 | 86 | bool useLocalMatrix, useGlobalMatrix; |
146 | 86 | fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix); |
147 | | |
148 | | |
149 | 86 | std::vector<SkColor> colors; |
150 | 86 | std::vector<SkScalar> pos; |
151 | 86 | SkTileMode mode; |
152 | 86 | initGradientParams(fuzz, &colors, &pos, &mode); |
153 | | |
154 | 86 | SkPaint p; |
155 | 86 | uint32_t flags; |
156 | 86 | fuzz->next(&flags); |
157 | | |
158 | 86 | SkTLazy<SkMatrix> localMatrix; |
159 | 86 | if (useLocalMatrix) { |
160 | 8 | makeMatrix(fuzz, localMatrix.init()); |
161 | 8 | } |
162 | 86 | p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(), |
163 | 86 | pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull())); |
164 | | |
165 | 86 | sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50))); |
166 | 86 | if (useGlobalMatrix) { |
167 | 19 | SkMatrix gm; |
168 | 19 | makeMatrix(fuzz, &gm); |
169 | 19 | SkCanvas* c = surface->getCanvas(); |
170 | 19 | c->setMatrix(gm); |
171 | 19 | c->drawPaint(p); |
172 | 67 | } else { |
173 | 67 | surface->getCanvas()->drawPaint(p); |
174 | 67 | } |
175 | 86 | } |
176 | | |
177 | 291 | void fuzzTwoPointConicalGradient(Fuzz* fuzz) { |
178 | 291 | SkPoint start; |
179 | 291 | fuzz->next(&start.fX, &start.fY); |
180 | 291 | SkPoint end; |
181 | 291 | fuzz->next(&end.fX, &end.fY); |
182 | 291 | SkScalar startRadius, endRadius; |
183 | 291 | bool useLocalMatrix, useGlobalMatrix; |
184 | 291 | fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix); |
185 | | |
186 | 291 | std::vector<SkColor> colors; |
187 | 291 | std::vector<SkScalar> pos; |
188 | 291 | SkTileMode mode; |
189 | 291 | initGradientParams(fuzz, &colors, &pos, &mode); |
190 | | |
191 | 291 | SkPaint p; |
192 | 291 | uint32_t flags; |
193 | 291 | fuzz->next(&flags); |
194 | | |
195 | 291 | SkTLazy<SkMatrix> localMatrix; |
196 | 291 | if (useLocalMatrix) { |
197 | 14 | makeMatrix(fuzz, localMatrix.init()); |
198 | 14 | } |
199 | 291 | p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius, |
200 | 291 | end, endRadius, colors.data(), pos.data(), colors.size(), mode, |
201 | 291 | flags, localMatrix.getMaybeNull())); |
202 | | |
203 | 291 | sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50))); |
204 | 291 | if (useGlobalMatrix) { |
205 | 72 | SkMatrix gm; |
206 | 72 | makeMatrix(fuzz, &gm); |
207 | 72 | SkCanvas* c = surface->getCanvas(); |
208 | 72 | c->setMatrix(gm); |
209 | 72 | c->drawPaint(p); |
210 | 219 | } else { |
211 | 219 | surface->getCanvas()->drawPaint(p); |
212 | 219 | } |
213 | 291 | } |
214 | | |
215 | 375 | void fuzzSweepGradient(Fuzz* fuzz) { |
216 | 375 | SkScalar cx, cy; |
217 | 375 | bool useLocalMatrix, useGlobalMatrix; |
218 | 375 | fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix); |
219 | | |
220 | 375 | std::vector<SkColor> colors; |
221 | 375 | std::vector<SkScalar> pos; |
222 | 375 | SkTileMode mode; |
223 | 375 | initGradientParams(fuzz, &colors, &pos, &mode); |
224 | | |
225 | 375 | SkPaint p; |
226 | 375 | if (useLocalMatrix) { |
227 | 138 | SkMatrix m; |
228 | 138 | makeMatrix(fuzz, &m); |
229 | 138 | uint32_t flags; |
230 | 138 | fuzz->next(&flags); |
231 | | |
232 | 138 | p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(), |
233 | 138 | pos.data(), colors.size(), flags, &m)); |
234 | 237 | } else { |
235 | 237 | p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(), |
236 | 237 | pos.data(), colors.size())); |
237 | 237 | } |
238 | | |
239 | 375 | sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50))); |
240 | 375 | if (useGlobalMatrix) { |
241 | 157 | SkMatrix gm; |
242 | 157 | makeMatrix(fuzz, &gm); |
243 | 157 | SkCanvas* c = surface->getCanvas(); |
244 | 157 | c->setMatrix(gm); |
245 | 157 | c->drawPaint(p); |
246 | 218 | } else { |
247 | 218 | surface->getCanvas()->drawPaint(p); |
248 | 218 | } |
249 | 375 | } |
250 | | |
251 | 877 | DEF_FUZZ(Gradients, fuzz) { |
252 | 877 | uint8_t i; |
253 | 877 | fuzz->next(&i); |
254 | | |
255 | 877 | switch(i) { |
256 | 125 | case 0: |
257 | 125 | SkDEBUGF("LinearGradient\n"); |
258 | 125 | fuzzLinearGradient(fuzz); |
259 | 125 | return; |
260 | 86 | case 1: |
261 | 86 | SkDEBUGF("RadialGradient\n"); |
262 | 86 | fuzzRadialGradient(fuzz); |
263 | 86 | return; |
264 | 291 | case 2: |
265 | 291 | SkDEBUGF("TwoPointConicalGradient\n"); |
266 | 291 | fuzzTwoPointConicalGradient(fuzz); |
267 | 291 | return; |
268 | 877 | } |
269 | 375 | SkDEBUGF("SweepGradient\n"); |
270 | 375 | fuzzSweepGradient(fuzz); |
271 | 375 | return; |
272 | 877 | } |