blob: 3b3715fe8ad3491f5f5b4b262a588128955777d5 [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"
Hal Canary24ac42b2017-02-14 13:35:14 -05009
10// CORE
11#include "SkCanvas.h"
12#include "SkColorFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050013#include "SkDebugCanvas.h"
14#include "SkDocument.h"
Hal Canary671e4422017-02-27 13:36:38 -050015#include "SkFontMgr.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050016#include "SkImageFilter.h"
17#include "SkMaskFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050018#include "SkNullCanvas.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050019#include "SkPathEffect.h"
20#include "SkPictureRecorder.h"
Mike Reed54518ac2017-07-22 08:29:48 -040021#include "SkPoint3.h"
Hal Canary5395c592017-03-08 16:52:18 -050022#include "SkRSXform.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050023#include "SkRegion.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050024#include "SkSurface.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050025#include "SkTypeface.h"
26
27// EFFECTS
Hal Canary5395c592017-03-08 16:52:18 -050028#include "Sk1DPathEffect.h"
29#include "Sk2DPathEffect.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050030#include "SkAlphaThresholdFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050031#include "SkArithmeticImageFilter.h"
Robert Phillips70e3e9a2017-06-26 14:22:01 -040032#include "SkBlurImageFilter.h"
Hal Canary5395c592017-03-08 16:52:18 -050033#include "SkBlurMaskFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050034#include "SkColorFilterImageFilter.h"
Hal Canary27bece82017-03-07 16:23:20 -050035#include "SkColorMatrixFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050036#include "SkComposeImageFilter.h"
Hal Canary5395c592017-03-08 16:52:18 -050037#include "SkCornerPathEffect.h"
38#include "SkDashPathEffect.h"
39#include "SkDiscretePathEffect.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050040#include "SkDisplacementMapEffect.h"
41#include "SkDropShadowImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050042#include "SkGradientShader.h"
Hal Canary27bece82017-03-07 16:23:20 -050043#include "SkHighContrastFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050044#include "SkImageSource.h"
45#include "SkLightingImageFilter.h"
Hal Canary27bece82017-03-07 16:23:20 -050046#include "SkLumaColorFilter.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050047#include "SkMagnifierImageFilter.h"
48#include "SkMatrixConvolutionImageFilter.h"
49#include "SkMergeImageFilter.h"
50#include "SkMorphologyImageFilter.h"
51#include "SkOffsetImageFilter.h"
52#include "SkPaintImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050053#include "SkPerlinNoiseShader.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050054#include "SkPictureImageFilter.h"
Hal Canary5395c592017-03-08 16:52:18 -050055#include "SkRRectsGaussianEdgeMaskFilter.h"
Hal Canary27bece82017-03-07 16:23:20 -050056#include "SkTableColorFilter.h"
Mike Reedc090c642017-05-16 10:39:06 -040057#include "SkTextBlob.h"
Hal Canarye03c3e52017-03-09 11:33:35 -050058#include "SkTileImageFilter.h"
59#include "SkXfermodeImageFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050060
61// SRC
62#include "SkUtils.h"
63
Hal Canary44801ca2017-03-15 11:39:06 -040064#if SK_SUPPORT_GPU
65#include "GrContextFactory.h"
66#endif
67
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050068// MISC
69
70#include <iostream>
71
Hal Canary24ac42b2017-02-14 13:35:14 -050072// TODO:
Hal Canary5395c592017-03-08 16:52:18 -050073// SkTextBlob with Unicode
Hal Canary44801ca2017-03-15 11:39:06 -040074// SkImage: more types
Hal Canary24ac42b2017-02-14 13:35:14 -050075
Hal Canaryf7005202017-03-10 08:48:28 -050076template <typename T, typename Min, typename Max>
77inline void fuzz_enum_range(Fuzz* fuzz, T* value, Min rmin, Max rmax) {
Hal Canary24ac42b2017-02-14 13:35:14 -050078 using U = skstd::underlying_type_t<T>;
Hal Canaryf7005202017-03-10 08:48:28 -050079 fuzz->nextRange((U*)value, (U)rmin, (U)rmax);
80}
81
Hal Canary1e0138b2017-03-10 13:56:08 -050082// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
83// In fact, all make_fuzz_foo() functions have this potential problem.
84// Use sequence points!
85template <typename T>
86inline T make_fuzz_t(Fuzz* fuzz) {
87 T t;
88 fuzz->next(&t);
89 return t;
Hal Canary24ac42b2017-02-14 13:35:14 -050090}
91
Hal Canary1e0138b2017-03-10 13:56:08 -050092// We don't always want to test NaNs and infinities.
Hal Canaryce540ea2017-03-06 08:30:44 -050093static void fuzz_nice_float(Fuzz* fuzz, float* f) {
Hal Canary1e0138b2017-03-10 13:56:08 -050094 float v;
95 fuzz->next(&v);
96 constexpr float kLimit = 1.0e35f; // FLT_MAX?
97 *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
Hal Canaryce540ea2017-03-06 08:30:44 -050098}
Hal Canary24ac42b2017-02-14 13:35:14 -050099
Hal Canaryce540ea2017-03-06 08:30:44 -0500100template <typename... Args>
Hal Canary1e0138b2017-03-10 13:56:08 -0500101inline void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
Hal Canaryce540ea2017-03-06 08:30:44 -0500102 fuzz_nice_float(fuzz, f);
103 fuzz_nice_float(fuzz, rest...);
104}
105
106static void fuzz_path(Fuzz* fuzz, SkPath* path, int maxOps) {
107 if (maxOps < 2) {
108 maxOps = 2;
109 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500110 uint8_t fillType;
111 fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType);
112 path->setFillType((SkPath::FillType)fillType);
113 uint8_t numOps;
Hal Canaryce540ea2017-03-06 08:30:44 -0500114 fuzz->nextRange(&numOps, 2, maxOps);
Hal Canary24ac42b2017-02-14 13:35:14 -0500115 for (uint8_t i = 0; i < numOps; ++i) {
116 uint8_t op;
117 fuzz->nextRange(&op, 0, 6);
118 SkScalar a, b, c, d, e, f;
119 switch (op) {
120 case 0:
Hal Canaryce540ea2017-03-06 08:30:44 -0500121 fuzz_nice_float(fuzz, &a, &b);
Hal Canary24ac42b2017-02-14 13:35:14 -0500122 path->moveTo(a, b);
123 break;
124 case 1:
Hal Canaryce540ea2017-03-06 08:30:44 -0500125 fuzz_nice_float(fuzz, &a, &b);
Hal Canary24ac42b2017-02-14 13:35:14 -0500126 path->lineTo(a, b);
127 break;
128 case 2:
Hal Canaryce540ea2017-03-06 08:30:44 -0500129 fuzz_nice_float(fuzz, &a, &b, &c, &d);
Hal Canary24ac42b2017-02-14 13:35:14 -0500130 path->quadTo(a, b, c, d);
131 break;
132 case 3:
Hal Canaryce540ea2017-03-06 08:30:44 -0500133 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
Hal Canary24ac42b2017-02-14 13:35:14 -0500134 path->conicTo(a, b, c, d, e);
135 break;
136 case 4:
Hal Canaryce540ea2017-03-06 08:30:44 -0500137 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500138 path->cubicTo(a, b, c, d, e, f);
139 break;
140 case 5:
Hal Canaryce540ea2017-03-06 08:30:44 -0500141 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
Hal Canary24ac42b2017-02-14 13:35:14 -0500142 path->arcTo(a, b, c, d, e);
143 break;
144 case 6:
145 path->close();
146 break;
147 default:
148 break;
149 }
150 }
151}
152
Hal Canarye03c3e52017-03-09 11:33:35 -0500153template <>
154inline void Fuzz::next(SkRegion* region) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500155 uint8_t N;
Hal Canarye03c3e52017-03-09 11:33:35 -0500156 this->nextRange(&N, 0, 10);
Hal Canary24ac42b2017-02-14 13:35:14 -0500157 for (uint8_t i = 0; i < N; ++i) {
158 SkIRect r;
159 uint8_t op;
Hal Canarye03c3e52017-03-09 11:33:35 -0500160 this->next(&r);
Hal Canary24ac42b2017-02-14 13:35:14 -0500161 r.sort();
Hal Canarye03c3e52017-03-09 11:33:35 -0500162 this->nextRange(&op, 0, (uint8_t)SkRegion::kLastOp);
Hal Canary24ac42b2017-02-14 13:35:14 -0500163 if (!region->op(r, (SkRegion::Op)op)) {
164 return;
165 }
166 }
167}
168
Hal Canaryb69c4b82017-03-08 11:02:40 -0500169template <>
170inline void Fuzz::next(SkShader::TileMode* m) {
Hal Canaryf7005202017-03-10 08:48:28 -0500171 fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500172}
173
Hal Canaryb69c4b82017-03-08 11:02:40 -0500174template <>
Hal Canarye03c3e52017-03-09 11:33:35 -0500175inline void Fuzz::next(SkFilterQuality* q) {
Hal Canaryf7005202017-03-10 08:48:28 -0500176 fuzz_enum_range(this, q, SkFilterQuality::kNone_SkFilterQuality,
177 SkFilterQuality::kLast_SkFilterQuality);
Hal Canarye03c3e52017-03-09 11:33:35 -0500178}
179
180template <>
Hal Canaryb69c4b82017-03-08 11:02:40 -0500181inline void Fuzz::next(SkMatrix* m) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500182 constexpr int kArrayLength = 9;
183 SkScalar buffer[kArrayLength];
184 int matrixType;
185 this->nextRange(&matrixType, 0, 4);
186 switch (matrixType) {
187 case 0: // identity
188 *m = SkMatrix::I();
189 return;
190 case 1: // translate
191 this->nextRange(&buffer[0], -4000.0f, 4000.0f);
192 this->nextRange(&buffer[1], -4000.0f, 4000.0f);
193 *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
194 return;
195 case 2: // translate + scale
196 this->nextRange(&buffer[0], -400.0f, 400.0f);
197 this->nextRange(&buffer[1], -400.0f, 400.0f);
198 this->nextRange(&buffer[2], -4000.0f, 4000.0f);
199 this->nextRange(&buffer[3], -4000.0f, 4000.0f);
200 *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
201 m->postTranslate(buffer[2], buffer[3]);
202 return;
203 case 3: // affine
204 this->nextN(buffer, 6);
205 m->setAffine(buffer);
206 return;
207 case 4: // perspective
208 this->nextN(buffer, kArrayLength);
209 m->set9(buffer);
210 return;
211 default:
212 return;
213 }
214}
215
Hal Canaryb69c4b82017-03-08 11:02:40 -0500216template <>
217inline void Fuzz::next(SkRRect* rr) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500218 SkRect r;
219 SkVector radii[4];
220 this->next(&r);
Hal Canary27bece82017-03-07 16:23:20 -0500221 r.sort();
222 for (SkVector& vec : radii) {
223 this->nextRange(&vec.fX, 0.0f, 1.0f);
224 vec.fX *= 0.5f * r.width();
225 this->nextRange(&vec.fY, 0.0f, 1.0f);
226 vec.fY *= 0.5f * r.height();
227 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500228 rr->setRectRadii(r, radii);
Hal Canary24ac42b2017-02-14 13:35:14 -0500229}
230
Hal Canaryb69c4b82017-03-08 11:02:40 -0500231template <>
232inline void Fuzz::next(SkBlendMode* mode) {
Hal Canaryf7005202017-03-10 08:48:28 -0500233 fuzz_enum_range(this, mode, 0, SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -0500234}
235
Hal Canary1e0138b2017-03-10 13:56:08 -0500236static sk_sp<SkImage> make_fuzz_image(Fuzz*);
Hal Canary671e4422017-02-27 13:36:38 -0500237
Hal Canary1e0138b2017-03-10 13:56:08 -0500238static SkBitmap make_fuzz_bitmap(Fuzz*);
Hal Canary24ac42b2017-02-14 13:35:14 -0500239
Hal Canary1e0138b2017-03-10 13:56:08 -0500240static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
Hal Canary671e4422017-02-27 13:36:38 -0500241
Hal Canary1e0138b2017-03-10 13:56:08 -0500242static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
Hal Canary27bece82017-03-07 16:23:20 -0500243 if (depth <= 0) {
244 return nullptr;
245 }
246 int colorFilterType;
247 fuzz->nextRange(&colorFilterType, 0, 8);
248 switch (colorFilterType) {
249 case 0:
250 return nullptr;
251 case 1: {
252 SkColor color;
253 SkBlendMode mode;
254 fuzz->next(&color, &mode);
255 return SkColorFilter::MakeModeFilter(color, mode);
256 }
257 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500258 sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
259 sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
Hal Canary27bece82017-03-07 16:23:20 -0500260 return SkColorFilter::MakeComposeFilter(std::move(outer), std::move(inner));
261 }
262 case 3: {
263 SkScalar array[20];
264 fuzz->nextN(array, SK_ARRAY_COUNT(array));
265 return SkColorFilter::MakeMatrixFilterRowMajor255(array);
266 }
267 case 4: {
268 SkColor mul, add;
269 fuzz->next(&mul, &add);
270 return SkColorMatrixFilter::MakeLightingFilter(mul, add);
271 }
272 case 5: {
273 bool grayscale;
274 int invertStyle;
275 float contrast;
276 fuzz->next(&grayscale);
277 fuzz->nextRange(&invertStyle, 0, 2);
278 fuzz->nextRange(&contrast, -1.0f, 1.0f);
279 return SkHighContrastFilter::Make(SkHighContrastConfig(
280 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
281 }
282 case 6:
283 return SkLumaColorFilter::Make();
284 case 7: {
285 uint8_t table[256];
286 fuzz->nextN(table, SK_ARRAY_COUNT(table));
287 return SkTableColorFilter::Make(table);
288 }
289 case 8: {
290 uint8_t tableA[256];
291 uint8_t tableR[256];
292 uint8_t tableG[256];
293 uint8_t tableB[256];
294 fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
295 fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
296 fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
297 fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
298 return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
299 }
300 }
301 return nullptr;
302}
Hal Canary24ac42b2017-02-14 13:35:14 -0500303
Hal Canary1e0138b2017-03-10 13:56:08 -0500304static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500305 SkScalar totalPos = 0;
306 for (int i = 0; i < colorCount; ++i) {
307 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
308 totalPos += pos[i];
309 }
310 totalPos = 1.0f / totalPos;
311 for (int i = 0; i < colorCount; ++i) {
312 pos[i] *= totalPos;
313 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500314 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500315 pos[colorCount - 1] = 1.0f;
316}
317
Hal Canary1e0138b2017-03-10 13:56:08 -0500318static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500319 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
320 sk_sp<SkColorFilter> colorFilter(nullptr);
321 SkBitmap bitmap;
322 sk_sp<SkImage> img;
323 SkShader::TileMode tmX, tmY;
324 bool useMatrix;
325 SkColor color;
326 SkMatrix matrix;
327 SkBlendMode blendMode;
328 int shaderType;
329 if (depth <= 0) {
330 return nullptr;
331 }
Hal Canary671e4422017-02-27 13:36:38 -0500332 fuzz->nextRange(&shaderType, 0, 14);
Hal Canary24ac42b2017-02-14 13:35:14 -0500333 switch (shaderType) {
334 case 0:
335 return nullptr;
336 case 1:
337 return SkShader::MakeEmptyShader();
338 case 2:
339 fuzz->next(&color);
340 return SkShader::MakeColorShader(color);
341 case 3:
Hal Canary1e0138b2017-03-10 13:56:08 -0500342 img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -0500343 fuzz->next(&tmX, &tmY, &useMatrix);
344 if (useMatrix) {
345 fuzz->next(&matrix);
346 }
347 return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
348 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -0500349 bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -0500350 fuzz->next(&tmX, &tmY, &useMatrix);
351 if (useMatrix) {
352 fuzz->next(&matrix);
353 }
354 return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
355 case 5:
Hal Canary1e0138b2017-03-10 13:56:08 -0500356 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
Hal Canary24ac42b2017-02-14 13:35:14 -0500357 fuzz->next(&matrix);
358 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
359 case 6:
Hal Canary1e0138b2017-03-10 13:56:08 -0500360 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
361 colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500362 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
363 case 7:
Hal Canary1e0138b2017-03-10 13:56:08 -0500364 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
365 shader2 = make_fuzz_shader(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500366 fuzz->next(&blendMode);
367 return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500368 case 8: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500369 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500370 bool useTile;
371 SkRect tile;
372 fuzz->next(&tmX, &tmY, &useMatrix, &useTile);
373 if (useMatrix) {
374 fuzz->next(&matrix);
Hal Canary671e4422017-02-27 13:36:38 -0500375 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500376 if (useTile) {
377 fuzz->next(&tile);
378 }
379 return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
380 useMatrix ? &matrix : nullptr,
381 useTile ? &tile : nullptr);
382 }
Hal Canary671e4422017-02-27 13:36:38 -0500383 // EFFECTS:
Hal Canary24ac42b2017-02-14 13:35:14 -0500384 case 9:
Florin Malitabb3f5622017-05-31 14:20:12 +0000385 // Deprecated SkGaussianEdgeShader
386 return nullptr;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500387 case 10: {
388 constexpr int kMaxColors = 12;
389 SkPoint pts[2];
390 SkColor colors[kMaxColors];
391 SkScalar pos[kMaxColors];
392 int colorCount;
393 bool usePos;
394 fuzz->nextN(pts, 2);
395 fuzz->nextRange(&colorCount, 2, kMaxColors);
396 fuzz->nextN(colors, colorCount);
397 fuzz->next(&tmX, &useMatrix, &usePos);
398 if (useMatrix) {
399 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500400 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500401 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500402 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500403 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500404 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
405 tmX, 0, useMatrix ? &matrix : nullptr);
406 }
407 case 11: {
408 constexpr int kMaxColors = 12;
409 SkPoint center;
410 SkScalar radius;
411 int colorCount;
412 bool usePos;
413 SkColor colors[kMaxColors];
414 SkScalar pos[kMaxColors];
415 fuzz->next(&tmX, &useMatrix, &usePos, &center, &radius);
416 fuzz->nextRange(&colorCount, 2, kMaxColors);
417 fuzz->nextN(colors, colorCount);
418 if (useMatrix) {
419 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500420 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500421 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500422 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500423 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500424 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
425 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
426 }
427 case 12: {
428 constexpr int kMaxColors = 12;
429 SkPoint start, end;
430 SkScalar startRadius, endRadius;
431 int colorCount;
432 bool usePos;
433 SkColor colors[kMaxColors];
434 SkScalar pos[kMaxColors];
435 fuzz->next(&tmX, &useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
436 fuzz->nextRange(&colorCount, 2, kMaxColors);
437 fuzz->nextN(colors, colorCount);
438 if (useMatrix) {
439 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500440 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500441 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500442 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500443 }
444 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
445 usePos ? pos : nullptr, colorCount, tmX, 0,
446 useMatrix ? &matrix : nullptr);
447 }
448 case 13: {
449 constexpr int kMaxColors = 12;
450 SkScalar cx, cy;
451 int colorCount;
452 bool usePos;
453 SkColor colors[kMaxColors];
454 SkScalar pos[kMaxColors];
455 fuzz->next(&cx, &cy, &useMatrix, &usePos);
456 fuzz->nextRange(&colorCount, 2, kMaxColors);
457 fuzz->nextN(colors, colorCount);
458 if (useMatrix) {
459 fuzz->next(&matrix);
460 }
461 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500462 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500463 }
464 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
465 0, useMatrix ? &matrix : nullptr);
466 }
467 case 14: {
468 SkScalar baseFrequencyX, baseFrequencyY, seed;
469 int numOctaves;
470 SkISize tileSize;
471 bool useTileSize, turbulence;
472 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
473 if (useTileSize) {
474 fuzz->next(&tileSize);
475 }
476 fuzz->nextRange(&numOctaves, 2, 7);
477 if (turbulence) {
478 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
479 numOctaves, seed,
480 useTileSize ? &tileSize : nullptr);
481 } else {
482 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
483 numOctaves, seed,
484 useTileSize ? &tileSize : nullptr);
485 }
486 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500487 default:
488 break;
489 }
Kevin Lubickedbeb8b2017-02-27 16:45:32 -0500490 return nullptr;
Hal Canary24ac42b2017-02-14 13:35:14 -0500491}
492
Hal Canary1e0138b2017-03-10 13:56:08 -0500493static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
Hal Canary5395c592017-03-08 16:52:18 -0500494 if (depth <= 0) {
495 return nullptr;
496 }
497 uint8_t pathEffectType;
Mike Reed40e7e652017-07-22 22:12:59 -0400498 fuzz->nextRange(&pathEffectType, 0, 8);
Hal Canary5395c592017-03-08 16:52:18 -0500499 switch (pathEffectType) {
500 case 0: {
501 return nullptr;
502 }
503 case 1: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500504 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
505 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500506 return SkPathEffect::MakeSum(std::move(first), std::move(second));
507 }
508 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500509 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
510 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500511 return SkPathEffect::MakeCompose(std::move(first), std::move(second));
512 }
513 case 3: {
514 SkPath path;
515 fuzz_path(fuzz, &path, 20);
516 SkScalar advance, phase;
517 fuzz->next(&advance, &phase);
Hal Canaryf7005202017-03-10 08:48:28 -0500518 SkPath1DPathEffect::Style style;
519 fuzz_enum_range(fuzz, &style, 0, SkPath1DPathEffect::kLastEnum_Style);
520 return SkPath1DPathEffect::Make(path, advance, phase, style);
Hal Canary5395c592017-03-08 16:52:18 -0500521 }
522 case 4: {
523 SkScalar width;
524 SkMatrix matrix;
525 fuzz->next(&width, &matrix);
526 return SkLine2DPathEffect::Make(width, matrix);
527 }
528 case 5: {
529 SkPath path;
530 fuzz_path(fuzz, &path, 20);
531 SkMatrix matrix;
532 fuzz->next(&matrix);
533 return SkPath2DPathEffect::Make(matrix, path);
534 }
535 case 6: {
536 SkScalar radius;
537 fuzz->next(&radius);
Hal Canary5395c592017-03-08 16:52:18 -0500538 return SkCornerPathEffect::Make(radius);
539 }
Mike Reed40e7e652017-07-22 22:12:59 -0400540 case 7: {
Hal Canary5395c592017-03-08 16:52:18 -0500541 SkScalar phase;
542 fuzz->next(&phase);
543 SkScalar intervals[20];
544 int count;
545 fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
546 fuzz->nextN(intervals, count);
547 return SkDashPathEffect::Make(intervals, count, phase);
548 }
Mike Reed40e7e652017-07-22 22:12:59 -0400549 case 8: {
Hal Canary5395c592017-03-08 16:52:18 -0500550 SkScalar segLength, dev;
551 uint32_t seed;
552 fuzz->next(&segLength, &dev, &seed);
553 return SkDiscretePathEffect::Make(segLength, dev, seed);
554 }
555 default:
556 SkASSERT(false);
557 return nullptr;
558 }
559}
Hal Canary24ac42b2017-02-14 13:35:14 -0500560
Hal Canary1e0138b2017-03-10 13:56:08 -0500561static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
Hal Canary5395c592017-03-08 16:52:18 -0500562 int maskfilterType;
563 fuzz->nextRange(&maskfilterType, 0, 2);
564 switch (maskfilterType) {
565 case 0:
566 return nullptr;
567 case 1: {
Hal Canaryf7005202017-03-10 08:48:28 -0500568 SkBlurStyle blurStyle;
569 fuzz_enum_range(fuzz, &blurStyle, 0, kLastEnum_SkBlurStyle);
Hal Canary5395c592017-03-08 16:52:18 -0500570 SkScalar sigma;
571 fuzz->next(&sigma);
572 SkRect occluder{0.0f, 0.0f, 0.0f, 0.0f};
Hal Canary1e0138b2017-03-10 13:56:08 -0500573 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -0500574 fuzz->next(&occluder);
575 }
576 uint32_t flags;
577 fuzz->nextRange(&flags, 0, 3);
Hal Canaryf7005202017-03-10 08:48:28 -0500578 return SkBlurMaskFilter::Make(blurStyle, sigma, occluder, flags);
Hal Canary5395c592017-03-08 16:52:18 -0500579 }
580 case 2: {
581 SkRRect first, second;
582 SkScalar radius;
583 fuzz->next(&first, &second, &radius);
584 return SkRRectsGaussianEdgeMaskFilter::Make(first, second, radius);
585 }
586 default:
587 SkASSERT(false);
588 return nullptr;
589 }
590}
Hal Canary24ac42b2017-02-14 13:35:14 -0500591
Hal Canary1e0138b2017-03-10 13:56:08 -0500592static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
593 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary671e4422017-02-27 13:36:38 -0500594 return nullptr;
595 }
596 auto fontMugger = SkFontMgr::RefDefault();
597 SkASSERT(fontMugger);
598 int familyCount = fontMugger->countFamilies();
599 int i, j;
600 fuzz->nextRange(&i, 0, familyCount - 1);
601 sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
602 int styleCount = family->count();
603 fuzz->nextRange(&j, 0, styleCount - 1);
604 return sk_sp<SkTypeface>(family->createTypeface(j));
605}
Hal Canary24ac42b2017-02-14 13:35:14 -0500606
Hal Canarye03c3e52017-03-09 11:33:35 -0500607template <>
608inline void Fuzz::next(SkImageFilter::CropRect* cropRect) {
609 SkRect rect;
610 uint8_t flags;
611 this->next(&rect);
612 this->nextRange(&flags, 0, 0xF);
613 *cropRect = SkImageFilter::CropRect(rect, flags);
614}
615
Hal Canary1e0138b2017-03-10 13:56:08 -0500616static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500617
618static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
619 if (depth <= 0) {
620 return nullptr;
621 }
622 uint8_t imageFilterType;
623 fuzz->nextRange(&imageFilterType, 1, 6);
624 SkPoint3 p, q;
625 SkColor lightColor;
626 SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
627 sk_sp<SkImageFilter> input;
628 SkImageFilter::CropRect cropRect;
629 bool useCropRect;
630 fuzz->next(&useCropRect);
631 if (useCropRect) {
632 fuzz->next(&cropRect);
633 }
634 switch (imageFilterType) {
635 case 1:
636 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500637 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500638 return SkLightingImageFilter::MakeDistantLitDiffuse(p, lightColor, surfaceScale, k,
639 std::move(input),
640 useCropRect ? &cropRect : nullptr);
641 case 2:
642 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500643 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500644 return SkLightingImageFilter::MakePointLitDiffuse(p, lightColor, surfaceScale, k,
645 std::move(input),
646 useCropRect ? &cropRect : nullptr);
647 case 3:
648 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500649 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500650 return SkLightingImageFilter::MakeSpotLitDiffuse(
651 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
652 std::move(input), useCropRect ? &cropRect : nullptr);
653 case 4:
654 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500655 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500656 return SkLightingImageFilter::MakeDistantLitSpecular(p, lightColor, surfaceScale, k,
657 shininess, std::move(input),
658 useCropRect ? &cropRect : nullptr);
659 case 5:
660 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500661 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500662 return SkLightingImageFilter::MakePointLitSpecular(p, lightColor, surfaceScale, k,
663 shininess, std::move(input),
664 useCropRect ? &cropRect : nullptr);
665 case 6:
666 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
667 &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500668 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500669 return SkLightingImageFilter::MakeSpotLitSpecular(
670 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
671 std::move(input), useCropRect ? &cropRect : nullptr);
672 default:
673 SkASSERT(false);
674 return nullptr;
675 }
676}
677
Hal Canary1e0138b2017-03-10 13:56:08 -0500678static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500679
Hal Canary1e0138b2017-03-10 13:56:08 -0500680static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
Hal Canarye03c3e52017-03-09 11:33:35 -0500681 if (depth <= 0) {
682 return nullptr;
683 }
684 uint8_t imageFilterType;
685 fuzz->nextRange(&imageFilterType, 0, 24);
686 switch (imageFilterType) {
687 case 0:
688 return nullptr;
689 case 1: {
690 SkScalar sigmaX, sigmaY;
Hal Canary1e0138b2017-03-10 13:56:08 -0500691 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500692 bool useCropRect;
693 fuzz->next(&sigmaX, &sigmaY, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400694 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500695 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400696 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500697 }
Robert Phillips70e3e9a2017-06-26 14:22:01 -0400698 return SkBlurImageFilter::Make(sigmaX, sigmaY, std::move(input),
Hal Canarye03c3e52017-03-09 11:33:35 -0500699 useCropRect ? &cropRect : nullptr);
700 }
701 case 2: {
702 SkMatrix matrix;
703 SkFilterQuality quality;
704 fuzz->next(&matrix, &quality);
Hal Canary1e0138b2017-03-10 13:56:08 -0500705 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500706 return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
707 }
708 case 3: {
709 SkRegion region;
710 SkScalar innerMin, outerMax;
Hal Canary1e0138b2017-03-10 13:56:08 -0500711 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500712 bool useCropRect;
713 fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400714 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500715 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400716 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500717 }
718 return SkAlphaThresholdFilter::Make(region, innerMin, outerMax, std::move(input),
719 useCropRect ? &cropRect : nullptr);
720 }
721 case 4: {
722 float k1, k2, k3, k4;
723 bool enforcePMColor;
724 bool useCropRect;
725 fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500726 sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
727 sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500728 SkImageFilter::CropRect cropRect;
729 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400730 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500731 }
732 return SkArithmeticImageFilter::Make(k1, k2, k3, k4, enforcePMColor,
733 std::move(background), std::move(foreground),
734 useCropRect ? &cropRect : nullptr);
735 }
736 case 5: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500737 sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
738 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500739 bool useCropRect;
740 SkImageFilter::CropRect cropRect;
741 fuzz->next(&useCropRect);
742 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400743 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500744 }
745 return SkColorFilterImageFilter::Make(std::move(cf), std::move(input),
746 useCropRect ? &cropRect : nullptr);
747 }
748 case 6: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500749 sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
750 sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500751 return SkComposeImageFilter::Make(std::move(ifo), std::move(ifi));
752 }
753 case 7: {
754 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, yChannelSelector;
Hal Canaryf49b1e02017-03-15 16:58:33 -0400755 fuzz_enum_range(fuzz, &xChannelSelector, 1, 4);
756 fuzz_enum_range(fuzz, &yChannelSelector, 1, 4);
Hal Canarye03c3e52017-03-09 11:33:35 -0500757 SkScalar scale;
758 bool useCropRect;
759 fuzz->next(&scale, &useCropRect);
760 SkImageFilter::CropRect cropRect;
761 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400762 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500763 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500764 sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
765 sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500766 return SkDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
767 std::move(displacement), std::move(color),
768 useCropRect ? &cropRect : nullptr);
769 }
770 case 8: {
771 SkScalar dx, dy, sigmaX, sigmaY;
772 SkColor color;
773 SkDropShadowImageFilter::ShadowMode shadowMode;
Hal Canaryf7005202017-03-10 08:48:28 -0500774 fuzz_enum_range(fuzz, &shadowMode, 0, 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500775 bool useCropRect;
776 fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &useCropRect);
777 SkImageFilter::CropRect cropRect;
778 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400779 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500780 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500781 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500782 return SkDropShadowImageFilter::Make(dx, dy, sigmaX, sigmaY, color, shadowMode,
783 std::move(input),
784 useCropRect ? &cropRect : nullptr);
785 }
786 case 9:
Hal Canary1e0138b2017-03-10 13:56:08 -0500787 return SkImageSource::Make(make_fuzz_image(fuzz));
Hal Canarye03c3e52017-03-09 11:33:35 -0500788 case 10: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500789 sk_sp<SkImage> image = make_fuzz_image(fuzz);
Hal Canarye03c3e52017-03-09 11:33:35 -0500790 SkRect srcRect, dstRect;
791 SkFilterQuality filterQuality;
792 fuzz->next(&srcRect, &dstRect, &filterQuality);
793 return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
794 }
795 case 11:
796 return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
797 case 12: {
798 SkRect srcRect;
799 SkScalar inset;
800 bool useCropRect;
801 SkImageFilter::CropRect cropRect;
802 fuzz->next(&srcRect, &inset, &useCropRect);
803 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400804 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500805 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500806 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500807 return SkMagnifierImageFilter::Make(srcRect, inset, std::move(input),
808 useCropRect ? &cropRect : nullptr);
809 }
810 case 13: {
811 constexpr int kMaxKernelSize = 5;
812 int32_t n, m;
813 fuzz->nextRange(&n, 1, kMaxKernelSize);
814 fuzz->nextRange(&m, 1, kMaxKernelSize);
815 SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
816 fuzz->nextN(kernel, n * m);
817 int32_t offsetX, offsetY;
818 fuzz->nextRange(&offsetX, 0, n - 1);
819 fuzz->nextRange(&offsetY, 0, m - 1);
820 SkScalar gain, bias;
821 bool convolveAlpha, useCropRect;
822 fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
823 SkMatrixConvolutionImageFilter::TileMode tileMode;
Hal Canaryf7005202017-03-10 08:48:28 -0500824 fuzz_enum_range(fuzz, &tileMode, 0, 2);
Hal Canarye03c3e52017-03-09 11:33:35 -0500825 SkImageFilter::CropRect cropRect;
826 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400827 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500828 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500829 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500830 return SkMatrixConvolutionImageFilter::Make(
831 SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
832 convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
833 }
834 case 14: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500835 sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
836 sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500837 bool useCropRect;
838 fuzz->next(&useCropRect);
839 SkImageFilter::CropRect cropRect;
840 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400841 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500842 }
Mike Reed0bdaf052017-06-18 23:35:57 -0400843 return SkMergeImageFilter::Make(std::move(first), std::move(second),
844 useCropRect ? &cropRect : nullptr);
845 }
846 case 15: {
847 constexpr int kMaxCount = 4;
848 sk_sp<SkImageFilter> ifs[kMaxCount];
849 int count;
850 fuzz->nextRange(&count, 1, kMaxCount);
851 for (int i = 0; i < count; ++i) {
852 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
853 }
854 bool useCropRect;
855 fuzz->next(&useCropRect);
856 SkImageFilter::CropRect cropRect;
857 if (useCropRect) {
858 fuzz->next(&cropRect);
859 }
860 return SkMergeImageFilter::Make(ifs, count, useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500861 }
862 case 16: {
863 int rx, ry;
864 fuzz->next(&rx, &ry);
865 bool useCropRect;
866 fuzz->next(&useCropRect);
867 SkImageFilter::CropRect cropRect;
868 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400869 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500870 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500871 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500872 return SkDilateImageFilter::Make(rx, ry, std::move(input),
873 useCropRect ? &cropRect : nullptr);
874 }
875 case 17: {
876 int rx, ry;
877 fuzz->next(&rx, &ry);
878 bool useCropRect;
879 fuzz->next(&useCropRect);
880 SkImageFilter::CropRect cropRect;
881 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400882 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500883 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500884 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500885 return SkErodeImageFilter::Make(rx, ry, std::move(input),
886 useCropRect ? &cropRect : nullptr);
887 }
888 case 18: {
889 SkScalar dx, dy;
890 fuzz->next(&dx, &dy);
891 bool useCropRect;
892 fuzz->next(&useCropRect);
893 SkImageFilter::CropRect cropRect;
894 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400895 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500896 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500897 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500898 return SkOffsetImageFilter::Make(dx, dy, std::move(input),
899 useCropRect ? &cropRect : nullptr);
900 }
901 case 19: {
902 SkPaint paint;
Hal Canary1e0138b2017-03-10 13:56:08 -0500903 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500904 bool useCropRect;
905 fuzz->next(&useCropRect);
906 SkImageFilter::CropRect cropRect;
907 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400908 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500909 }
910 return SkPaintImageFilter::Make(paint, useCropRect ? &cropRect : nullptr);
911 }
912 case 20: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500913 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500914 return SkPictureImageFilter::Make(std::move(picture));
915 }
916 case 21: {
917 SkRect cropRect;
918 fuzz->next(&cropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500919 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500920 return SkPictureImageFilter::Make(std::move(picture), cropRect);
921 }
922 case 22: {
923 SkRect cropRect;
924 SkFilterQuality filterQuality;
925 fuzz->next(&cropRect, &filterQuality);
Hal Canary1e0138b2017-03-10 13:56:08 -0500926 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500927 return SkPictureImageFilter::MakeForLocalSpace(std::move(picture), cropRect,
928 filterQuality);
929 }
930 case 23: {
931 SkRect src, dst;
932 fuzz->next(&src, &dst);
Hal Canary1e0138b2017-03-10 13:56:08 -0500933 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500934 return SkTileImageFilter::Make(src, dst, std::move(input));
935 }
936 case 24: {
937 SkBlendMode blendMode;
938 bool useCropRect;
939 fuzz->next(&useCropRect, &blendMode);
940 SkImageFilter::CropRect cropRect;
941 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400942 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500943 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500944 sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
945 sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500946 return SkXfermodeImageFilter::Make(blendMode, std::move(bg), std::move(fg),
947 useCropRect ? &cropRect : nullptr);
948 }
949 default:
950 SkASSERT(false);
951 return nullptr;
952 }
953}
Hal Canary24ac42b2017-02-14 13:35:14 -0500954
Hal Canary1e0138b2017-03-10 13:56:08 -0500955static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500956 int w, h;
957 fuzz->nextRange(&w, 1, 1024);
958 fuzz->nextRange(&h, 1, 1024);
959 SkAutoTMalloc<SkPMColor> data(w * h);
960 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
961 int n = w * h;
962 for (int i = 0; i < n; ++i) {
963 SkColor c;
964 fuzz->next(&c);
965 data[i] = SkPreMultiplyColor(c);
966 }
967 (void)data.release();
Hal Canaryb69c4b82017-03-08 11:02:40 -0500968 return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
969 nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500970}
971
Hal Canary1e0138b2017-03-10 13:56:08 -0500972static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500973 SkBitmap bitmap;
974 int w, h;
975 fuzz->nextRange(&w, 1, 1024);
976 fuzz->nextRange(&h, 1, 1024);
977 bitmap.allocN32Pixels(w, h);
Hal Canary24ac42b2017-02-14 13:35:14 -0500978 for (int y = 0; y < h; ++y) {
979 for (int x = 0; x < w; ++x) {
980 SkColor c;
981 fuzz->next(&c);
982 *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
983 }
984 }
985 return bitmap;
986}
987
Hal Canary1e0138b2017-03-10 13:56:08 -0500988template <typename T, typename Min, typename Max>
989inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
990 T value;
991 fuzz_enum_range(fuzz, &value, minv, maxv);
992 return value;
993}
994
995static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500996 if (!fuzz || !paint || depth <= 0) {
997 return;
998 }
999
Hal Canary1e0138b2017-03-10 13:56:08 -05001000 paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
1001 paint->setDither( make_fuzz_t<bool>(fuzz));
1002 paint->setColor( make_fuzz_t<SkColor>(fuzz));
1003 paint->setBlendMode( make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
1004 paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
1005 paint->setStyle( make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
1006 paint->setShader( make_fuzz_shader(fuzz, depth - 1));
1007 paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
1008 paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
1009 paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
1010 paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
Hal Canary24ac42b2017-02-14 13:35:14 -05001011
1012 if (paint->getStyle() != SkPaint::kFill_Style) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001013 paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
1014 paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
1015 paint->setStrokeCap( make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
1016 paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
Hal Canary24ac42b2017-02-14 13:35:14 -05001017 }
1018}
1019
Hal Canary1e0138b2017-03-10 13:56:08 -05001020static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
1021 paint->setTypeface( make_fuzz_typeface(fuzz));
1022 paint->setTextSize( make_fuzz_t<SkScalar>(fuzz));
1023 paint->setTextScaleX( make_fuzz_t<SkScalar>(fuzz));
1024 paint->setTextSkewX( make_fuzz_t<SkScalar>(fuzz));
1025 paint->setLinearText( make_fuzz_t<bool>(fuzz));
1026 paint->setSubpixelText( make_fuzz_t<bool>(fuzz));
1027 paint->setLCDRenderText( make_fuzz_t<bool>(fuzz));
1028 paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
1029 paint->setAutohinted( make_fuzz_t<bool>(fuzz));
1030 paint->setVerticalText( make_fuzz_t<bool>(fuzz));
1031 paint->setFakeBoldText( make_fuzz_t<bool>(fuzz));
1032 paint->setDevKernText( make_fuzz_t<bool>(fuzz));
1033 paint->setHinting( make_fuzz_t_range<SkPaint::Hinting>(fuzz, 0,
1034 SkPaint::kFull_Hinting));
1035 paint->setTextAlign( make_fuzz_t_range<SkPaint::Align>(fuzz, 0, 2));
Hal Canary5395c592017-03-08 16:52:18 -05001036}
1037
1038static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001039 paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
Hal Canary24ac42b2017-02-14 13:35:14 -05001040}
1041
Hal Canary5395c592017-03-08 16:52:18 -05001042constexpr int kMaxGlyphCount = 30;
1043
Hal Canary1e0138b2017-03-10 13:56:08 -05001044static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
Hal Canary671e4422017-02-27 13:36:38 -05001045 SkTDArray<uint8_t> array;
1046 if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -05001047 int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
1048 : SkTypeface::MakeDefault()->countGlyphs();
Hal Canary671e4422017-02-27 13:36:38 -05001049 int glyphCount;
Hal Canary5395c592017-03-08 16:52:18 -05001050 fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
Hal Canary671e4422017-02-27 13:36:38 -05001051 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
1052 for (int i = 0; i < glyphCount; ++i) {
1053 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
1054 }
1055 return array;
1056 }
1057 static const SkUnichar ranges[][2] = {
1058 {0x0020, 0x007F},
1059 {0x00A1, 0x0250},
1060 {0x0400, 0x0500},
1061 };
1062 int32_t count = 0;
Hal Canaryb69c4b82017-03-08 11:02:40 -05001063 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -05001064 count += (ranges[i][1] - ranges[i][0]);
1065 }
Hal Canary5395c592017-03-08 16:52:18 -05001066 constexpr int kMaxLength = kMaxGlyphCount;
Hal Canary671e4422017-02-27 13:36:38 -05001067 SkUnichar buffer[kMaxLength];
1068 int length;
1069 fuzz->nextRange(&length, 1, kMaxLength);
1070 for (int j = 0; j < length; ++j) {
1071 int32_t value;
1072 fuzz->nextRange(&value, 0, count - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001073 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -05001074 if (value + ranges[i][0] < ranges[i][1]) {
1075 buffer[j] = value + ranges[i][0];
1076 break;
1077 } else {
1078 value -= (ranges[i][1] - ranges[i][0]);
1079 }
1080 }
1081 }
1082 switch (paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -05001083 case SkPaint::kUTF8_TextEncoding: {
1084 size_t utf8len = 0;
1085 for (int j = 0; j < length; ++j) {
1086 utf8len += SkUTF8_FromUnichar(buffer[j], nullptr);
Hal Canary671e4422017-02-27 13:36:38 -05001087 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001088 char* ptr = (char*)array.append(utf8len);
1089 for (int j = 0; j < length; ++j) {
1090 ptr += SkUTF8_FromUnichar(buffer[j], ptr);
Hal Canary671e4422017-02-27 13:36:38 -05001091 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001092 } break;
1093 case SkPaint::kUTF16_TextEncoding: {
1094 size_t utf16len = 0;
1095 for (int j = 0; j < length; ++j) {
1096 utf16len += SkUTF16_FromUnichar(buffer[j]);
1097 }
1098 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
1099 for (int j = 0; j < length; ++j) {
1100 ptr += SkUTF16_FromUnichar(buffer[j], ptr);
1101 }
1102 } break;
Hal Canary671e4422017-02-27 13:36:38 -05001103 case SkPaint::kUTF32_TextEncoding:
1104 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
Hal Canaryc1a70e22017-03-01 15:40:46 -05001105 break;
Hal Canary671e4422017-02-27 13:36:38 -05001106 default:
Hal Canaryb69c4b82017-03-08 11:02:40 -05001107 SkASSERT(false);
Hal Canary671e4422017-02-27 13:36:38 -05001108 }
1109 return array;
1110}
1111
Hal Canary5395c592017-03-08 16:52:18 -05001112static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
1113 SkTextBlobBuilder textBlobBuilder;
1114 int8_t runCount;
1115 fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
1116 while (runCount-- > 0) {
1117 SkPaint paint;
1118 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary1e0138b2017-03-10 13:56:08 -05001119 paint.setAntiAlias(make_fuzz_t<bool>(fuzz));
Hal Canary5395c592017-03-08 16:52:18 -05001120 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1121 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1122 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1123 SkASSERT(glyphCount <= kMaxGlyphCount);
1124 SkScalar x, y;
1125 const SkTextBlobBuilder::RunBuffer* buffer;
1126 uint8_t runType;
1127 fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
1128 switch (runType) {
1129 case 0:
1130 fuzz->next(&x, &y);
1131 // TODO: Test other variations of this.
1132 buffer = &textBlobBuilder.allocRun(paint, glyphCount, x, y);
1133 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1134 break;
1135 case 1:
1136 fuzz->next(&y);
1137 // TODO: Test other variations of this.
1138 buffer = &textBlobBuilder.allocRunPosH(paint, glyphCount, y);
1139 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1140 fuzz->nextN(buffer->pos, glyphCount);
1141 break;
1142 case 2:
1143 // TODO: Test other variations of this.
1144 buffer = &textBlobBuilder.allocRunPos(paint, glyphCount);
1145 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1146 fuzz->nextN(buffer->pos, glyphCount * 2);
1147 break;
1148 default:
1149 SkASSERT(false);
1150 }
1151 }
1152 return textBlobBuilder.make();
1153}
1154
Hal Canary1e0138b2017-03-10 13:56:08 -05001155static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001156 if (!fuzz || !canvas || depth <= 0) {
1157 return;
1158 }
1159 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1160 unsigned N;
1161 fuzz->nextRange(&N, 0, 2000);
1162 for (unsigned i = 0; i < N; ++i) {
1163 if (fuzz->exhausted()) {
1164 return;
1165 }
1166 SkPaint paint;
1167 SkMatrix matrix;
1168 unsigned drawCommand;
Hal Canary5af600e2017-03-09 14:10:36 -05001169 fuzz->nextRange(&drawCommand, 0, 53);
Hal Canary24ac42b2017-02-14 13:35:14 -05001170 switch (drawCommand) {
1171 case 0:
1172 canvas->flush();
1173 break;
1174 case 1:
1175 canvas->save();
1176 break;
1177 case 2: {
1178 SkRect bounds;
1179 fuzz->next(&bounds);
Hal Canary1e0138b2017-03-10 13:56:08 -05001180 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001181 canvas->saveLayer(&bounds, &paint);
1182 break;
1183 }
1184 case 3: {
1185 SkRect bounds;
1186 fuzz->next(&bounds);
1187 canvas->saveLayer(&bounds, nullptr);
1188 break;
1189 }
1190 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -05001191 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001192 canvas->saveLayer(nullptr, &paint);
1193 break;
1194 case 5:
1195 canvas->saveLayer(nullptr, nullptr);
1196 break;
1197 case 6: {
1198 uint8_t alpha;
1199 fuzz->next(&alpha);
1200 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1201 break;
1202 }
1203 case 7: {
1204 SkRect bounds;
1205 uint8_t alpha;
1206 fuzz->next(&bounds, &alpha);
1207 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1208 break;
1209 }
1210 case 8: {
1211 SkCanvas::SaveLayerRec saveLayerRec;
1212 SkRect bounds;
Hal Canary1e0138b2017-03-10 13:56:08 -05001213 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001214 fuzz->next(&bounds);
1215 saveLayerRec.fBounds = &bounds;
1216 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001217 if (make_fuzz_t<bool>(fuzz)) {
1218 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001219 saveLayerRec.fPaint = &paint;
1220 }
1221 sk_sp<SkImageFilter> imageFilter;
Hal Canary1e0138b2017-03-10 13:56:08 -05001222 if (make_fuzz_t<bool>(fuzz)) {
1223 imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001224 saveLayerRec.fBackdrop = imageFilter.get();
1225 }
Hal Canary5395c592017-03-08 16:52:18 -05001226 // _DumpCanvas can't handle this.
Hal Canary1e0138b2017-03-10 13:56:08 -05001227 // if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -05001228 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kIsOpaque_SaveLayerFlag;
1229 // }
Hal Canary1e0138b2017-03-10 13:56:08 -05001230 // if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -05001231 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1232 // }
1233
Hal Canary24ac42b2017-02-14 13:35:14 -05001234 canvas->saveLayer(saveLayerRec);
1235 break;
1236 }
1237 case 9:
1238 canvas->restore();
1239 break;
1240 case 10: {
1241 int saveCount;
1242 fuzz->next(&saveCount);
1243 canvas->restoreToCount(saveCount);
1244 break;
1245 }
1246 case 11: {
1247 SkScalar x, y;
1248 fuzz->next(&x, &y);
1249 canvas->translate(x, y);
1250 break;
1251 }
1252 case 12: {
1253 SkScalar x, y;
1254 fuzz->next(&x, &y);
1255 canvas->scale(x, y);
1256 break;
1257 }
1258 case 13: {
1259 SkScalar v;
1260 fuzz->next(&v);
1261 canvas->rotate(v);
1262 break;
1263 }
1264 case 14: {
1265 SkScalar x, y, v;
1266 fuzz->next(&x, &y, &v);
1267 canvas->rotate(v, x, y);
1268 break;
1269 }
1270 case 15: {
1271 SkScalar x, y;
1272 fuzz->next(&x, &y);
1273 canvas->skew(x, y);
1274 break;
1275 }
1276 case 16: {
1277 SkMatrix mat;
1278 fuzz->next(&mat);
1279 canvas->concat(mat);
1280 break;
1281 }
1282 case 17: {
1283 SkMatrix mat;
1284 fuzz->next(&mat);
1285 canvas->setMatrix(mat);
1286 break;
1287 }
1288 case 18:
1289 canvas->resetMatrix();
1290 break;
1291 case 19: {
1292 SkRect r;
1293 int op;
1294 bool doAntiAlias;
1295 fuzz->next(&r, &doAntiAlias);
1296 fuzz->nextRange(&op, 0, 1);
1297 r.sort();
1298 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1299 break;
1300 }
1301 case 20: {
1302 SkRRect rr;
1303 int op;
1304 bool doAntiAlias;
1305 fuzz->next(&rr);
1306 fuzz->next(&doAntiAlias);
1307 fuzz->nextRange(&op, 0, 1);
1308 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1309 break;
1310 }
1311 case 21: {
1312 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001313 fuzz_path(fuzz, &path, 30);
Hal Canary24ac42b2017-02-14 13:35:14 -05001314 int op;
1315 bool doAntiAlias;
1316 fuzz->next(&doAntiAlias);
1317 fuzz->nextRange(&op, 0, 1);
1318 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1319 break;
1320 }
1321 case 22: {
1322 SkRegion region;
Hal Canary24ac42b2017-02-14 13:35:14 -05001323 int op;
Hal Canarye03c3e52017-03-09 11:33:35 -05001324 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001325 fuzz->nextRange(&op, 0, 1);
1326 canvas->clipRegion(region, (SkClipOp)op);
1327 break;
1328 }
1329 case 23:
Hal Canary1e0138b2017-03-10 13:56:08 -05001330 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001331 canvas->drawPaint(paint);
1332 break;
1333 case 24: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001334 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001335 uint8_t pointMode;
1336 fuzz->nextRange(&pointMode, 0, 3);
1337 size_t count;
1338 constexpr int kMaxCount = 30;
1339 fuzz->nextRange(&count, 0, kMaxCount);
1340 SkPoint pts[kMaxCount];
1341 fuzz->nextN(pts, count);
1342 canvas->drawPoints((SkCanvas::PointMode)pointMode, count, pts, paint);
1343 break;
1344 }
1345 case 25: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001346 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001347 SkRect r;
1348 fuzz->next(&r);
1349 canvas->drawRect(r, paint);
1350 break;
1351 }
1352 case 26: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001353 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001354 SkRegion region;
Hal Canarye03c3e52017-03-09 11:33:35 -05001355 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001356 canvas->drawRegion(region, paint);
1357 break;
1358 }
1359 case 27: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001360 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001361 SkRect r;
1362 fuzz->next(&r);
1363 canvas->drawOval(r, paint);
1364 break;
1365 }
1366 case 29: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001367 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001368 SkRRect rr;
1369 fuzz->next(&rr);
1370 canvas->drawRRect(rr, paint);
1371 break;
1372 }
1373 case 30: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001374 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001375 SkRRect orr, irr;
1376 fuzz->next(&orr);
1377 fuzz->next(&irr);
Hal Canary27bece82017-03-07 16:23:20 -05001378 if (orr.getBounds().contains(irr.getBounds())) {
1379 canvas->drawDRRect(orr, irr, paint);
1380 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001381 break;
1382 }
1383 case 31: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001384 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001385 SkRect r;
1386 SkScalar start, sweep;
1387 bool useCenter;
1388 fuzz->next(&r, &start, &sweep, &useCenter);
1389 canvas->drawArc(r, start, sweep, useCenter, paint);
1390 break;
1391 }
1392 case 32: {
1393 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001394 fuzz_path(fuzz, &path, 60);
Hal Canary24ac42b2017-02-14 13:35:14 -05001395 canvas->drawPath(path, paint);
1396 break;
1397 }
1398 case 33: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001399 sk_sp<SkImage> img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001400 SkScalar left, top;
1401 bool usePaint;
1402 fuzz->next(&left, &top, &usePaint);
1403 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001404 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001405 }
1406 canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
1407 break;
1408 }
1409 case 34: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001410 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001411 SkRect src, dst;
1412 bool usePaint;
1413 fuzz->next(&src, &dst, &usePaint);
1414 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001415 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001416 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001417 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001418 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1419 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001420 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1421 break;
1422 }
1423 case 35: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001424 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001425 SkIRect src;
1426 SkRect dst;
1427 bool usePaint;
1428 fuzz->next(&src, &dst, &usePaint);
1429 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001430 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001431 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001432 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001433 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1434 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001435 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1436 break;
1437 }
1438 case 36: {
1439 bool usePaint;
Hal Canary1e0138b2017-03-10 13:56:08 -05001440 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001441 SkRect dst;
1442 fuzz->next(&dst, &usePaint);
1443 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001444 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001445 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001446 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001447 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1448 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001449 canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr, constraint);
1450 break;
1451 }
1452 case 37: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001453 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001454 SkIRect center;
1455 SkRect dst;
1456 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001457 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001458 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001459 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001460 }
Hal Canary0361d492017-03-15 12:58:15 -04001461 if (make_fuzz_t<bool>(fuzz)) {
1462 fuzz->next(&center);
1463 } else { // Make valid center, see SkLatticeIter::Valid().
1464 fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1465 fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1466 fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1467 fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1468 }
1469 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001470 canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
1471 break;
1472 }
1473 case 38: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001474 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001475 SkScalar left, top;
1476 bool usePaint;
1477 fuzz->next(&left, &top, &usePaint);
1478 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001479 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001480 }
1481 canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
1482 break;
1483 }
1484 case 39: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001485 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001486 SkRect src, dst;
1487 bool usePaint;
1488 fuzz->next(&src, &dst, &usePaint);
1489 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001490 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001491 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001492 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001493 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1494 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001495 canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
1496 break;
1497 }
1498 case 40: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001499 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001500 SkIRect src;
1501 SkRect dst;
1502 bool usePaint;
1503 fuzz->next(&src, &dst, &usePaint);
1504 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001505 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001506 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001507 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001508 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1509 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001510 canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1511 break;
1512 }
1513 case 41: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001514 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001515 SkRect dst;
1516 bool usePaint;
1517 fuzz->next(&dst, &usePaint);
1518 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001519 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001520 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001521 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001522 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1523 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001524 canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1525 break;
1526 }
1527 case 42: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001528 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001529 SkIRect center;
1530 SkRect dst;
1531 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001532 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001533 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001534 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001535 }
Hal Canary0361d492017-03-15 12:58:15 -04001536 if (make_fuzz_t<bool>(fuzz)) {
1537 fuzz->next(&center);
1538 } else { // Make valid center, see SkLatticeIter::Valid().
1539 fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
1540 fuzz->nextRange(&center.fTop, 0, img.height() - 1);
1541 fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
1542 fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
1543 }
1544 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001545 canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1546 break;
1547 }
1548 case 43: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001549 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001550 bool usePaint;
1551 SkRect dst;
1552 fuzz->next(&usePaint, &dst);
1553 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001554 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001555 }
1556 constexpr int kMax = 6;
1557 int xDivs[kMax], yDivs[kMax];
1558 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr};
1559 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1560 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1561 fuzz->nextN(xDivs, lattice.fXCount);
1562 fuzz->nextN(yDivs, lattice.fYCount);
1563 canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1564 break;
1565 }
1566 case 44: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001567 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001568 bool usePaint;
1569 SkRect dst;
1570 fuzz->next(&usePaint, &dst);
1571 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001572 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001573 }
1574 constexpr int kMax = 6;
1575 int xDivs[kMax], yDivs[kMax];
1576 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr};
1577 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1578 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1579 fuzz->nextN(xDivs, lattice.fXCount);
1580 fuzz->nextN(yDivs, lattice.fYCount);
1581 canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1582 break;
1583 }
1584 case 45: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001585 fuzz_paint(fuzz, &paint, depth - 1);
1586 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001587 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001588 SkScalar x, y;
1589 fuzz->next(&x, &y);
Hal Canary5395c592017-03-08 16:52:18 -05001590 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001591 canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001592 break;
1593 }
1594 case 46: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001595 fuzz_paint(fuzz, &paint, depth - 1);
1596 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001597 fuzz_paint_text_encoding(fuzz, &paint);
1598 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001599 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001600 if (glyphCount < 1) {
1601 break;
1602 }
1603 SkAutoTMalloc<SkPoint> pos(glyphCount);
1604 SkAutoTMalloc<SkScalar> widths(glyphCount);
Hal Canary671e4422017-02-27 13:36:38 -05001605 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001606 pos[0] = {0, 0};
1607 for (int i = 1; i < glyphCount; ++i) {
1608 float y;
Hal Canaryb69c4b82017-03-08 11:02:40 -05001609 fuzz->nextRange(&y, -0.5f * paint.getTextSize(), 0.5f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001610 pos[i] = {pos[i - 1].x() + widths[i - 1], y};
1611 }
Hal Canary671e4422017-02-27 13:36:38 -05001612 canvas->drawPosText(text.begin(), SkToSizeT(text.count()), pos.get(), paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001613 break;
1614 }
1615 case 47: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001616 fuzz_paint(fuzz, &paint, depth - 1);
1617 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001618 fuzz_paint_text_encoding(fuzz, &paint);
1619 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001620 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001621 SkAutoTMalloc<SkScalar> widths(glyphCount);
1622 if (glyphCount < 1) {
1623 break;
1624 }
Hal Canary671e4422017-02-27 13:36:38 -05001625 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001626 SkScalar x = widths[0];
1627 for (int i = 0; i < glyphCount; ++i) {
1628 SkTSwap(x, widths[i]);
1629 x += widths[i];
1630 SkScalar offset;
1631 fuzz->nextRange(&offset, -0.125f * paint.getTextSize(),
Hal Canaryb69c4b82017-03-08 11:02:40 -05001632 0.125f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001633 widths[i] += offset;
1634 }
1635 SkScalar y;
1636 fuzz->next(&y);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001637 canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001638 break;
1639 }
1640 case 48: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001641 fuzz_paint(fuzz, &paint, depth - 1);
1642 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001643 fuzz_paint_text_encoding(fuzz, &paint);
1644 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001645 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001646 fuzz_path(fuzz, &path, 20);
Hal Canary24ac42b2017-02-14 13:35:14 -05001647 SkScalar hOffset, vOffset;
1648 fuzz->next(&hOffset, &vOffset);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001649 canvas->drawTextOnPathHV(text.begin(), SkToSizeT(text.count()), path, hOffset,
1650 vOffset, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001651 break;
1652 }
1653 case 49: {
1654 SkMatrix matrix;
Hal Canary1e0138b2017-03-10 13:56:08 -05001655 bool useMatrix = make_fuzz_t<bool>(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001656 if (useMatrix) {
1657 fuzz->next(&matrix);
1658 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001659 fuzz_paint(fuzz, &paint, depth - 1);
1660 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001661 fuzz_paint_text_encoding(fuzz, &paint);
1662 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001663 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001664 fuzz_path(fuzz, &path, 20);
Hal Canary671e4422017-02-27 13:36:38 -05001665 canvas->drawTextOnPath(text.begin(), SkToSizeT(text.count()), path,
Hal Canary24ac42b2017-02-14 13:35:14 -05001666 useMatrix ? &matrix : nullptr, paint);
1667 break;
1668 }
1669 case 50: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001670 fuzz_paint(fuzz, &paint, depth - 1);
1671 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001672 fuzz_paint_text_encoding(fuzz, &paint);
1673 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1674 SkRSXform rSXform[kMaxGlyphCount];
1675 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1676 SkASSERT(glyphCount <= kMaxGlyphCount);
1677 fuzz->nextN(rSXform, glyphCount);
1678 SkRect cullRect;
1679 bool useCullRect;
1680 fuzz->next(&useCullRect);
1681 if (useCullRect) {
1682 fuzz->next(&cullRect);
1683 }
1684 canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
1685 useCullRect ? &cullRect : nullptr, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001686 break;
1687 }
1688 case 51: {
Hal Canary5395c592017-03-08 16:52:18 -05001689 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
Hal Canary1e0138b2017-03-10 13:56:08 -05001690 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -05001691 SkScalar x, y;
1692 fuzz->next(&x, &y);
1693 canvas->drawTextBlob(blob, x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001694 break;
1695 }
1696 case 52: {
1697 bool usePaint, useMatrix;
1698 fuzz->next(&usePaint, &useMatrix);
1699 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001700 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001701 }
1702 if (useMatrix) {
1703 fuzz->next(&matrix);
1704 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001705 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001706 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1707 usePaint ? &paint : nullptr);
1708 break;
1709 }
1710 case 53: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001711 fuzz_paint(fuzz, &paint, depth - 1);
Mike Reed887cdf12017-04-03 11:11:09 -04001712 SkVertices::VertexMode vertexMode;
Hal Canary5af600e2017-03-09 14:10:36 -05001713 SkBlendMode blendMode;
Mike Reed887cdf12017-04-03 11:11:09 -04001714 fuzz_enum_range(fuzz, &vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
Hal Canary5af600e2017-03-09 14:10:36 -05001715 fuzz->next(&blendMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001716 constexpr int kMaxCount = 100;
1717 int vertexCount;
1718 SkPoint vertices[kMaxCount];
1719 SkPoint texs[kMaxCount];
1720 SkColor colors[kMaxCount];
Hal Canary24ac42b2017-02-14 13:35:14 -05001721 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1722 fuzz->nextN(vertices, vertexCount);
1723 bool useTexs, useColors;
1724 fuzz->next(&useTexs, &useColors);
1725 if (useTexs) {
1726 fuzz->nextN(texs, vertexCount);
1727 }
1728 if (useColors) {
1729 fuzz->nextN(colors, vertexCount);
1730 }
1731 int indexCount = 0;
Hal Canary68b9b572017-03-02 15:27:23 -05001732 uint16_t indices[kMaxCount * 2];
Hal Canary1e0138b2017-03-10 13:56:08 -05001733 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary68b9b572017-03-02 15:27:23 -05001734 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1735 for (int i = 0; i < indexCount; ++i) {
1736 fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1737 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001738 }
Mike Reed887cdf12017-04-03 11:11:09 -04001739 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1740 useTexs ? texs : nullptr,
1741 useColors ? colors : nullptr,
1742 indexCount, indices),
1743 blendMode, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001744 break;
1745 }
1746 default:
1747 break;
1748 }
1749 }
1750}
1751
Hal Canary1e0138b2017-03-10 13:56:08 -05001752static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001753 SkScalar w, h;
1754 fuzz->next(&w, &h);
1755 SkPictureRecorder pictureRecorder;
1756 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1757 return pictureRecorder.finishRecordingAsPicture();
1758}
1759
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001760DEF_FUZZ(NullCanvas, fuzz) {
1761 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001762}
1763
Hal Canary44801ca2017-03-15 11:39:06 -04001764// 8.5x11 letter paper at 72ppi.
1765constexpr SkISize kCanvasSize = {612, 792};
1766
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001767DEF_FUZZ(RasterN32Canvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001768 auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001769 SkASSERT(surface && surface->getCanvas());
1770 fuzz_canvas(fuzz, surface->getCanvas());
1771}
1772
Hal Canary44801ca2017-03-15 11:39:06 -04001773#if SK_SUPPORT_GPU
Hal Canary5aa91582017-03-21 11:11:44 -07001774static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
1775 SkASSERT(context);
1776 auto surface = SkSurface::MakeRenderTarget(
1777 context,
1778 SkBudgeted::kNo,
1779 SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1780 SkASSERT(surface && surface->getCanvas());
1781 fuzz_canvas(fuzz, surface->getCanvas());
1782}
1783
Hal Canary44801ca2017-03-15 11:39:06 -04001784DEF_FUZZ(NativeGLCanvas, fuzz) {
Brian Salomon6405e712017-03-20 08:54:16 -04001785 GrContext* context = sk_gpu_test::GrContextFactory().get(
1786 sk_gpu_test::GrContextFactory::kGL_ContextType);
1787 if (!context) {
1788 context = sk_gpu_test::GrContextFactory().get(
1789 sk_gpu_test::GrContextFactory::kGLES_ContextType);
1790 }
Hal Canary5aa91582017-03-21 11:11:44 -07001791 fuzz_ganesh(fuzz, context);
1792}
1793
1794DEF_FUZZ(NullGLCanvas, fuzz) {
1795 fuzz_ganesh(fuzz, sk_gpu_test::GrContextFactory().get(
1796 sk_gpu_test::GrContextFactory::kNullGL_ContextType));
1797}
1798
1799DEF_FUZZ(DebugGLCanvas, fuzz) {
1800 fuzz_ganesh(fuzz, sk_gpu_test::GrContextFactory().get(
1801 sk_gpu_test::GrContextFactory::kDebugGL_ContextType));
Hal Canary44801ca2017-03-15 11:39:06 -04001802}
1803#endif
1804
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001805DEF_FUZZ(PDFCanvas, fuzz) {
Hal Canaryfe759302017-08-26 17:06:42 -04001806 SkNullWStream stream;
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001807 auto doc = SkDocument::MakePDF(&stream);
Hal Canary44801ca2017-03-15 11:39:06 -04001808 fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1809 SkIntToScalar(kCanvasSize.height())));
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001810}
1811
1812// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1813DEF_FUZZ(_DumpCanvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001814 SkDebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001815 fuzz_canvas(fuzz, &debugCanvas);
1816 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1817 UrlDataManager dataManager(SkString("data"));
1818 Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
1819 Json::StyledStreamWriter(" ").write(std::cout, json);
1820}