blob: 9627be70ac23f1f6575643f4acde5f5014b37d1e [file] [log] [blame]
Hal Canary24ac42b2017-02-14 13:35:14 -05001/*
2 * Copyright 2017 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.h"
Kevin Lubick2541edf2018-01-11 10:27:14 -05009#include "FuzzCommon.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050010
11// CORE
12#include "SkCanvas.h"
13#include "SkColorFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050014#include "SkDebugCanvas.h"
15#include "SkDocument.h"
Hal Canary671e4422017-02-27 13:36:38 -050016#include "SkFontMgr.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050017#include "SkImageFilter.h"
18#include "SkMaskFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050019#include "SkNullCanvas.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040020#include "SkOSFile.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050021#include "SkPathEffect.h"
Cary Clarkefd99cc2018-06-11 16:25:43 -040022#include "SkPicturePriv.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050023#include "SkPictureRecorder.h"
Mike Reed54518ac2017-07-22 08:29:48 -040024#include "SkPoint3.h"
Hal Canary5395c592017-03-08 16:52:18 -050025#include "SkRSXform.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050026#include "SkRegion.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050027#include "SkSurface.h"
Hal Canaryc640d0d2018-06-13 09:59:02 -040028#include "SkTo.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050029#include "SkTypeface.h"
30
31// EFFECTS
Hal Canary5395c592017-03-08 16:52:18 -050032#include "Sk1DPathEffect.h"
33#include "Sk2DPathEffect.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050034#include "SkAlphaThresholdFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050035#include "SkArithmeticImageFilter.h"
Robert Phillips70e3e9a2017-06-26 14:22:01 -040036#include "SkBlurImageFilter.h"
Hal Canary5395c592017-03-08 16:52:18 -050037#include "SkBlurMaskFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050038#include "SkColorFilterImageFilter.h"
Hal Canary27bece82017-03-07 16:23:20 -050039#include "SkColorMatrixFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050040#include "SkComposeImageFilter.h"
Hal Canary5395c592017-03-08 16:52:18 -050041#include "SkCornerPathEffect.h"
42#include "SkDashPathEffect.h"
43#include "SkDiscretePathEffect.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050044#include "SkDisplacementMapEffect.h"
45#include "SkDropShadowImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050046#include "SkGradientShader.h"
Hal Canary27bece82017-03-07 16:23:20 -050047#include "SkHighContrastFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050048#include "SkImageSource.h"
49#include "SkLightingImageFilter.h"
Hal Canary27bece82017-03-07 16:23:20 -050050#include "SkLumaColorFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050051#include "SkMagnifierImageFilter.h"
52#include "SkMatrixConvolutionImageFilter.h"
53#include "SkMergeImageFilter.h"
54#include "SkMorphologyImageFilter.h"
55#include "SkOffsetImageFilter.h"
56#include "SkPaintImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050057#include "SkPerlinNoiseShader.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050058#include "SkPictureImageFilter.h"
Mike Reedfadbfcd2017-12-06 16:09:20 -050059#include "SkReadBuffer.h"
Hal Canary27bece82017-03-07 16:23:20 -050060#include "SkTableColorFilter.h"
Mike Reedc090c642017-05-16 10:39:06 -040061#include "SkTextBlob.h"
Mike Reeda62d0362018-08-28 16:26:06 -040062#include "SkTextOnPath.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050063#include "SkTileImageFilter.h"
64#include "SkXfermodeImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050065
66// SRC
Kevin Lubickfaef5142018-06-07 10:33:11 -040067#include "SkCommandLineFlags.h"
Hal Canaryea60b952018-08-21 11:45:46 -040068#include "SkUTF.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050069
Hal Canary44801ca2017-03-15 11:39:06 -040070#if SK_SUPPORT_GPU
71#include "GrContextFactory.h"
Kevin Lubickfaef5142018-06-07 10:33:11 -040072#include "GrContextPriv.h"
73#include "gl/GrGLFunctions.h"
74#include "gl/GrGLGpu.h"
75#include "gl/GrGLUtil.h"
Hal Canary44801ca2017-03-15 11:39:06 -040076#endif
77
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050078// MISC
79
80#include <iostream>
Ben Wagnerf08d1d02018-06-18 15:11:00 -040081#include <utility>
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050082
Kevin Lubickfaef5142018-06-07 10:33:11 -040083DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
84
Hal Canary24ac42b2017-02-14 13:35:14 -050085// TODO:
Hal Canary5395c592017-03-08 16:52:18 -050086// SkTextBlob with Unicode
Hal Canary44801ca2017-03-15 11:39:06 -040087// SkImage: more types
Hal Canary24ac42b2017-02-14 13:35:14 -050088
Hal Canary1e0138b2017-03-10 13:56:08 -050089// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
90// In fact, all make_fuzz_foo() functions have this potential problem.
91// Use sequence points!
92template <typename T>
93inline T make_fuzz_t(Fuzz* fuzz) {
94 T t;
95 fuzz->next(&t);
96 return t;
Hal Canary24ac42b2017-02-14 13:35:14 -050097}
98
Hal Canaryb69c4b82017-03-08 11:02:40 -050099template <>
100inline void Fuzz::next(SkShader::TileMode* m) {
Hal Canaryf7005202017-03-10 08:48:28 -0500101 fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500102}
103
Hal Canaryb69c4b82017-03-08 11:02:40 -0500104template <>
Hal Canarye03c3e52017-03-09 11:33:35 -0500105inline void Fuzz::next(SkFilterQuality* q) {
Hal Canaryf7005202017-03-10 08:48:28 -0500106 fuzz_enum_range(this, q, SkFilterQuality::kNone_SkFilterQuality,
107 SkFilterQuality::kLast_SkFilterQuality);
Hal Canarye03c3e52017-03-09 11:33:35 -0500108}
109
110template <>
Hal Canaryb69c4b82017-03-08 11:02:40 -0500111inline void Fuzz::next(SkMatrix* m) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500112 constexpr int kArrayLength = 9;
113 SkScalar buffer[kArrayLength];
114 int matrixType;
115 this->nextRange(&matrixType, 0, 4);
116 switch (matrixType) {
117 case 0: // identity
118 *m = SkMatrix::I();
119 return;
120 case 1: // translate
121 this->nextRange(&buffer[0], -4000.0f, 4000.0f);
122 this->nextRange(&buffer[1], -4000.0f, 4000.0f);
123 *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
124 return;
125 case 2: // translate + scale
126 this->nextRange(&buffer[0], -400.0f, 400.0f);
127 this->nextRange(&buffer[1], -400.0f, 400.0f);
128 this->nextRange(&buffer[2], -4000.0f, 4000.0f);
129 this->nextRange(&buffer[3], -4000.0f, 4000.0f);
130 *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
131 m->postTranslate(buffer[2], buffer[3]);
132 return;
133 case 3: // affine
134 this->nextN(buffer, 6);
135 m->setAffine(buffer);
136 return;
137 case 4: // perspective
138 this->nextN(buffer, kArrayLength);
139 m->set9(buffer);
140 return;
141 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -0500142 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -0500143 return;
144 }
145}
146
Hal Canaryb69c4b82017-03-08 11:02:40 -0500147template <>
148inline void Fuzz::next(SkRRect* rr) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500149 SkRect r;
150 SkVector radii[4];
151 this->next(&r);
Hal Canary27bece82017-03-07 16:23:20 -0500152 r.sort();
153 for (SkVector& vec : radii) {
154 this->nextRange(&vec.fX, 0.0f, 1.0f);
155 vec.fX *= 0.5f * r.width();
156 this->nextRange(&vec.fY, 0.0f, 1.0f);
157 vec.fY *= 0.5f * r.height();
158 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500159 rr->setRectRadii(r, radii);
Hal Canary24ac42b2017-02-14 13:35:14 -0500160}
161
Hal Canaryb69c4b82017-03-08 11:02:40 -0500162template <>
163inline void Fuzz::next(SkBlendMode* mode) {
Hal Canaryf7005202017-03-10 08:48:28 -0500164 fuzz_enum_range(this, mode, 0, SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -0500165}
166
Hal Canary1e0138b2017-03-10 13:56:08 -0500167static sk_sp<SkImage> make_fuzz_image(Fuzz*);
Hal Canary671e4422017-02-27 13:36:38 -0500168
Hal Canary1e0138b2017-03-10 13:56:08 -0500169static SkBitmap make_fuzz_bitmap(Fuzz*);
Hal Canary24ac42b2017-02-14 13:35:14 -0500170
Hal Canary1e0138b2017-03-10 13:56:08 -0500171static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
Hal Canary671e4422017-02-27 13:36:38 -0500172
Hal Canary1e0138b2017-03-10 13:56:08 -0500173static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
Hal Canary27bece82017-03-07 16:23:20 -0500174 if (depth <= 0) {
175 return nullptr;
176 }
177 int colorFilterType;
178 fuzz->nextRange(&colorFilterType, 0, 8);
179 switch (colorFilterType) {
180 case 0:
181 return nullptr;
182 case 1: {
183 SkColor color;
184 SkBlendMode mode;
185 fuzz->next(&color, &mode);
186 return SkColorFilter::MakeModeFilter(color, mode);
187 }
188 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500189 sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500190 if (!outer) {
191 return nullptr;
192 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500193 sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500194 // makeComposed should be able to handle nullptr.
Mike Reed19d7bd62018-02-19 14:10:57 -0500195 return outer->makeComposed(std::move(inner));
Hal Canary27bece82017-03-07 16:23:20 -0500196 }
197 case 3: {
198 SkScalar array[20];
199 fuzz->nextN(array, SK_ARRAY_COUNT(array));
200 return SkColorFilter::MakeMatrixFilterRowMajor255(array);
201 }
202 case 4: {
203 SkColor mul, add;
204 fuzz->next(&mul, &add);
205 return SkColorMatrixFilter::MakeLightingFilter(mul, add);
206 }
207 case 5: {
208 bool grayscale;
209 int invertStyle;
210 float contrast;
211 fuzz->next(&grayscale);
212 fuzz->nextRange(&invertStyle, 0, 2);
213 fuzz->nextRange(&contrast, -1.0f, 1.0f);
214 return SkHighContrastFilter::Make(SkHighContrastConfig(
215 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
216 }
217 case 6:
218 return SkLumaColorFilter::Make();
219 case 7: {
220 uint8_t table[256];
221 fuzz->nextN(table, SK_ARRAY_COUNT(table));
222 return SkTableColorFilter::Make(table);
223 }
224 case 8: {
225 uint8_t tableA[256];
226 uint8_t tableR[256];
227 uint8_t tableG[256];
228 uint8_t tableB[256];
229 fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
230 fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
231 fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
232 fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
233 return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
234 }
Kevin Lubick54f20e02018-01-11 14:50:21 -0500235 default:
236 SkASSERT(false);
237 break;
Hal Canary27bece82017-03-07 16:23:20 -0500238 }
239 return nullptr;
240}
Hal Canary24ac42b2017-02-14 13:35:14 -0500241
Hal Canary1e0138b2017-03-10 13:56:08 -0500242static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500243 SkScalar totalPos = 0;
244 for (int i = 0; i < colorCount; ++i) {
245 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
246 totalPos += pos[i];
247 }
248 totalPos = 1.0f / totalPos;
249 for (int i = 0; i < colorCount; ++i) {
250 pos[i] *= totalPos;
251 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500252 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500253 pos[colorCount - 1] = 1.0f;
254}
255
Hal Canary1e0138b2017-03-10 13:56:08 -0500256static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500257 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
258 sk_sp<SkColorFilter> colorFilter(nullptr);
259 SkBitmap bitmap;
260 sk_sp<SkImage> img;
261 SkShader::TileMode tmX, tmY;
262 bool useMatrix;
263 SkColor color;
264 SkMatrix matrix;
265 SkBlendMode blendMode;
266 int shaderType;
267 if (depth <= 0) {
268 return nullptr;
269 }
Hal Canary671e4422017-02-27 13:36:38 -0500270 fuzz->nextRange(&shaderType, 0, 14);
Hal Canary24ac42b2017-02-14 13:35:14 -0500271 switch (shaderType) {
272 case 0:
273 return nullptr;
274 case 1:
275 return SkShader::MakeEmptyShader();
276 case 2:
277 fuzz->next(&color);
278 return SkShader::MakeColorShader(color);
279 case 3:
Hal Canary1e0138b2017-03-10 13:56:08 -0500280 img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -0500281 fuzz->next(&tmX, &tmY, &useMatrix);
282 if (useMatrix) {
283 fuzz->next(&matrix);
284 }
285 return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
286 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -0500287 bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -0500288 fuzz->next(&tmX, &tmY, &useMatrix);
289 if (useMatrix) {
290 fuzz->next(&matrix);
291 }
292 return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
293 case 5:
Hal Canary1e0138b2017-03-10 13:56:08 -0500294 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
Hal Canary24ac42b2017-02-14 13:35:14 -0500295 fuzz->next(&matrix);
296 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
297 case 6:
Hal Canary1e0138b2017-03-10 13:56:08 -0500298 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
299 colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500300 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
301 case 7:
Hal Canary1e0138b2017-03-10 13:56:08 -0500302 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
303 shader2 = make_fuzz_shader(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500304 fuzz->next(&blendMode);
305 return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500306 case 8: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500307 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500308 bool useTile;
309 SkRect tile;
310 fuzz->next(&tmX, &tmY, &useMatrix, &useTile);
311 if (useMatrix) {
312 fuzz->next(&matrix);
Hal Canary671e4422017-02-27 13:36:38 -0500313 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500314 if (useTile) {
315 fuzz->next(&tile);
316 }
317 return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
318 useMatrix ? &matrix : nullptr,
319 useTile ? &tile : nullptr);
320 }
Hal Canary671e4422017-02-27 13:36:38 -0500321 // EFFECTS:
Hal Canary24ac42b2017-02-14 13:35:14 -0500322 case 9:
Florin Malitabb3f5622017-05-31 14:20:12 +0000323 // Deprecated SkGaussianEdgeShader
324 return nullptr;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500325 case 10: {
326 constexpr int kMaxColors = 12;
327 SkPoint pts[2];
328 SkColor colors[kMaxColors];
329 SkScalar pos[kMaxColors];
330 int colorCount;
331 bool usePos;
332 fuzz->nextN(pts, 2);
333 fuzz->nextRange(&colorCount, 2, kMaxColors);
334 fuzz->nextN(colors, colorCount);
335 fuzz->next(&tmX, &useMatrix, &usePos);
336 if (useMatrix) {
337 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500338 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500339 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500340 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500341 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500342 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
343 tmX, 0, useMatrix ? &matrix : nullptr);
344 }
345 case 11: {
346 constexpr int kMaxColors = 12;
347 SkPoint center;
348 SkScalar radius;
349 int colorCount;
350 bool usePos;
351 SkColor colors[kMaxColors];
352 SkScalar pos[kMaxColors];
353 fuzz->next(&tmX, &useMatrix, &usePos, &center, &radius);
354 fuzz->nextRange(&colorCount, 2, kMaxColors);
355 fuzz->nextN(colors, colorCount);
356 if (useMatrix) {
357 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500358 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500359 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500360 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500361 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500362 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
363 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
364 }
365 case 12: {
366 constexpr int kMaxColors = 12;
367 SkPoint start, end;
368 SkScalar startRadius, endRadius;
369 int colorCount;
370 bool usePos;
371 SkColor colors[kMaxColors];
372 SkScalar pos[kMaxColors];
373 fuzz->next(&tmX, &useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
374 fuzz->nextRange(&colorCount, 2, kMaxColors);
375 fuzz->nextN(colors, colorCount);
376 if (useMatrix) {
377 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500378 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500379 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500380 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500381 }
382 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
383 usePos ? pos : nullptr, colorCount, tmX, 0,
384 useMatrix ? &matrix : nullptr);
385 }
386 case 13: {
387 constexpr int kMaxColors = 12;
388 SkScalar cx, cy;
389 int colorCount;
390 bool usePos;
391 SkColor colors[kMaxColors];
392 SkScalar pos[kMaxColors];
393 fuzz->next(&cx, &cy, &useMatrix, &usePos);
394 fuzz->nextRange(&colorCount, 2, kMaxColors);
395 fuzz->nextN(colors, colorCount);
396 if (useMatrix) {
397 fuzz->next(&matrix);
398 }
399 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500400 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500401 }
402 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
403 0, useMatrix ? &matrix : nullptr);
404 }
405 case 14: {
406 SkScalar baseFrequencyX, baseFrequencyY, seed;
407 int numOctaves;
408 SkISize tileSize;
409 bool useTileSize, turbulence;
410 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
411 if (useTileSize) {
412 fuzz->next(&tileSize);
413 }
414 fuzz->nextRange(&numOctaves, 2, 7);
415 if (turbulence) {
416 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
417 numOctaves, seed,
418 useTileSize ? &tileSize : nullptr);
419 } else {
420 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
421 numOctaves, seed,
422 useTileSize ? &tileSize : nullptr);
423 }
424 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500425 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -0500426 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -0500427 break;
428 }
Kevin Lubickedbeb8b2017-02-27 16:45:32 -0500429 return nullptr;
Hal Canary24ac42b2017-02-14 13:35:14 -0500430}
431
Hal Canary1e0138b2017-03-10 13:56:08 -0500432static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
Hal Canary5395c592017-03-08 16:52:18 -0500433 if (depth <= 0) {
434 return nullptr;
435 }
436 uint8_t pathEffectType;
Mike Reed40e7e652017-07-22 22:12:59 -0400437 fuzz->nextRange(&pathEffectType, 0, 8);
Hal Canary5395c592017-03-08 16:52:18 -0500438 switch (pathEffectType) {
439 case 0: {
440 return nullptr;
441 }
442 case 1: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500443 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
444 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500445 return SkPathEffect::MakeSum(std::move(first), std::move(second));
446 }
447 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500448 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
449 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500450 return SkPathEffect::MakeCompose(std::move(first), std::move(second));
451 }
452 case 3: {
453 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -0500454 FuzzPath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500455 SkScalar advance, phase;
456 fuzz->next(&advance, &phase);
Hal Canaryf7005202017-03-10 08:48:28 -0500457 SkPath1DPathEffect::Style style;
458 fuzz_enum_range(fuzz, &style, 0, SkPath1DPathEffect::kLastEnum_Style);
459 return SkPath1DPathEffect::Make(path, advance, phase, style);
Hal Canary5395c592017-03-08 16:52:18 -0500460 }
461 case 4: {
462 SkScalar width;
463 SkMatrix matrix;
464 fuzz->next(&width, &matrix);
465 return SkLine2DPathEffect::Make(width, matrix);
466 }
467 case 5: {
468 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -0500469 FuzzPath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500470 SkMatrix matrix;
471 fuzz->next(&matrix);
472 return SkPath2DPathEffect::Make(matrix, path);
473 }
474 case 6: {
475 SkScalar radius;
476 fuzz->next(&radius);
Hal Canary5395c592017-03-08 16:52:18 -0500477 return SkCornerPathEffect::Make(radius);
478 }
Mike Reed40e7e652017-07-22 22:12:59 -0400479 case 7: {
Hal Canary5395c592017-03-08 16:52:18 -0500480 SkScalar phase;
481 fuzz->next(&phase);
482 SkScalar intervals[20];
483 int count;
484 fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
485 fuzz->nextN(intervals, count);
486 return SkDashPathEffect::Make(intervals, count, phase);
487 }
Mike Reed40e7e652017-07-22 22:12:59 -0400488 case 8: {
Hal Canary5395c592017-03-08 16:52:18 -0500489 SkScalar segLength, dev;
490 uint32_t seed;
491 fuzz->next(&segLength, &dev, &seed);
492 return SkDiscretePathEffect::Make(segLength, dev, seed);
493 }
494 default:
495 SkASSERT(false);
496 return nullptr;
497 }
498}
Hal Canary24ac42b2017-02-14 13:35:14 -0500499
Hal Canary1e0138b2017-03-10 13:56:08 -0500500static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
Hal Canary5395c592017-03-08 16:52:18 -0500501 int maskfilterType;
Robert Phillipsab4f5bd2018-04-18 10:05:00 -0400502 fuzz->nextRange(&maskfilterType, 0, 1);
Hal Canary5395c592017-03-08 16:52:18 -0500503 switch (maskfilterType) {
504 case 0:
505 return nullptr;
506 case 1: {
Hal Canaryf7005202017-03-10 08:48:28 -0500507 SkBlurStyle blurStyle;
508 fuzz_enum_range(fuzz, &blurStyle, 0, kLastEnum_SkBlurStyle);
Hal Canary5395c592017-03-08 16:52:18 -0500509 SkScalar sigma;
510 fuzz->next(&sigma);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400511 bool respectCTM;
512 fuzz->next(&respectCTM);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400513 return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
Hal Canary5395c592017-03-08 16:52:18 -0500514 }
Hal Canary5395c592017-03-08 16:52:18 -0500515 default:
516 SkASSERT(false);
517 return nullptr;
518 }
519}
Hal Canary24ac42b2017-02-14 13:35:14 -0500520
Hal Canary1e0138b2017-03-10 13:56:08 -0500521static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
522 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary671e4422017-02-27 13:36:38 -0500523 return nullptr;
524 }
525 auto fontMugger = SkFontMgr::RefDefault();
526 SkASSERT(fontMugger);
527 int familyCount = fontMugger->countFamilies();
528 int i, j;
529 fuzz->nextRange(&i, 0, familyCount - 1);
530 sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
531 int styleCount = family->count();
532 fuzz->nextRange(&j, 0, styleCount - 1);
533 return sk_sp<SkTypeface>(family->createTypeface(j));
534}
Hal Canary24ac42b2017-02-14 13:35:14 -0500535
Hal Canarye03c3e52017-03-09 11:33:35 -0500536template <>
537inline void Fuzz::next(SkImageFilter::CropRect* cropRect) {
538 SkRect rect;
539 uint8_t flags;
540 this->next(&rect);
541 this->nextRange(&flags, 0, 0xF);
542 *cropRect = SkImageFilter::CropRect(rect, flags);
543}
544
Hal Canary1e0138b2017-03-10 13:56:08 -0500545static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500546
547static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
548 if (depth <= 0) {
549 return nullptr;
550 }
551 uint8_t imageFilterType;
552 fuzz->nextRange(&imageFilterType, 1, 6);
553 SkPoint3 p, q;
554 SkColor lightColor;
555 SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
556 sk_sp<SkImageFilter> input;
557 SkImageFilter::CropRect cropRect;
558 bool useCropRect;
559 fuzz->next(&useCropRect);
560 if (useCropRect) {
561 fuzz->next(&cropRect);
562 }
563 switch (imageFilterType) {
564 case 1:
565 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500566 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500567 return SkLightingImageFilter::MakeDistantLitDiffuse(p, lightColor, surfaceScale, k,
568 std::move(input),
569 useCropRect ? &cropRect : nullptr);
570 case 2:
571 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500572 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500573 return SkLightingImageFilter::MakePointLitDiffuse(p, lightColor, surfaceScale, k,
574 std::move(input),
575 useCropRect ? &cropRect : nullptr);
576 case 3:
577 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500578 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500579 return SkLightingImageFilter::MakeSpotLitDiffuse(
580 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
581 std::move(input), useCropRect ? &cropRect : nullptr);
582 case 4:
583 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500584 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500585 return SkLightingImageFilter::MakeDistantLitSpecular(p, lightColor, surfaceScale, k,
586 shininess, std::move(input),
587 useCropRect ? &cropRect : nullptr);
588 case 5:
589 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500590 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500591 return SkLightingImageFilter::MakePointLitSpecular(p, lightColor, surfaceScale, k,
592 shininess, std::move(input),
593 useCropRect ? &cropRect : nullptr);
594 case 6:
595 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
596 &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500597 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500598 return SkLightingImageFilter::MakeSpotLitSpecular(
599 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
600 std::move(input), useCropRect ? &cropRect : nullptr);
601 default:
602 SkASSERT(false);
603 return nullptr;
604 }
605}
606
Hal Canary1e0138b2017-03-10 13:56:08 -0500607static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500608
Hal Canary1e0138b2017-03-10 13:56:08 -0500609static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
Hal Canarye03c3e52017-03-09 11:33:35 -0500610 if (depth <= 0) {
611 return nullptr;
612 }
613 uint8_t imageFilterType;
Kevin Lubick54f20e02018-01-11 14:50:21 -0500614 fuzz->nextRange(&imageFilterType, 0, 23);
Hal Canarye03c3e52017-03-09 11:33:35 -0500615 switch (imageFilterType) {
616 case 0:
617 return nullptr;
618 case 1: {
619 SkScalar sigmaX, sigmaY;
Hal Canary1e0138b2017-03-10 13:56:08 -0500620 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500621 bool useCropRect;
622 fuzz->next(&sigmaX, &sigmaY, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400623 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500624 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400625 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500626 }
Robert Phillips70e3e9a2017-06-26 14:22:01 -0400627 return SkBlurImageFilter::Make(sigmaX, sigmaY, std::move(input),
Hal Canarye03c3e52017-03-09 11:33:35 -0500628 useCropRect ? &cropRect : nullptr);
629 }
630 case 2: {
631 SkMatrix matrix;
632 SkFilterQuality quality;
633 fuzz->next(&matrix, &quality);
Hal Canary1e0138b2017-03-10 13:56:08 -0500634 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500635 return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
636 }
637 case 3: {
638 SkRegion region;
639 SkScalar innerMin, outerMax;
Hal Canary1e0138b2017-03-10 13:56:08 -0500640 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500641 bool useCropRect;
642 fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400643 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500644 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400645 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500646 }
647 return SkAlphaThresholdFilter::Make(region, innerMin, outerMax, std::move(input),
648 useCropRect ? &cropRect : nullptr);
649 }
650 case 4: {
651 float k1, k2, k3, k4;
652 bool enforcePMColor;
653 bool useCropRect;
654 fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500655 sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
656 sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500657 SkImageFilter::CropRect cropRect;
658 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400659 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500660 }
661 return SkArithmeticImageFilter::Make(k1, k2, k3, k4, enforcePMColor,
662 std::move(background), std::move(foreground),
663 useCropRect ? &cropRect : nullptr);
664 }
665 case 5: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500666 sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
667 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500668 bool useCropRect;
669 SkImageFilter::CropRect cropRect;
670 fuzz->next(&useCropRect);
671 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400672 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500673 }
674 return SkColorFilterImageFilter::Make(std::move(cf), std::move(input),
675 useCropRect ? &cropRect : nullptr);
676 }
677 case 6: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500678 sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
679 sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500680 return SkComposeImageFilter::Make(std::move(ifo), std::move(ifi));
681 }
682 case 7: {
683 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, yChannelSelector;
Hal Canaryf49b1e02017-03-15 16:58:33 -0400684 fuzz_enum_range(fuzz, &xChannelSelector, 1, 4);
685 fuzz_enum_range(fuzz, &yChannelSelector, 1, 4);
Hal Canarye03c3e52017-03-09 11:33:35 -0500686 SkScalar scale;
687 bool useCropRect;
688 fuzz->next(&scale, &useCropRect);
689 SkImageFilter::CropRect cropRect;
690 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400691 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500692 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500693 sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
694 sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500695 return SkDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
696 std::move(displacement), std::move(color),
697 useCropRect ? &cropRect : nullptr);
698 }
699 case 8: {
700 SkScalar dx, dy, sigmaX, sigmaY;
701 SkColor color;
702 SkDropShadowImageFilter::ShadowMode shadowMode;
Hal Canaryf7005202017-03-10 08:48:28 -0500703 fuzz_enum_range(fuzz, &shadowMode, 0, 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500704 bool useCropRect;
705 fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &useCropRect);
706 SkImageFilter::CropRect cropRect;
707 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400708 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500709 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500710 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500711 return SkDropShadowImageFilter::Make(dx, dy, sigmaX, sigmaY, color, shadowMode,
712 std::move(input),
713 useCropRect ? &cropRect : nullptr);
714 }
715 case 9:
Hal Canary1e0138b2017-03-10 13:56:08 -0500716 return SkImageSource::Make(make_fuzz_image(fuzz));
Hal Canarye03c3e52017-03-09 11:33:35 -0500717 case 10: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500718 sk_sp<SkImage> image = make_fuzz_image(fuzz);
Hal Canarye03c3e52017-03-09 11:33:35 -0500719 SkRect srcRect, dstRect;
720 SkFilterQuality filterQuality;
721 fuzz->next(&srcRect, &dstRect, &filterQuality);
722 return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
723 }
724 case 11:
725 return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
726 case 12: {
727 SkRect srcRect;
728 SkScalar inset;
729 bool useCropRect;
730 SkImageFilter::CropRect cropRect;
731 fuzz->next(&srcRect, &inset, &useCropRect);
732 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400733 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500734 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500735 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500736 return SkMagnifierImageFilter::Make(srcRect, inset, std::move(input),
737 useCropRect ? &cropRect : nullptr);
738 }
739 case 13: {
740 constexpr int kMaxKernelSize = 5;
741 int32_t n, m;
742 fuzz->nextRange(&n, 1, kMaxKernelSize);
743 fuzz->nextRange(&m, 1, kMaxKernelSize);
744 SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
745 fuzz->nextN(kernel, n * m);
746 int32_t offsetX, offsetY;
747 fuzz->nextRange(&offsetX, 0, n - 1);
748 fuzz->nextRange(&offsetY, 0, m - 1);
749 SkScalar gain, bias;
750 bool convolveAlpha, useCropRect;
751 fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
752 SkMatrixConvolutionImageFilter::TileMode tileMode;
Hal Canaryf7005202017-03-10 08:48:28 -0500753 fuzz_enum_range(fuzz, &tileMode, 0, 2);
Hal Canarye03c3e52017-03-09 11:33:35 -0500754 SkImageFilter::CropRect cropRect;
755 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400756 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500757 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500758 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500759 return SkMatrixConvolutionImageFilter::Make(
760 SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
761 convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
762 }
763 case 14: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500764 sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
765 sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500766 bool useCropRect;
767 fuzz->next(&useCropRect);
768 SkImageFilter::CropRect cropRect;
769 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400770 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500771 }
Mike Reed0bdaf052017-06-18 23:35:57 -0400772 return SkMergeImageFilter::Make(std::move(first), std::move(second),
773 useCropRect ? &cropRect : nullptr);
774 }
775 case 15: {
776 constexpr int kMaxCount = 4;
777 sk_sp<SkImageFilter> ifs[kMaxCount];
778 int count;
779 fuzz->nextRange(&count, 1, kMaxCount);
780 for (int i = 0; i < count; ++i) {
781 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
782 }
783 bool useCropRect;
784 fuzz->next(&useCropRect);
785 SkImageFilter::CropRect cropRect;
786 if (useCropRect) {
787 fuzz->next(&cropRect);
788 }
789 return SkMergeImageFilter::Make(ifs, count, useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500790 }
791 case 16: {
792 int rx, ry;
793 fuzz->next(&rx, &ry);
794 bool useCropRect;
795 fuzz->next(&useCropRect);
796 SkImageFilter::CropRect cropRect;
797 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400798 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500799 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500800 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500801 return SkDilateImageFilter::Make(rx, ry, std::move(input),
802 useCropRect ? &cropRect : nullptr);
803 }
804 case 17: {
805 int rx, ry;
806 fuzz->next(&rx, &ry);
807 bool useCropRect;
808 fuzz->next(&useCropRect);
809 SkImageFilter::CropRect cropRect;
810 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400811 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500812 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500813 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500814 return SkErodeImageFilter::Make(rx, ry, std::move(input),
815 useCropRect ? &cropRect : nullptr);
816 }
817 case 18: {
818 SkScalar dx, dy;
819 fuzz->next(&dx, &dy);
820 bool useCropRect;
821 fuzz->next(&useCropRect);
822 SkImageFilter::CropRect cropRect;
823 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400824 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500825 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500826 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500827 return SkOffsetImageFilter::Make(dx, dy, std::move(input),
828 useCropRect ? &cropRect : nullptr);
829 }
830 case 19: {
831 SkPaint paint;
Hal Canary1e0138b2017-03-10 13:56:08 -0500832 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500833 bool useCropRect;
834 fuzz->next(&useCropRect);
835 SkImageFilter::CropRect cropRect;
836 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400837 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500838 }
839 return SkPaintImageFilter::Make(paint, useCropRect ? &cropRect : nullptr);
840 }
841 case 20: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500842 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500843 return SkPictureImageFilter::Make(std::move(picture));
844 }
845 case 21: {
846 SkRect cropRect;
847 fuzz->next(&cropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500848 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500849 return SkPictureImageFilter::Make(std::move(picture), cropRect);
850 }
851 case 22: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500852 SkRect src, dst;
853 fuzz->next(&src, &dst);
Hal Canary1e0138b2017-03-10 13:56:08 -0500854 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500855 return SkTileImageFilter::Make(src, dst, std::move(input));
856 }
Mike Reed77e487d2017-11-09 21:50:20 +0000857 case 23: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500858 SkBlendMode blendMode;
859 bool useCropRect;
860 fuzz->next(&useCropRect, &blendMode);
861 SkImageFilter::CropRect cropRect;
862 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400863 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500864 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500865 sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
866 sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500867 return SkXfermodeImageFilter::Make(blendMode, std::move(bg), std::move(fg),
868 useCropRect ? &cropRect : nullptr);
869 }
870 default:
871 SkASSERT(false);
872 return nullptr;
873 }
874}
Hal Canary24ac42b2017-02-14 13:35:14 -0500875
Hal Canary1e0138b2017-03-10 13:56:08 -0500876static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500877 int w, h;
878 fuzz->nextRange(&w, 1, 1024);
879 fuzz->nextRange(&h, 1, 1024);
880 SkAutoTMalloc<SkPMColor> data(w * h);
881 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
882 int n = w * h;
883 for (int i = 0; i < n; ++i) {
884 SkColor c;
885 fuzz->next(&c);
886 data[i] = SkPreMultiplyColor(c);
887 }
888 (void)data.release();
Hal Canaryb69c4b82017-03-08 11:02:40 -0500889 return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
890 nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500891}
892
Hal Canary1e0138b2017-03-10 13:56:08 -0500893static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500894 SkBitmap bitmap;
895 int w, h;
896 fuzz->nextRange(&w, 1, 1024);
897 fuzz->nextRange(&h, 1, 1024);
Kevin Lubick1991f552018-02-27 10:59:10 -0500898 if (!bitmap.tryAllocN32Pixels(w, h)) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400899 SkDEBUGF("Could not allocate pixels %d x %d", w, h);
Kevin Lubick1991f552018-02-27 10:59:10 -0500900 return bitmap;
901 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500902 for (int y = 0; y < h; ++y) {
903 for (int x = 0; x < w; ++x) {
904 SkColor c;
905 fuzz->next(&c);
906 *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
907 }
908 }
909 return bitmap;
910}
911
Hal Canary1e0138b2017-03-10 13:56:08 -0500912template <typename T, typename Min, typename Max>
913inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
914 T value;
915 fuzz_enum_range(fuzz, &value, minv, maxv);
916 return value;
917}
918
919static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500920 if (!fuzz || !paint || depth <= 0) {
921 return;
922 }
923
Hal Canary1e0138b2017-03-10 13:56:08 -0500924 paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
925 paint->setDither( make_fuzz_t<bool>(fuzz));
926 paint->setColor( make_fuzz_t<SkColor>(fuzz));
927 paint->setBlendMode( make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
928 paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
929 paint->setStyle( make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
930 paint->setShader( make_fuzz_shader(fuzz, depth - 1));
931 paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
932 paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
933 paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
934 paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
Hal Canary24ac42b2017-02-14 13:35:14 -0500935
936 if (paint->getStyle() != SkPaint::kFill_Style) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500937 paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
938 paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
939 paint->setStrokeCap( make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
940 paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
Hal Canary24ac42b2017-02-14 13:35:14 -0500941 }
942}
943
Hal Canary1e0138b2017-03-10 13:56:08 -0500944static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
945 paint->setTypeface( make_fuzz_typeface(fuzz));
946 paint->setTextSize( make_fuzz_t<SkScalar>(fuzz));
947 paint->setTextScaleX( make_fuzz_t<SkScalar>(fuzz));
948 paint->setTextSkewX( make_fuzz_t<SkScalar>(fuzz));
949 paint->setLinearText( make_fuzz_t<bool>(fuzz));
950 paint->setSubpixelText( make_fuzz_t<bool>(fuzz));
951 paint->setLCDRenderText( make_fuzz_t<bool>(fuzz));
952 paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
953 paint->setAutohinted( make_fuzz_t<bool>(fuzz));
954 paint->setVerticalText( make_fuzz_t<bool>(fuzz));
955 paint->setFakeBoldText( make_fuzz_t<bool>(fuzz));
956 paint->setDevKernText( make_fuzz_t<bool>(fuzz));
957 paint->setHinting( make_fuzz_t_range<SkPaint::Hinting>(fuzz, 0,
958 SkPaint::kFull_Hinting));
959 paint->setTextAlign( make_fuzz_t_range<SkPaint::Align>(fuzz, 0, 2));
Hal Canary5395c592017-03-08 16:52:18 -0500960}
961
962static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500963 paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
Hal Canary24ac42b2017-02-14 13:35:14 -0500964}
965
Hal Canary5395c592017-03-08 16:52:18 -0500966constexpr int kMaxGlyphCount = 30;
967
Hal Canary1e0138b2017-03-10 13:56:08 -0500968static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
Hal Canary671e4422017-02-27 13:36:38 -0500969 SkTDArray<uint8_t> array;
970 if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500971 int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
972 : SkTypeface::MakeDefault()->countGlyphs();
Kevin Lubick1991f552018-02-27 10:59:10 -0500973 if (glyphRange == 0) {
974 // Some fuzzing environments have no fonts, so empty array is the best
975 // we can do.
976 return array;
977 }
Hal Canary671e4422017-02-27 13:36:38 -0500978 int glyphCount;
Hal Canary5395c592017-03-08 16:52:18 -0500979 fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
Hal Canary671e4422017-02-27 13:36:38 -0500980 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
981 for (int i = 0; i < glyphCount; ++i) {
982 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
983 }
984 return array;
985 }
986 static const SkUnichar ranges[][2] = {
987 {0x0020, 0x007F},
988 {0x00A1, 0x0250},
989 {0x0400, 0x0500},
990 };
991 int32_t count = 0;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500992 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500993 count += (ranges[i][1] - ranges[i][0]);
994 }
Hal Canary5395c592017-03-08 16:52:18 -0500995 constexpr int kMaxLength = kMaxGlyphCount;
Hal Canary671e4422017-02-27 13:36:38 -0500996 SkUnichar buffer[kMaxLength];
997 int length;
998 fuzz->nextRange(&length, 1, kMaxLength);
999 for (int j = 0; j < length; ++j) {
1000 int32_t value;
1001 fuzz->nextRange(&value, 0, count - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001002 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -05001003 if (value + ranges[i][0] < ranges[i][1]) {
1004 buffer[j] = value + ranges[i][0];
1005 break;
1006 } else {
1007 value -= (ranges[i][1] - ranges[i][0]);
1008 }
1009 }
1010 }
1011 switch (paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -05001012 case SkPaint::kUTF8_TextEncoding: {
1013 size_t utf8len = 0;
1014 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -04001015 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
Hal Canary671e4422017-02-27 13:36:38 -05001016 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001017 char* ptr = (char*)array.append(utf8len);
1018 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -04001019 ptr += SkUTF::ToUTF8(buffer[j], ptr);
Hal Canary671e4422017-02-27 13:36:38 -05001020 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001021 } break;
1022 case SkPaint::kUTF16_TextEncoding: {
1023 size_t utf16len = 0;
1024 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -04001025 utf16len += SkUTF::ToUTF16(buffer[j]);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001026 }
1027 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
1028 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -04001029 ptr += SkUTF::ToUTF16(buffer[j], ptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001030 }
1031 } break;
Hal Canary671e4422017-02-27 13:36:38 -05001032 case SkPaint::kUTF32_TextEncoding:
1033 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
Hal Canaryc1a70e22017-03-01 15:40:46 -05001034 break;
Hal Canary671e4422017-02-27 13:36:38 -05001035 default:
Hal Canaryb69c4b82017-03-08 11:02:40 -05001036 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -05001037 break;
Hal Canary671e4422017-02-27 13:36:38 -05001038 }
1039 return array;
1040}
1041
Hal Canary5395c592017-03-08 16:52:18 -05001042static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
1043 SkTextBlobBuilder textBlobBuilder;
1044 int8_t runCount;
1045 fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
1046 while (runCount-- > 0) {
1047 SkPaint paint;
1048 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary1e0138b2017-03-10 13:56:08 -05001049 paint.setAntiAlias(make_fuzz_t<bool>(fuzz));
Hal Canary5395c592017-03-08 16:52:18 -05001050 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1051 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1052 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1053 SkASSERT(glyphCount <= kMaxGlyphCount);
1054 SkScalar x, y;
1055 const SkTextBlobBuilder::RunBuffer* buffer;
1056 uint8_t runType;
1057 fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
1058 switch (runType) {
1059 case 0:
1060 fuzz->next(&x, &y);
1061 // TODO: Test other variations of this.
1062 buffer = &textBlobBuilder.allocRun(paint, glyphCount, x, y);
1063 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1064 break;
1065 case 1:
1066 fuzz->next(&y);
1067 // TODO: Test other variations of this.
1068 buffer = &textBlobBuilder.allocRunPosH(paint, glyphCount, y);
1069 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1070 fuzz->nextN(buffer->pos, glyphCount);
1071 break;
1072 case 2:
1073 // TODO: Test other variations of this.
1074 buffer = &textBlobBuilder.allocRunPos(paint, glyphCount);
1075 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1076 fuzz->nextN(buffer->pos, glyphCount * 2);
1077 break;
1078 default:
1079 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -05001080 break;
Hal Canary5395c592017-03-08 16:52:18 -05001081 }
1082 }
1083 return textBlobBuilder.make();
1084}
1085
Kevin Lubickd2ae8dc2018-06-01 13:16:20 -04001086extern std::atomic<bool> gSkUseDeltaAA;
1087extern std::atomic<bool> gSkForceDeltaAA;
1088
Hal Canary1e0138b2017-03-10 13:56:08 -05001089static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001090 if (!fuzz || !canvas || depth <= 0) {
1091 return;
1092 }
1093 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
Kevin Lubickd2ae8dc2018-06-01 13:16:20 -04001094 bool useDAA;
1095 fuzz->next(&useDAA);
1096 if (useDAA) {
1097 gSkForceDeltaAA = true;
1098 gSkUseDeltaAA = true;
1099 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001100 unsigned N;
1101 fuzz->nextRange(&N, 0, 2000);
1102 for (unsigned i = 0; i < N; ++i) {
1103 if (fuzz->exhausted()) {
1104 return;
1105 }
1106 SkPaint paint;
1107 SkMatrix matrix;
1108 unsigned drawCommand;
Hal Canary5af600e2017-03-09 14:10:36 -05001109 fuzz->nextRange(&drawCommand, 0, 53);
Hal Canary24ac42b2017-02-14 13:35:14 -05001110 switch (drawCommand) {
1111 case 0:
1112 canvas->flush();
1113 break;
1114 case 1:
1115 canvas->save();
1116 break;
1117 case 2: {
1118 SkRect bounds;
1119 fuzz->next(&bounds);
Hal Canary1e0138b2017-03-10 13:56:08 -05001120 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001121 canvas->saveLayer(&bounds, &paint);
1122 break;
1123 }
1124 case 3: {
1125 SkRect bounds;
1126 fuzz->next(&bounds);
1127 canvas->saveLayer(&bounds, nullptr);
1128 break;
1129 }
1130 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -05001131 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001132 canvas->saveLayer(nullptr, &paint);
1133 break;
1134 case 5:
1135 canvas->saveLayer(nullptr, nullptr);
1136 break;
1137 case 6: {
1138 uint8_t alpha;
1139 fuzz->next(&alpha);
1140 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1141 break;
1142 }
1143 case 7: {
1144 SkRect bounds;
1145 uint8_t alpha;
1146 fuzz->next(&bounds, &alpha);
1147 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1148 break;
1149 }
1150 case 8: {
1151 SkCanvas::SaveLayerRec saveLayerRec;
1152 SkRect bounds;
Hal Canary1e0138b2017-03-10 13:56:08 -05001153 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001154 fuzz->next(&bounds);
1155 saveLayerRec.fBounds = &bounds;
1156 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001157 if (make_fuzz_t<bool>(fuzz)) {
1158 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001159 saveLayerRec.fPaint = &paint;
1160 }
1161 sk_sp<SkImageFilter> imageFilter;
Hal Canary1e0138b2017-03-10 13:56:08 -05001162 if (make_fuzz_t<bool>(fuzz)) {
1163 imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001164 saveLayerRec.fBackdrop = imageFilter.get();
1165 }
Hal Canary5395c592017-03-08 16:52:18 -05001166 // _DumpCanvas can't handle this.
Hal Canary1e0138b2017-03-10 13:56:08 -05001167 // if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -05001168 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1169 // }
1170
Hal Canary24ac42b2017-02-14 13:35:14 -05001171 canvas->saveLayer(saveLayerRec);
1172 break;
1173 }
1174 case 9:
1175 canvas->restore();
1176 break;
1177 case 10: {
1178 int saveCount;
1179 fuzz->next(&saveCount);
1180 canvas->restoreToCount(saveCount);
1181 break;
1182 }
1183 case 11: {
1184 SkScalar x, y;
1185 fuzz->next(&x, &y);
1186 canvas->translate(x, y);
1187 break;
1188 }
1189 case 12: {
1190 SkScalar x, y;
1191 fuzz->next(&x, &y);
1192 canvas->scale(x, y);
1193 break;
1194 }
1195 case 13: {
1196 SkScalar v;
1197 fuzz->next(&v);
1198 canvas->rotate(v);
1199 break;
1200 }
1201 case 14: {
1202 SkScalar x, y, v;
1203 fuzz->next(&x, &y, &v);
1204 canvas->rotate(v, x, y);
1205 break;
1206 }
1207 case 15: {
1208 SkScalar x, y;
1209 fuzz->next(&x, &y);
1210 canvas->skew(x, y);
1211 break;
1212 }
1213 case 16: {
1214 SkMatrix mat;
1215 fuzz->next(&mat);
1216 canvas->concat(mat);
1217 break;
1218 }
1219 case 17: {
1220 SkMatrix mat;
1221 fuzz->next(&mat);
1222 canvas->setMatrix(mat);
1223 break;
1224 }
1225 case 18:
1226 canvas->resetMatrix();
1227 break;
1228 case 19: {
1229 SkRect r;
1230 int op;
1231 bool doAntiAlias;
1232 fuzz->next(&r, &doAntiAlias);
1233 fuzz->nextRange(&op, 0, 1);
1234 r.sort();
1235 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1236 break;
1237 }
1238 case 20: {
1239 SkRRect rr;
1240 int op;
1241 bool doAntiAlias;
1242 fuzz->next(&rr);
1243 fuzz->next(&doAntiAlias);
1244 fuzz->nextRange(&op, 0, 1);
1245 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1246 break;
1247 }
1248 case 21: {
1249 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -05001250 FuzzPath(fuzz, &path, 30);
Hal Canary24ac42b2017-02-14 13:35:14 -05001251 int op;
1252 bool doAntiAlias;
1253 fuzz->next(&doAntiAlias);
1254 fuzz->nextRange(&op, 0, 1);
1255 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1256 break;
1257 }
1258 case 22: {
1259 SkRegion region;
Hal Canary24ac42b2017-02-14 13:35:14 -05001260 int op;
Hal Canarye03c3e52017-03-09 11:33:35 -05001261 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001262 fuzz->nextRange(&op, 0, 1);
1263 canvas->clipRegion(region, (SkClipOp)op);
1264 break;
1265 }
1266 case 23:
Hal Canary1e0138b2017-03-10 13:56:08 -05001267 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001268 canvas->drawPaint(paint);
1269 break;
1270 case 24: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001271 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001272 SkCanvas::PointMode pointMode;
1273 fuzz_enum_range(fuzz, &pointMode,
1274 SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001275 size_t count;
1276 constexpr int kMaxCount = 30;
1277 fuzz->nextRange(&count, 0, kMaxCount);
1278 SkPoint pts[kMaxCount];
1279 fuzz->nextN(pts, count);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001280 canvas->drawPoints(pointMode, count, pts, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001281 break;
1282 }
1283 case 25: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001284 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001285 SkRect r;
1286 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001287 if (!r.isFinite()) {
1288 break;
1289 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001290 canvas->drawRect(r, paint);
1291 break;
1292 }
1293 case 26: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001294 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001295 SkRegion region;
Hal Canarye03c3e52017-03-09 11:33:35 -05001296 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001297 canvas->drawRegion(region, paint);
1298 break;
1299 }
1300 case 27: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001301 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001302 SkRect r;
1303 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001304 if (!r.isFinite()) {
1305 break;
1306 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001307 canvas->drawOval(r, paint);
1308 break;
1309 }
Mike Reed9cec1bc2018-01-19 12:57:01 -05001310 case 28: break; // must have deleted this some time earlier
Hal Canary24ac42b2017-02-14 13:35:14 -05001311 case 29: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001312 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001313 SkRRect rr;
1314 fuzz->next(&rr);
1315 canvas->drawRRect(rr, paint);
1316 break;
1317 }
1318 case 30: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001319 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001320 SkRRect orr, irr;
1321 fuzz->next(&orr);
1322 fuzz->next(&irr);
Hal Canary27bece82017-03-07 16:23:20 -05001323 if (orr.getBounds().contains(irr.getBounds())) {
1324 canvas->drawDRRect(orr, irr, paint);
1325 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001326 break;
1327 }
1328 case 31: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001329 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001330 SkRect r;
1331 SkScalar start, sweep;
1332 bool useCenter;
1333 fuzz->next(&r, &start, &sweep, &useCenter);
1334 canvas->drawArc(r, start, sweep, useCenter, paint);
1335 break;
1336 }
1337 case 32: {
Kevin Lubick0938ce72018-05-21 21:17:15 -04001338 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001339 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -05001340 FuzzPath(fuzz, &path, 60);
Hal Canary24ac42b2017-02-14 13:35:14 -05001341 canvas->drawPath(path, paint);
1342 break;
1343 }
1344 case 33: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001345 sk_sp<SkImage> img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001346 SkScalar left, top;
1347 bool usePaint;
1348 fuzz->next(&left, &top, &usePaint);
1349 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001350 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001351 }
1352 canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
1353 break;
1354 }
1355 case 34: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001356 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001357 SkRect src, dst;
1358 bool usePaint;
1359 fuzz->next(&src, &dst, &usePaint);
1360 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001361 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001362 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001363 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001364 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1365 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001366 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1367 break;
1368 }
1369 case 35: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001370 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001371 SkIRect src;
1372 SkRect dst;
1373 bool usePaint;
1374 fuzz->next(&src, &dst, &usePaint);
1375 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001376 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001377 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001378 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001379 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1380 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001381 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1382 break;
1383 }
1384 case 36: {
1385 bool usePaint;
Hal Canary1e0138b2017-03-10 13:56:08 -05001386 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001387 SkRect dst;
1388 fuzz->next(&dst, &usePaint);
1389 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001390 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001391 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001392 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001393 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1394 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001395 canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr, constraint);
1396 break;
1397 }
1398 case 37: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001399 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001400 SkIRect center;
1401 SkRect dst;
1402 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001403 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001404 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001405 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001406 }
Hal Canary0361d492017-03-15 12:58:15 -04001407 if (make_fuzz_t<bool>(fuzz)) {
1408 fuzz->next(&center);
1409 } else { // Make valid center, see SkLatticeIter::Valid().
1410 fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1411 fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1412 fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1413 fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1414 }
1415 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001416 canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
1417 break;
1418 }
1419 case 38: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001420 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001421 SkScalar left, top;
1422 bool usePaint;
1423 fuzz->next(&left, &top, &usePaint);
1424 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001425 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001426 }
1427 canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
1428 break;
1429 }
1430 case 39: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001431 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001432 SkRect src, dst;
1433 bool usePaint;
1434 fuzz->next(&src, &dst, &usePaint);
1435 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001436 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001437 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001438 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001439 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1440 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001441 canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
1442 break;
1443 }
1444 case 40: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001445 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001446 SkIRect src;
1447 SkRect dst;
1448 bool usePaint;
1449 fuzz->next(&src, &dst, &usePaint);
1450 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001451 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001452 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001453 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001454 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1455 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001456 canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1457 break;
1458 }
1459 case 41: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001460 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001461 SkRect dst;
1462 bool usePaint;
1463 fuzz->next(&dst, &usePaint);
1464 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001465 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001466 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001467 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001468 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1469 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001470 canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1471 break;
1472 }
1473 case 42: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001474 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001475 SkIRect center;
1476 SkRect dst;
1477 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001478 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001479 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001480 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001481 }
Hal Canary0361d492017-03-15 12:58:15 -04001482 if (make_fuzz_t<bool>(fuzz)) {
1483 fuzz->next(&center);
1484 } else { // Make valid center, see SkLatticeIter::Valid().
Kevin Lubick1991f552018-02-27 10:59:10 -05001485 if (img.width() == 0 || img.height() == 0) {
1486 // bitmap may not have had its pixels initialized.
1487 break;
1488 }
Hal Canary0361d492017-03-15 12:58:15 -04001489 fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
1490 fuzz->nextRange(&center.fTop, 0, img.height() - 1);
1491 fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
1492 fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
1493 }
1494 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001495 canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1496 break;
1497 }
1498 case 43: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001499 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001500 bool usePaint;
1501 SkRect dst;
1502 fuzz->next(&usePaint, &dst);
1503 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001504 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001505 }
1506 constexpr int kMax = 6;
1507 int xDivs[kMax], yDivs[kMax];
Stan Ilievca8c0952017-12-11 13:01:58 -05001508 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
Hal Canary24ac42b2017-02-14 13:35:14 -05001509 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1510 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1511 fuzz->nextN(xDivs, lattice.fXCount);
1512 fuzz->nextN(yDivs, lattice.fYCount);
1513 canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1514 break;
1515 }
1516 case 44: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001517 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001518 bool usePaint;
1519 SkRect dst;
1520 fuzz->next(&usePaint, &dst);
1521 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001522 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001523 }
1524 constexpr int kMax = 6;
1525 int xDivs[kMax], yDivs[kMax];
Stan Ilievca8c0952017-12-11 13:01:58 -05001526 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
Hal Canary24ac42b2017-02-14 13:35:14 -05001527 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1528 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1529 fuzz->nextN(xDivs, lattice.fXCount);
1530 fuzz->nextN(yDivs, lattice.fYCount);
1531 canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1532 break;
1533 }
1534 case 45: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001535 fuzz_paint(fuzz, &paint, depth - 1);
1536 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001537 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001538 SkScalar x, y;
1539 fuzz->next(&x, &y);
Hal Canary5395c592017-03-08 16:52:18 -05001540 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001541 canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001542 break;
1543 }
1544 case 46: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001545 fuzz_paint(fuzz, &paint, depth - 1);
1546 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001547 fuzz_paint_text_encoding(fuzz, &paint);
1548 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001549 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001550 if (glyphCount < 1) {
1551 break;
1552 }
1553 SkAutoTMalloc<SkPoint> pos(glyphCount);
1554 SkAutoTMalloc<SkScalar> widths(glyphCount);
Hal Canary671e4422017-02-27 13:36:38 -05001555 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001556 pos[0] = {0, 0};
1557 for (int i = 1; i < glyphCount; ++i) {
1558 float y;
Hal Canaryb69c4b82017-03-08 11:02:40 -05001559 fuzz->nextRange(&y, -0.5f * paint.getTextSize(), 0.5f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001560 pos[i] = {pos[i - 1].x() + widths[i - 1], y};
1561 }
Hal Canary671e4422017-02-27 13:36:38 -05001562 canvas->drawPosText(text.begin(), SkToSizeT(text.count()), pos.get(), paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001563 break;
1564 }
1565 case 47: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001566 fuzz_paint(fuzz, &paint, depth - 1);
1567 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001568 fuzz_paint_text_encoding(fuzz, &paint);
1569 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001570 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001571 SkAutoTMalloc<SkScalar> widths(glyphCount);
1572 if (glyphCount < 1) {
1573 break;
1574 }
Hal Canary671e4422017-02-27 13:36:38 -05001575 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001576 SkScalar x = widths[0];
1577 for (int i = 0; i < glyphCount; ++i) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001578 using std::swap;
1579 swap(x, widths[i]);
Hal Canary24ac42b2017-02-14 13:35:14 -05001580 x += widths[i];
1581 SkScalar offset;
1582 fuzz->nextRange(&offset, -0.125f * paint.getTextSize(),
Hal Canaryb69c4b82017-03-08 11:02:40 -05001583 0.125f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001584 widths[i] += offset;
1585 }
1586 SkScalar y;
1587 fuzz->next(&y);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001588 canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001589 break;
1590 }
1591 case 48: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001592 fuzz_paint(fuzz, &paint, depth - 1);
1593 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001594 fuzz_paint_text_encoding(fuzz, &paint);
1595 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001596 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -05001597 FuzzPath(fuzz, &path, 20);
Hal Canary24ac42b2017-02-14 13:35:14 -05001598 SkScalar hOffset, vOffset;
1599 fuzz->next(&hOffset, &vOffset);
Mike Reeda62d0362018-08-28 16:26:06 -04001600 SkDrawTextOnPathHV(text.begin(), SkToSizeT(text.count()), paint, path, hOffset,
1601 vOffset, canvas);
Hal Canary24ac42b2017-02-14 13:35:14 -05001602 break;
1603 }
1604 case 49: {
1605 SkMatrix matrix;
Hal Canary1e0138b2017-03-10 13:56:08 -05001606 bool useMatrix = make_fuzz_t<bool>(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001607 if (useMatrix) {
1608 fuzz->next(&matrix);
1609 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001610 fuzz_paint(fuzz, &paint, depth - 1);
1611 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001612 fuzz_paint_text_encoding(fuzz, &paint);
1613 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001614 SkPath path;
Cary Clark91390c82018-03-09 14:02:46 -05001615 FuzzPath(fuzz, &path, 20);
Mike Reeda62d0362018-08-28 16:26:06 -04001616 SkDrawTextOnPath(text.begin(), SkToSizeT(text.count()), paint, path,
1617 useMatrix ? &matrix :nullptr, canvas);
Hal Canary24ac42b2017-02-14 13:35:14 -05001618 break;
1619 }
1620 case 50: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001621 fuzz_paint(fuzz, &paint, depth - 1);
1622 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001623 fuzz_paint_text_encoding(fuzz, &paint);
1624 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1625 SkRSXform rSXform[kMaxGlyphCount];
1626 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1627 SkASSERT(glyphCount <= kMaxGlyphCount);
1628 fuzz->nextN(rSXform, glyphCount);
1629 SkRect cullRect;
1630 bool useCullRect;
1631 fuzz->next(&useCullRect);
1632 if (useCullRect) {
1633 fuzz->next(&cullRect);
1634 }
1635 canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
1636 useCullRect ? &cullRect : nullptr, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001637 break;
1638 }
1639 case 51: {
Hal Canary5395c592017-03-08 16:52:18 -05001640 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
Hal Canary1e0138b2017-03-10 13:56:08 -05001641 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -05001642 SkScalar x, y;
1643 fuzz->next(&x, &y);
1644 canvas->drawTextBlob(blob, x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001645 break;
1646 }
1647 case 52: {
1648 bool usePaint, useMatrix;
1649 fuzz->next(&usePaint, &useMatrix);
1650 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001651 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001652 }
1653 if (useMatrix) {
1654 fuzz->next(&matrix);
1655 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001656 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001657 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1658 usePaint ? &paint : nullptr);
1659 break;
1660 }
1661 case 53: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001662 fuzz_paint(fuzz, &paint, depth - 1);
Mike Reed887cdf12017-04-03 11:11:09 -04001663 SkVertices::VertexMode vertexMode;
Hal Canary5af600e2017-03-09 14:10:36 -05001664 SkBlendMode blendMode;
Mike Reed887cdf12017-04-03 11:11:09 -04001665 fuzz_enum_range(fuzz, &vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
Hal Canary5af600e2017-03-09 14:10:36 -05001666 fuzz->next(&blendMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001667 constexpr int kMaxCount = 100;
1668 int vertexCount;
1669 SkPoint vertices[kMaxCount];
1670 SkPoint texs[kMaxCount];
1671 SkColor colors[kMaxCount];
Hal Canary24ac42b2017-02-14 13:35:14 -05001672 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1673 fuzz->nextN(vertices, vertexCount);
1674 bool useTexs, useColors;
1675 fuzz->next(&useTexs, &useColors);
1676 if (useTexs) {
1677 fuzz->nextN(texs, vertexCount);
1678 }
1679 if (useColors) {
1680 fuzz->nextN(colors, vertexCount);
1681 }
1682 int indexCount = 0;
Hal Canary68b9b572017-03-02 15:27:23 -05001683 uint16_t indices[kMaxCount * 2];
Hal Canary1e0138b2017-03-10 13:56:08 -05001684 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary68b9b572017-03-02 15:27:23 -05001685 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1686 for (int i = 0; i < indexCount; ++i) {
1687 fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1688 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001689 }
Mike Reed887cdf12017-04-03 11:11:09 -04001690 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1691 useTexs ? texs : nullptr,
1692 useColors ? colors : nullptr,
1693 indexCount, indices),
1694 blendMode, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001695 break;
1696 }
1697 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -05001698 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -05001699 break;
1700 }
1701 }
1702}
1703
Hal Canary1e0138b2017-03-10 13:56:08 -05001704static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001705 SkScalar w, h;
1706 fuzz->next(&w, &h);
1707 SkPictureRecorder pictureRecorder;
1708 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1709 return pictureRecorder.finishRecordingAsPicture();
1710}
1711
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001712DEF_FUZZ(NullCanvas, fuzz) {
1713 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001714}
1715
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001716constexpr SkISize kCanvasSize = {128, 160};
Hal Canary44801ca2017-03-15 11:39:06 -04001717
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001718DEF_FUZZ(RasterN32Canvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001719 auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001720 if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001721 fuzz_canvas(fuzz, surface->getCanvas());
1722}
1723
Hal Canarye2924432017-12-01 11:46:26 -05001724DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1725 SkPictureRecorder recorder;
1726 fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1727 SkIntToScalar(kCanvasSize.height())));
1728 sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1729 if (!pic) { fuzz->signalBug(); }
1730 sk_sp<SkData> data = pic->serialize();
1731 if (!data) { fuzz->signalBug(); }
Mike Reedfadbfcd2017-12-06 16:09:20 -05001732 SkReadBuffer rb(data->data(), data->size());
Cary Clarkefd99cc2018-06-11 16:25:43 -04001733 auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
Hal Canarye2924432017-12-01 11:46:26 -05001734 if (!deserialized) { fuzz->signalBug(); }
1735 auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1736 SkASSERT(surface && surface->getCanvas());
1737 surface->getCanvas()->drawPicture(deserialized);
1738}
1739
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001740DEF_FUZZ(ImageFilter, fuzz) {
1741 auto fil = make_fuzz_imageFilter(fuzz, 20);
1742
1743 SkPaint paint;
1744 paint.setImageFilter(fil);
1745 SkBitmap bitmap;
1746 SkCanvas canvas(bitmap);
1747 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1748}
1749
1750
1751//SkRandom _rand;
1752#define SK_ADD_RANDOM_BIT_FLIPS
1753
1754DEF_FUZZ(SerializedImageFilter, fuzz) {
1755 auto filter = make_fuzz_imageFilter(fuzz, 20);
1756 auto data = filter->serialize();
1757 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1758 size_t len = data->size();
1759#ifdef SK_ADD_RANDOM_BIT_FLIPS
1760 unsigned char* p = const_cast<unsigned char*>(ptr);
1761 for (size_t i = 0; i < len; ++i, ++p) {
1762 uint8_t j;
1763 fuzz->nextRange(&j, 1, 250);
1764 if (j == 1) { // 0.4% of the time, flip a bit or byte
1765 uint8_t k;
1766 fuzz->nextRange(&k, 1, 10);
1767 if (k == 1) { // Then 10% of the time, change a whole byte
1768 uint8_t s;
1769 fuzz->nextRange(&s, 0, 2);
1770 switch(s) {
1771 case 0:
1772 *p ^= 0xFF; // Flip entire byte
1773 break;
1774 case 1:
1775 *p = 0xFF; // Set all bits to 1
1776 break;
1777 case 2:
1778 *p = 0x00; // Set all bits to 0
1779 break;
1780 }
1781 } else {
1782 uint8_t s;
1783 fuzz->nextRange(&s, 0, 7);
1784 *p ^= (1 << 7);
1785 }
1786 }
1787 }
1788#endif // SK_ADD_RANDOM_BIT_FLIPS
1789 auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1790
1791 // uncomment below to write out a serialized image filter (to make corpus
1792 // for -t filter_fuzz)
1793 // SkString s("./serialized_filters/sf");
1794 // s.appendU32(_rand.nextU());
1795 // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1796 // sk_fwrite(data->bytes(), data->size(), file);
1797 // sk_fclose(file);
1798
1799 SkPaint paint;
1800 paint.setImageFilter(deserializedFil);
1801 SkBitmap bitmap;
1802 SkCanvas canvas(bitmap);
1803 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1804}
1805
Hal Canary44801ca2017-03-15 11:39:06 -04001806#if SK_SUPPORT_GPU
Kevin Lubickfaef5142018-06-07 10:33:11 -04001807
1808static void dump_GPU_info(GrContext* context) {
1809 const GrGLInterface* gl = static_cast<GrGLGpu*>(context->contextPriv().getGpu())
1810 ->glInterface();
1811 const GrGLubyte* output;
1812 GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1813 SkDebugf("GL_RENDERER %s\n", (const char*) output);
1814
1815 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1816 SkDebugf("GL_VENDOR %s\n", (const char*) output);
1817
1818 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1819 SkDebugf("GL_VERSION %s\n", (const char*) output);
1820}
1821
Hal Canary5aa91582017-03-21 11:11:44 -07001822static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
1823 SkASSERT(context);
1824 auto surface = SkSurface::MakeRenderTarget(
1825 context,
1826 SkBudgeted::kNo,
1827 SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1828 SkASSERT(surface && surface->getCanvas());
1829 fuzz_canvas(fuzz, surface->getCanvas());
1830}
1831
Hal Canary44801ca2017-03-15 11:39:06 -04001832DEF_FUZZ(NativeGLCanvas, fuzz) {
Hal Canary549be4a2018-01-05 16:59:53 -05001833 sk_gpu_test::GrContextFactory f;
1834 GrContext* context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
Brian Salomon6405e712017-03-20 08:54:16 -04001835 if (!context) {
Hal Canary549be4a2018-01-05 16:59:53 -05001836 context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
Brian Salomon6405e712017-03-20 08:54:16 -04001837 }
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001838 if (FLAGS_gpuInfo) {
Kevin Lubickfaef5142018-06-07 10:33:11 -04001839 dump_GPU_info(context);
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001840 }
Hal Canary5aa91582017-03-21 11:11:44 -07001841 fuzz_ganesh(fuzz, context);
1842}
1843
Kevin Lubick27d42192018-04-03 12:30:32 -04001844// This target is deprecated, NullGLContext is not well maintained.
1845// Please use MockGPUCanvas instead.
Hal Canary5aa91582017-03-21 11:11:44 -07001846DEF_FUZZ(NullGLCanvas, fuzz) {
Hal Canary549be4a2018-01-05 16:59:53 -05001847 sk_gpu_test::GrContextFactory f;
1848 fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kNullGL_ContextType));
Hal Canary5aa91582017-03-21 11:11:44 -07001849}
1850
Kevin Lubick27d42192018-04-03 12:30:32 -04001851DEF_FUZZ(MockGPUCanvas, fuzz) {
Kevin Lubick30709262018-04-02 11:06:41 -04001852 sk_gpu_test::GrContextFactory f;
1853 fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
1854}
Hal Canary44801ca2017-03-15 11:39:06 -04001855#endif
1856
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001857DEF_FUZZ(PDFCanvas, fuzz) {
Hal Canaryfe759302017-08-26 17:06:42 -04001858 SkNullWStream stream;
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001859 auto doc = SkDocument::MakePDF(&stream);
Hal Canary44801ca2017-03-15 11:39:06 -04001860 fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1861 SkIntToScalar(kCanvasSize.height())));
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001862}
1863
1864// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1865DEF_FUZZ(_DumpCanvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001866 SkDebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001867 fuzz_canvas(fuzz, &debugCanvas);
1868 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1869 UrlDataManager dataManager(SkString("data"));
1870 Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
1871 Json::StyledStreamWriter(" ").write(std::cout, json);
1872}