blob: 4b52ab0e8135b38f35dae33ab6272e0914e6a8dc [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"
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 Canaryc640d0d2018-06-13 09:59:02 -040019#include "SkOSFile.h"
Hal Canary23564b92018-09-07 14:33:14 -040020#include "SkPDFDocument.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 Canary1e0138b2017-03-10 13:56:08 -050099static sk_sp<SkImage> make_fuzz_image(Fuzz*);
Hal Canary671e4422017-02-27 13:36:38 -0500100
Hal Canary1e0138b2017-03-10 13:56:08 -0500101static SkBitmap make_fuzz_bitmap(Fuzz*);
Hal Canary24ac42b2017-02-14 13:35:14 -0500102
Hal Canary1e0138b2017-03-10 13:56:08 -0500103static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
Hal Canary671e4422017-02-27 13:36:38 -0500104
Hal Canary1e0138b2017-03-10 13:56:08 -0500105static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
Hal Canary27bece82017-03-07 16:23:20 -0500106 if (depth <= 0) {
107 return nullptr;
108 }
109 int colorFilterType;
110 fuzz->nextRange(&colorFilterType, 0, 8);
111 switch (colorFilterType) {
112 case 0:
113 return nullptr;
114 case 1: {
115 SkColor color;
116 SkBlendMode mode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400117 fuzz->next(&color);
118 fuzz->nextEnum(&mode, 0, SkBlendMode::kLastMode);
Hal Canary27bece82017-03-07 16:23:20 -0500119 return SkColorFilter::MakeModeFilter(color, mode);
120 }
121 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500122 sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500123 if (!outer) {
124 return nullptr;
125 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500126 sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500127 // makeComposed should be able to handle nullptr.
Mike Reed19d7bd62018-02-19 14:10:57 -0500128 return outer->makeComposed(std::move(inner));
Hal Canary27bece82017-03-07 16:23:20 -0500129 }
130 case 3: {
131 SkScalar array[20];
132 fuzz->nextN(array, SK_ARRAY_COUNT(array));
133 return SkColorFilter::MakeMatrixFilterRowMajor255(array);
134 }
135 case 4: {
136 SkColor mul, add;
137 fuzz->next(&mul, &add);
138 return SkColorMatrixFilter::MakeLightingFilter(mul, add);
139 }
140 case 5: {
141 bool grayscale;
142 int invertStyle;
143 float contrast;
144 fuzz->next(&grayscale);
145 fuzz->nextRange(&invertStyle, 0, 2);
146 fuzz->nextRange(&contrast, -1.0f, 1.0f);
147 return SkHighContrastFilter::Make(SkHighContrastConfig(
148 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
149 }
150 case 6:
151 return SkLumaColorFilter::Make();
152 case 7: {
153 uint8_t table[256];
154 fuzz->nextN(table, SK_ARRAY_COUNT(table));
155 return SkTableColorFilter::Make(table);
156 }
157 case 8: {
158 uint8_t tableA[256];
159 uint8_t tableR[256];
160 uint8_t tableG[256];
161 uint8_t tableB[256];
162 fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
163 fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
164 fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
165 fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
166 return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
167 }
Kevin Lubick54f20e02018-01-11 14:50:21 -0500168 default:
169 SkASSERT(false);
170 break;
Hal Canary27bece82017-03-07 16:23:20 -0500171 }
172 return nullptr;
173}
Hal Canary24ac42b2017-02-14 13:35:14 -0500174
Hal Canary1e0138b2017-03-10 13:56:08 -0500175static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500176 SkScalar totalPos = 0;
177 for (int i = 0; i < colorCount; ++i) {
178 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
179 totalPos += pos[i];
180 }
181 totalPos = 1.0f / totalPos;
182 for (int i = 0; i < colorCount; ++i) {
183 pos[i] *= totalPos;
184 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500185 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500186 pos[colorCount - 1] = 1.0f;
187}
188
Hal Canary1e0138b2017-03-10 13:56:08 -0500189static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500190 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
191 sk_sp<SkColorFilter> colorFilter(nullptr);
192 SkBitmap bitmap;
193 sk_sp<SkImage> img;
194 SkShader::TileMode tmX, tmY;
195 bool useMatrix;
196 SkColor color;
197 SkMatrix matrix;
198 SkBlendMode blendMode;
199 int shaderType;
200 if (depth <= 0) {
201 return nullptr;
202 }
Hal Canary671e4422017-02-27 13:36:38 -0500203 fuzz->nextRange(&shaderType, 0, 14);
Hal Canary24ac42b2017-02-14 13:35:14 -0500204 switch (shaderType) {
205 case 0:
206 return nullptr;
207 case 1:
208 return SkShader::MakeEmptyShader();
209 case 2:
210 fuzz->next(&color);
211 return SkShader::MakeColorShader(color);
212 case 3:
Hal Canary1e0138b2017-03-10 13:56:08 -0500213 img = make_fuzz_image(fuzz);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400214 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
215 fuzz->nextEnum(&tmY, 0, SkShader::TileMode::kLast_TileMode);
216 fuzz->next(&useMatrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500217 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400218 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500219 }
220 return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
221 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -0500222 bitmap = make_fuzz_bitmap(fuzz);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400223 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
224 fuzz->nextEnum(&tmY, 0, SkShader::TileMode::kLast_TileMode);
225 fuzz->next(&useMatrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500226 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400227 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500228 }
229 return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
230 case 5:
Hal Canary1e0138b2017-03-10 13:56:08 -0500231 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400232 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500233 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
234 case 6:
Hal Canary1e0138b2017-03-10 13:56:08 -0500235 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
236 colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500237 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
238 case 7:
Hal Canary1e0138b2017-03-10 13:56:08 -0500239 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
240 shader2 = make_fuzz_shader(fuzz, depth - 1);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400241 fuzz->nextEnum(&blendMode, 0, SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -0500242 return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500243 case 8: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500244 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500245 bool useTile;
246 SkRect tile;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400247 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
248 fuzz->nextEnum(&tmY, 0, SkShader::TileMode::kLast_TileMode);
249 fuzz->next(&useMatrix, &useTile);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500250 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400251 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary671e4422017-02-27 13:36:38 -0500252 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500253 if (useTile) {
254 fuzz->next(&tile);
255 }
256 return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
257 useMatrix ? &matrix : nullptr,
258 useTile ? &tile : nullptr);
259 }
Hal Canary671e4422017-02-27 13:36:38 -0500260 // EFFECTS:
Hal Canary24ac42b2017-02-14 13:35:14 -0500261 case 9:
Florin Malitabb3f5622017-05-31 14:20:12 +0000262 // Deprecated SkGaussianEdgeShader
263 return nullptr;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500264 case 10: {
265 constexpr int kMaxColors = 12;
266 SkPoint pts[2];
267 SkColor colors[kMaxColors];
268 SkScalar pos[kMaxColors];
269 int colorCount;
270 bool usePos;
271 fuzz->nextN(pts, 2);
272 fuzz->nextRange(&colorCount, 2, kMaxColors);
273 fuzz->nextN(colors, colorCount);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400274 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
275 fuzz->next(&useMatrix, &usePos);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500276 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400277 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500278 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500279 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500280 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500281 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500282 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
283 tmX, 0, useMatrix ? &matrix : nullptr);
284 }
285 case 11: {
286 constexpr int kMaxColors = 12;
287 SkPoint center;
288 SkScalar radius;
289 int colorCount;
290 bool usePos;
291 SkColor colors[kMaxColors];
292 SkScalar pos[kMaxColors];
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400293 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
294 fuzz->next(&useMatrix, &usePos, &center, &radius);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500295 fuzz->nextRange(&colorCount, 2, kMaxColors);
296 fuzz->nextN(colors, colorCount);
297 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400298 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500299 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500300 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500301 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500302 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500303 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
304 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
305 }
306 case 12: {
307 constexpr int kMaxColors = 12;
308 SkPoint start, end;
309 SkScalar startRadius, endRadius;
310 int colorCount;
311 bool usePos;
312 SkColor colors[kMaxColors];
313 SkScalar pos[kMaxColors];
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400314 fuzz->nextEnum(&tmX, 0, SkShader::TileMode::kLast_TileMode);
315 fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500316 fuzz->nextRange(&colorCount, 2, kMaxColors);
317 fuzz->nextN(colors, colorCount);
318 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400319 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500320 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500321 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500322 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500323 }
324 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
325 usePos ? pos : nullptr, colorCount, tmX, 0,
326 useMatrix ? &matrix : nullptr);
327 }
328 case 13: {
329 constexpr int kMaxColors = 12;
330 SkScalar cx, cy;
331 int colorCount;
332 bool usePos;
333 SkColor colors[kMaxColors];
334 SkScalar pos[kMaxColors];
335 fuzz->next(&cx, &cy, &useMatrix, &usePos);
336 fuzz->nextRange(&colorCount, 2, kMaxColors);
337 fuzz->nextN(colors, colorCount);
338 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400339 FuzzNiceMatrix(fuzz, &matrix);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500340 }
341 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500342 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500343 }
344 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
345 0, useMatrix ? &matrix : nullptr);
346 }
347 case 14: {
348 SkScalar baseFrequencyX, baseFrequencyY, seed;
349 int numOctaves;
350 SkISize tileSize;
351 bool useTileSize, turbulence;
352 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
353 if (useTileSize) {
354 fuzz->next(&tileSize);
355 }
356 fuzz->nextRange(&numOctaves, 2, 7);
357 if (turbulence) {
358 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
359 numOctaves, seed,
360 useTileSize ? &tileSize : nullptr);
361 } else {
362 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
363 numOctaves, seed,
364 useTileSize ? &tileSize : nullptr);
365 }
366 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500367 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -0500368 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -0500369 break;
370 }
Kevin Lubickedbeb8b2017-02-27 16:45:32 -0500371 return nullptr;
Hal Canary24ac42b2017-02-14 13:35:14 -0500372}
373
Hal Canary1e0138b2017-03-10 13:56:08 -0500374static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
Hal Canary5395c592017-03-08 16:52:18 -0500375 if (depth <= 0) {
376 return nullptr;
377 }
378 uint8_t pathEffectType;
Mike Reed40e7e652017-07-22 22:12:59 -0400379 fuzz->nextRange(&pathEffectType, 0, 8);
Hal Canary5395c592017-03-08 16:52:18 -0500380 switch (pathEffectType) {
381 case 0: {
382 return nullptr;
383 }
384 case 1: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500385 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
386 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500387 return SkPathEffect::MakeSum(std::move(first), std::move(second));
388 }
389 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500390 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
391 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500392 return SkPathEffect::MakeCompose(std::move(first), std::move(second));
393 }
394 case 3: {
395 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -0400396 FuzzNicePath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500397 SkScalar advance, phase;
398 fuzz->next(&advance, &phase);
Hal Canaryf7005202017-03-10 08:48:28 -0500399 SkPath1DPathEffect::Style style;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400400 fuzz->nextEnum(&style, 0, SkPath1DPathEffect::kLastEnum_Style);
Hal Canaryf7005202017-03-10 08:48:28 -0500401 return SkPath1DPathEffect::Make(path, advance, phase, style);
Hal Canary5395c592017-03-08 16:52:18 -0500402 }
403 case 4: {
404 SkScalar width;
405 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400406 fuzz->next(&width);
407 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary5395c592017-03-08 16:52:18 -0500408 return SkLine2DPathEffect::Make(width, matrix);
409 }
410 case 5: {
411 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -0400412 FuzzNicePath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500413 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400414 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary5395c592017-03-08 16:52:18 -0500415 return SkPath2DPathEffect::Make(matrix, path);
416 }
417 case 6: {
418 SkScalar radius;
419 fuzz->next(&radius);
Hal Canary5395c592017-03-08 16:52:18 -0500420 return SkCornerPathEffect::Make(radius);
421 }
Mike Reed40e7e652017-07-22 22:12:59 -0400422 case 7: {
Hal Canary5395c592017-03-08 16:52:18 -0500423 SkScalar phase;
424 fuzz->next(&phase);
425 SkScalar intervals[20];
426 int count;
427 fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
428 fuzz->nextN(intervals, count);
429 return SkDashPathEffect::Make(intervals, count, phase);
430 }
Mike Reed40e7e652017-07-22 22:12:59 -0400431 case 8: {
Hal Canary5395c592017-03-08 16:52:18 -0500432 SkScalar segLength, dev;
433 uint32_t seed;
434 fuzz->next(&segLength, &dev, &seed);
435 return SkDiscretePathEffect::Make(segLength, dev, seed);
436 }
437 default:
438 SkASSERT(false);
439 return nullptr;
440 }
441}
Hal Canary24ac42b2017-02-14 13:35:14 -0500442
Hal Canary1e0138b2017-03-10 13:56:08 -0500443static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
Hal Canary5395c592017-03-08 16:52:18 -0500444 int maskfilterType;
Robert Phillipsab4f5bd2018-04-18 10:05:00 -0400445 fuzz->nextRange(&maskfilterType, 0, 1);
Hal Canary5395c592017-03-08 16:52:18 -0500446 switch (maskfilterType) {
447 case 0:
448 return nullptr;
449 case 1: {
Hal Canaryf7005202017-03-10 08:48:28 -0500450 SkBlurStyle blurStyle;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400451 fuzz->nextEnum(&blurStyle, 0, kLastEnum_SkBlurStyle);
Hal Canary5395c592017-03-08 16:52:18 -0500452 SkScalar sigma;
453 fuzz->next(&sigma);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400454 bool respectCTM;
455 fuzz->next(&respectCTM);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400456 return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
Hal Canary5395c592017-03-08 16:52:18 -0500457 }
Hal Canary5395c592017-03-08 16:52:18 -0500458 default:
459 SkASSERT(false);
460 return nullptr;
461 }
462}
Hal Canary24ac42b2017-02-14 13:35:14 -0500463
Hal Canary1e0138b2017-03-10 13:56:08 -0500464static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
465 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary671e4422017-02-27 13:36:38 -0500466 return nullptr;
467 }
468 auto fontMugger = SkFontMgr::RefDefault();
469 SkASSERT(fontMugger);
470 int familyCount = fontMugger->countFamilies();
471 int i, j;
472 fuzz->nextRange(&i, 0, familyCount - 1);
473 sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
474 int styleCount = family->count();
475 fuzz->nextRange(&j, 0, styleCount - 1);
476 return sk_sp<SkTypeface>(family->createTypeface(j));
477}
Hal Canary24ac42b2017-02-14 13:35:14 -0500478
Hal Canary1e0138b2017-03-10 13:56:08 -0500479static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500480
481static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
482 if (depth <= 0) {
483 return nullptr;
484 }
485 uint8_t imageFilterType;
486 fuzz->nextRange(&imageFilterType, 1, 6);
487 SkPoint3 p, q;
488 SkColor lightColor;
489 SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
490 sk_sp<SkImageFilter> input;
491 SkImageFilter::CropRect cropRect;
492 bool useCropRect;
493 fuzz->next(&useCropRect);
494 if (useCropRect) {
495 fuzz->next(&cropRect);
496 }
497 switch (imageFilterType) {
498 case 1:
499 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500500 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500501 return SkLightingImageFilter::MakeDistantLitDiffuse(p, lightColor, surfaceScale, k,
502 std::move(input),
503 useCropRect ? &cropRect : nullptr);
504 case 2:
505 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500506 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500507 return SkLightingImageFilter::MakePointLitDiffuse(p, lightColor, surfaceScale, k,
508 std::move(input),
509 useCropRect ? &cropRect : nullptr);
510 case 3:
511 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500512 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500513 return SkLightingImageFilter::MakeSpotLitDiffuse(
514 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
515 std::move(input), useCropRect ? &cropRect : nullptr);
516 case 4:
517 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500518 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500519 return SkLightingImageFilter::MakeDistantLitSpecular(p, lightColor, surfaceScale, k,
520 shininess, std::move(input),
521 useCropRect ? &cropRect : nullptr);
522 case 5:
523 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500524 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500525 return SkLightingImageFilter::MakePointLitSpecular(p, lightColor, surfaceScale, k,
526 shininess, std::move(input),
527 useCropRect ? &cropRect : nullptr);
528 case 6:
529 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
530 &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500531 input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500532 return SkLightingImageFilter::MakeSpotLitSpecular(
533 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
534 std::move(input), useCropRect ? &cropRect : nullptr);
535 default:
536 SkASSERT(false);
537 return nullptr;
538 }
539}
540
Hal Canary1e0138b2017-03-10 13:56:08 -0500541static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500542
Hal Canary1e0138b2017-03-10 13:56:08 -0500543static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
Hal Canarye03c3e52017-03-09 11:33:35 -0500544 if (depth <= 0) {
545 return nullptr;
546 }
547 uint8_t imageFilterType;
Kevin Lubick54f20e02018-01-11 14:50:21 -0500548 fuzz->nextRange(&imageFilterType, 0, 23);
Hal Canarye03c3e52017-03-09 11:33:35 -0500549 switch (imageFilterType) {
550 case 0:
551 return nullptr;
552 case 1: {
553 SkScalar sigmaX, sigmaY;
Hal Canary1e0138b2017-03-10 13:56:08 -0500554 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500555 bool useCropRect;
556 fuzz->next(&sigmaX, &sigmaY, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400557 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500558 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400559 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500560 }
Robert Phillips70e3e9a2017-06-26 14:22:01 -0400561 return SkBlurImageFilter::Make(sigmaX, sigmaY, std::move(input),
Hal Canarye03c3e52017-03-09 11:33:35 -0500562 useCropRect ? &cropRect : nullptr);
563 }
564 case 2: {
565 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400566 FuzzNiceMatrix(fuzz, &matrix);
Hal Canarye03c3e52017-03-09 11:33:35 -0500567 SkFilterQuality quality;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400568 fuzz->nextEnum(&quality, 0, SkFilterQuality::kLast_SkFilterQuality);
Hal Canary1e0138b2017-03-10 13:56:08 -0500569 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500570 return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
571 }
572 case 3: {
573 SkRegion region;
574 SkScalar innerMin, outerMax;
Hal Canary1e0138b2017-03-10 13:56:08 -0500575 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500576 bool useCropRect;
577 fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
Kevin Lubickdad29a02017-03-14 17:20:24 -0400578 SkImageFilter::CropRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500579 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400580 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500581 }
582 return SkAlphaThresholdFilter::Make(region, innerMin, outerMax, std::move(input),
583 useCropRect ? &cropRect : nullptr);
584 }
585 case 4: {
586 float k1, k2, k3, k4;
587 bool enforcePMColor;
588 bool useCropRect;
589 fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500590 sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
591 sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500592 SkImageFilter::CropRect cropRect;
593 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400594 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500595 }
596 return SkArithmeticImageFilter::Make(k1, k2, k3, k4, enforcePMColor,
597 std::move(background), std::move(foreground),
598 useCropRect ? &cropRect : nullptr);
599 }
600 case 5: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500601 sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
602 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500603 bool useCropRect;
604 SkImageFilter::CropRect cropRect;
605 fuzz->next(&useCropRect);
606 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400607 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500608 }
609 return SkColorFilterImageFilter::Make(std::move(cf), std::move(input),
610 useCropRect ? &cropRect : nullptr);
611 }
612 case 6: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500613 sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
614 sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500615 return SkComposeImageFilter::Make(std::move(ifo), std::move(ifi));
616 }
617 case 7: {
618 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, yChannelSelector;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400619 fuzz->nextEnum(&xChannelSelector, 1, 4);
620 fuzz->nextEnum(&yChannelSelector, 1, 4);
Hal Canarye03c3e52017-03-09 11:33:35 -0500621 SkScalar scale;
622 bool useCropRect;
623 fuzz->next(&scale, &useCropRect);
624 SkImageFilter::CropRect cropRect;
625 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400626 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500627 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500628 sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
629 sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500630 return SkDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
631 std::move(displacement), std::move(color),
632 useCropRect ? &cropRect : nullptr);
633 }
634 case 8: {
635 SkScalar dx, dy, sigmaX, sigmaY;
636 SkColor color;
637 SkDropShadowImageFilter::ShadowMode shadowMode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400638 fuzz->nextEnum(&shadowMode, 0, 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500639 bool useCropRect;
640 fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &useCropRect);
641 SkImageFilter::CropRect cropRect;
642 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400643 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500644 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500645 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500646 return SkDropShadowImageFilter::Make(dx, dy, sigmaX, sigmaY, color, shadowMode,
647 std::move(input),
648 useCropRect ? &cropRect : nullptr);
649 }
650 case 9:
Hal Canary1e0138b2017-03-10 13:56:08 -0500651 return SkImageSource::Make(make_fuzz_image(fuzz));
Hal Canarye03c3e52017-03-09 11:33:35 -0500652 case 10: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500653 sk_sp<SkImage> image = make_fuzz_image(fuzz);
Hal Canarye03c3e52017-03-09 11:33:35 -0500654 SkRect srcRect, dstRect;
655 SkFilterQuality filterQuality;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400656 fuzz->next(&srcRect, &dstRect);
657 fuzz->nextEnum(&filterQuality, 0, SkFilterQuality::kLast_SkFilterQuality);
Hal Canarye03c3e52017-03-09 11:33:35 -0500658 return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
659 }
660 case 11:
661 return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
662 case 12: {
663 SkRect srcRect;
664 SkScalar inset;
665 bool useCropRect;
666 SkImageFilter::CropRect cropRect;
667 fuzz->next(&srcRect, &inset, &useCropRect);
668 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400669 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500670 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500671 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500672 return SkMagnifierImageFilter::Make(srcRect, inset, std::move(input),
673 useCropRect ? &cropRect : nullptr);
674 }
675 case 13: {
676 constexpr int kMaxKernelSize = 5;
677 int32_t n, m;
678 fuzz->nextRange(&n, 1, kMaxKernelSize);
679 fuzz->nextRange(&m, 1, kMaxKernelSize);
680 SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
681 fuzz->nextN(kernel, n * m);
682 int32_t offsetX, offsetY;
683 fuzz->nextRange(&offsetX, 0, n - 1);
684 fuzz->nextRange(&offsetY, 0, m - 1);
685 SkScalar gain, bias;
686 bool convolveAlpha, useCropRect;
687 fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
688 SkMatrixConvolutionImageFilter::TileMode tileMode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400689 fuzz->nextEnum(&tileMode, 0, SkMatrixConvolutionImageFilter::TileMode::kLast_TileMode);
Hal Canarye03c3e52017-03-09 11:33:35 -0500690 SkImageFilter::CropRect cropRect;
691 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400692 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500693 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500694 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500695 return SkMatrixConvolutionImageFilter::Make(
696 SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
697 convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
698 }
699 case 14: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500700 sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
701 sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500702 bool useCropRect;
703 fuzz->next(&useCropRect);
704 SkImageFilter::CropRect cropRect;
705 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400706 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500707 }
Mike Reed0bdaf052017-06-18 23:35:57 -0400708 return SkMergeImageFilter::Make(std::move(first), std::move(second),
709 useCropRect ? &cropRect : nullptr);
710 }
711 case 15: {
712 constexpr int kMaxCount = 4;
713 sk_sp<SkImageFilter> ifs[kMaxCount];
714 int count;
715 fuzz->nextRange(&count, 1, kMaxCount);
716 for (int i = 0; i < count; ++i) {
717 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
718 }
719 bool useCropRect;
720 fuzz->next(&useCropRect);
721 SkImageFilter::CropRect cropRect;
722 if (useCropRect) {
723 fuzz->next(&cropRect);
724 }
725 return SkMergeImageFilter::Make(ifs, count, useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500726 }
727 case 16: {
728 int rx, ry;
729 fuzz->next(&rx, &ry);
730 bool useCropRect;
731 fuzz->next(&useCropRect);
732 SkImageFilter::CropRect cropRect;
733 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400734 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500735 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500736 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500737 return SkDilateImageFilter::Make(rx, ry, std::move(input),
738 useCropRect ? &cropRect : nullptr);
739 }
740 case 17: {
741 int rx, ry;
742 fuzz->next(&rx, &ry);
743 bool useCropRect;
744 fuzz->next(&useCropRect);
745 SkImageFilter::CropRect cropRect;
746 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400747 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500748 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500749 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500750 return SkErodeImageFilter::Make(rx, ry, std::move(input),
751 useCropRect ? &cropRect : nullptr);
752 }
753 case 18: {
754 SkScalar dx, dy;
755 fuzz->next(&dx, &dy);
756 bool useCropRect;
757 fuzz->next(&useCropRect);
758 SkImageFilter::CropRect cropRect;
759 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400760 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500761 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500762 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500763 return SkOffsetImageFilter::Make(dx, dy, std::move(input),
764 useCropRect ? &cropRect : nullptr);
765 }
766 case 19: {
767 SkPaint paint;
Hal Canary1e0138b2017-03-10 13:56:08 -0500768 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500769 bool useCropRect;
770 fuzz->next(&useCropRect);
771 SkImageFilter::CropRect cropRect;
772 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400773 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500774 }
775 return SkPaintImageFilter::Make(paint, useCropRect ? &cropRect : nullptr);
776 }
777 case 20: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500778 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500779 return SkPictureImageFilter::Make(std::move(picture));
780 }
781 case 21: {
782 SkRect cropRect;
783 fuzz->next(&cropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500784 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500785 return SkPictureImageFilter::Make(std::move(picture), cropRect);
786 }
787 case 22: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500788 SkRect src, dst;
789 fuzz->next(&src, &dst);
Hal Canary1e0138b2017-03-10 13:56:08 -0500790 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500791 return SkTileImageFilter::Make(src, dst, std::move(input));
792 }
Mike Reed77e487d2017-11-09 21:50:20 +0000793 case 23: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500794 SkBlendMode blendMode;
795 bool useCropRect;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400796 fuzz->next(&useCropRect);
797 fuzz->nextEnum(&blendMode, 0, SkBlendMode::kLastMode);
Hal Canarye03c3e52017-03-09 11:33:35 -0500798 SkImageFilter::CropRect cropRect;
799 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400800 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500801 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500802 sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
803 sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500804 return SkXfermodeImageFilter::Make(blendMode, std::move(bg), std::move(fg),
805 useCropRect ? &cropRect : nullptr);
806 }
807 default:
808 SkASSERT(false);
809 return nullptr;
810 }
811}
Hal Canary24ac42b2017-02-14 13:35:14 -0500812
Hal Canary1e0138b2017-03-10 13:56:08 -0500813static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500814 int w, h;
815 fuzz->nextRange(&w, 1, 1024);
816 fuzz->nextRange(&h, 1, 1024);
817 SkAutoTMalloc<SkPMColor> data(w * h);
818 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
819 int n = w * h;
820 for (int i = 0; i < n; ++i) {
821 SkColor c;
822 fuzz->next(&c);
823 data[i] = SkPreMultiplyColor(c);
824 }
825 (void)data.release();
Hal Canaryb69c4b82017-03-08 11:02:40 -0500826 return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
827 nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500828}
829
Hal Canary1e0138b2017-03-10 13:56:08 -0500830static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500831 SkBitmap bitmap;
832 int w, h;
833 fuzz->nextRange(&w, 1, 1024);
834 fuzz->nextRange(&h, 1, 1024);
Kevin Lubick1991f552018-02-27 10:59:10 -0500835 if (!bitmap.tryAllocN32Pixels(w, h)) {
Hal Canary2b0e6cd2018-07-09 12:43:39 -0400836 SkDEBUGF("Could not allocate pixels %d x %d", w, h);
Kevin Lubick1991f552018-02-27 10:59:10 -0500837 return bitmap;
838 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500839 for (int y = 0; y < h; ++y) {
840 for (int x = 0; x < w; ++x) {
841 SkColor c;
842 fuzz->next(&c);
843 *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
844 }
845 }
846 return bitmap;
847}
848
Hal Canary1e0138b2017-03-10 13:56:08 -0500849template <typename T, typename Min, typename Max>
850inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
851 T value;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400852 fuzz->nextEnum(&value, minv, maxv);
Hal Canary1e0138b2017-03-10 13:56:08 -0500853 return value;
854}
855
856static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500857 if (!fuzz || !paint || depth <= 0) {
858 return;
859 }
860
Hal Canary1e0138b2017-03-10 13:56:08 -0500861 paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
862 paint->setDither( make_fuzz_t<bool>(fuzz));
863 paint->setColor( make_fuzz_t<SkColor>(fuzz));
864 paint->setBlendMode( make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
865 paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
866 paint->setStyle( make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
867 paint->setShader( make_fuzz_shader(fuzz, depth - 1));
868 paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
869 paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
870 paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
871 paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
Hal Canary24ac42b2017-02-14 13:35:14 -0500872
873 if (paint->getStyle() != SkPaint::kFill_Style) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500874 paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
875 paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
876 paint->setStrokeCap( make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
877 paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
Hal Canary24ac42b2017-02-14 13:35:14 -0500878 }
879}
880
Hal Canary1e0138b2017-03-10 13:56:08 -0500881static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
882 paint->setTypeface( make_fuzz_typeface(fuzz));
883 paint->setTextSize( make_fuzz_t<SkScalar>(fuzz));
884 paint->setTextScaleX( make_fuzz_t<SkScalar>(fuzz));
885 paint->setTextSkewX( make_fuzz_t<SkScalar>(fuzz));
886 paint->setLinearText( make_fuzz_t<bool>(fuzz));
887 paint->setSubpixelText( make_fuzz_t<bool>(fuzz));
888 paint->setLCDRenderText( make_fuzz_t<bool>(fuzz));
889 paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
890 paint->setAutohinted( make_fuzz_t<bool>(fuzz));
891 paint->setVerticalText( make_fuzz_t<bool>(fuzz));
892 paint->setFakeBoldText( make_fuzz_t<bool>(fuzz));
893 paint->setDevKernText( make_fuzz_t<bool>(fuzz));
894 paint->setHinting( make_fuzz_t_range<SkPaint::Hinting>(fuzz, 0,
895 SkPaint::kFull_Hinting));
896 paint->setTextAlign( make_fuzz_t_range<SkPaint::Align>(fuzz, 0, 2));
Hal Canary5395c592017-03-08 16:52:18 -0500897}
898
899static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500900 paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
Hal Canary24ac42b2017-02-14 13:35:14 -0500901}
902
Hal Canary5395c592017-03-08 16:52:18 -0500903constexpr int kMaxGlyphCount = 30;
904
Hal Canary1e0138b2017-03-10 13:56:08 -0500905static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
Hal Canary671e4422017-02-27 13:36:38 -0500906 SkTDArray<uint8_t> array;
907 if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500908 int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
909 : SkTypeface::MakeDefault()->countGlyphs();
Kevin Lubick1991f552018-02-27 10:59:10 -0500910 if (glyphRange == 0) {
911 // Some fuzzing environments have no fonts, so empty array is the best
912 // we can do.
913 return array;
914 }
Hal Canary671e4422017-02-27 13:36:38 -0500915 int glyphCount;
Hal Canary5395c592017-03-08 16:52:18 -0500916 fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
Hal Canary671e4422017-02-27 13:36:38 -0500917 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
918 for (int i = 0; i < glyphCount; ++i) {
919 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
920 }
921 return array;
922 }
923 static const SkUnichar ranges[][2] = {
924 {0x0020, 0x007F},
925 {0x00A1, 0x0250},
926 {0x0400, 0x0500},
927 };
928 int32_t count = 0;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500929 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500930 count += (ranges[i][1] - ranges[i][0]);
931 }
Hal Canary5395c592017-03-08 16:52:18 -0500932 constexpr int kMaxLength = kMaxGlyphCount;
Hal Canary671e4422017-02-27 13:36:38 -0500933 SkUnichar buffer[kMaxLength];
934 int length;
935 fuzz->nextRange(&length, 1, kMaxLength);
936 for (int j = 0; j < length; ++j) {
937 int32_t value;
938 fuzz->nextRange(&value, 0, count - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500939 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500940 if (value + ranges[i][0] < ranges[i][1]) {
941 buffer[j] = value + ranges[i][0];
942 break;
943 } else {
944 value -= (ranges[i][1] - ranges[i][0]);
945 }
946 }
947 }
948 switch (paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500949 case SkPaint::kUTF8_TextEncoding: {
950 size_t utf8len = 0;
951 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400952 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
Hal Canary671e4422017-02-27 13:36:38 -0500953 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500954 char* ptr = (char*)array.append(utf8len);
955 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400956 ptr += SkUTF::ToUTF8(buffer[j], ptr);
Hal Canary671e4422017-02-27 13:36:38 -0500957 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500958 } break;
959 case SkPaint::kUTF16_TextEncoding: {
960 size_t utf16len = 0;
961 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400962 utf16len += SkUTF::ToUTF16(buffer[j]);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500963 }
964 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
965 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400966 ptr += SkUTF::ToUTF16(buffer[j], ptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500967 }
968 } break;
Hal Canary671e4422017-02-27 13:36:38 -0500969 case SkPaint::kUTF32_TextEncoding:
970 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
Hal Canaryc1a70e22017-03-01 15:40:46 -0500971 break;
Hal Canary671e4422017-02-27 13:36:38 -0500972 default:
Hal Canaryb69c4b82017-03-08 11:02:40 -0500973 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -0500974 break;
Hal Canary671e4422017-02-27 13:36:38 -0500975 }
976 return array;
977}
978
Hal Canary5395c592017-03-08 16:52:18 -0500979static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
980 SkTextBlobBuilder textBlobBuilder;
981 int8_t runCount;
982 fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
983 while (runCount-- > 0) {
984 SkPaint paint;
985 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary1e0138b2017-03-10 13:56:08 -0500986 paint.setAntiAlias(make_fuzz_t<bool>(fuzz));
Hal Canary5395c592017-03-08 16:52:18 -0500987 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
988 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
989 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
990 SkASSERT(glyphCount <= kMaxGlyphCount);
991 SkScalar x, y;
992 const SkTextBlobBuilder::RunBuffer* buffer;
993 uint8_t runType;
994 fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
995 switch (runType) {
996 case 0:
997 fuzz->next(&x, &y);
998 // TODO: Test other variations of this.
999 buffer = &textBlobBuilder.allocRun(paint, glyphCount, x, y);
1000 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1001 break;
1002 case 1:
1003 fuzz->next(&y);
1004 // TODO: Test other variations of this.
1005 buffer = &textBlobBuilder.allocRunPosH(paint, glyphCount, y);
1006 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1007 fuzz->nextN(buffer->pos, glyphCount);
1008 break;
1009 case 2:
1010 // TODO: Test other variations of this.
1011 buffer = &textBlobBuilder.allocRunPos(paint, glyphCount);
1012 memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1013 fuzz->nextN(buffer->pos, glyphCount * 2);
1014 break;
1015 default:
1016 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -05001017 break;
Hal Canary5395c592017-03-08 16:52:18 -05001018 }
1019 }
1020 return textBlobBuilder.make();
1021}
1022
Kevin Lubickd2ae8dc2018-06-01 13:16:20 -04001023extern std::atomic<bool> gSkUseDeltaAA;
1024extern std::atomic<bool> gSkForceDeltaAA;
1025
Hal Canary1e0138b2017-03-10 13:56:08 -05001026static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001027 if (!fuzz || !canvas || depth <= 0) {
1028 return;
1029 }
1030 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
Kevin Lubickd2ae8dc2018-06-01 13:16:20 -04001031 bool useDAA;
1032 fuzz->next(&useDAA);
1033 if (useDAA) {
1034 gSkForceDeltaAA = true;
1035 gSkUseDeltaAA = true;
1036 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001037 unsigned N;
1038 fuzz->nextRange(&N, 0, 2000);
1039 for (unsigned i = 0; i < N; ++i) {
1040 if (fuzz->exhausted()) {
1041 return;
1042 }
1043 SkPaint paint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001044 unsigned drawCommand;
Hal Canary5af600e2017-03-09 14:10:36 -05001045 fuzz->nextRange(&drawCommand, 0, 53);
Hal Canary24ac42b2017-02-14 13:35:14 -05001046 switch (drawCommand) {
1047 case 0:
1048 canvas->flush();
1049 break;
1050 case 1:
1051 canvas->save();
1052 break;
1053 case 2: {
1054 SkRect bounds;
1055 fuzz->next(&bounds);
Hal Canary1e0138b2017-03-10 13:56:08 -05001056 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001057 canvas->saveLayer(&bounds, &paint);
1058 break;
1059 }
1060 case 3: {
1061 SkRect bounds;
1062 fuzz->next(&bounds);
1063 canvas->saveLayer(&bounds, nullptr);
1064 break;
1065 }
1066 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -05001067 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001068 canvas->saveLayer(nullptr, &paint);
1069 break;
1070 case 5:
1071 canvas->saveLayer(nullptr, nullptr);
1072 break;
1073 case 6: {
1074 uint8_t alpha;
1075 fuzz->next(&alpha);
1076 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1077 break;
1078 }
1079 case 7: {
1080 SkRect bounds;
1081 uint8_t alpha;
1082 fuzz->next(&bounds, &alpha);
1083 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1084 break;
1085 }
1086 case 8: {
1087 SkCanvas::SaveLayerRec saveLayerRec;
1088 SkRect bounds;
Hal Canary1e0138b2017-03-10 13:56:08 -05001089 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001090 fuzz->next(&bounds);
1091 saveLayerRec.fBounds = &bounds;
1092 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001093 if (make_fuzz_t<bool>(fuzz)) {
1094 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001095 saveLayerRec.fPaint = &paint;
1096 }
1097 sk_sp<SkImageFilter> imageFilter;
Hal Canary1e0138b2017-03-10 13:56:08 -05001098 if (make_fuzz_t<bool>(fuzz)) {
1099 imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001100 saveLayerRec.fBackdrop = imageFilter.get();
1101 }
Hal Canary5395c592017-03-08 16:52:18 -05001102 // _DumpCanvas can't handle this.
Hal Canary1e0138b2017-03-10 13:56:08 -05001103 // if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -05001104 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1105 // }
1106
Hal Canary24ac42b2017-02-14 13:35:14 -05001107 canvas->saveLayer(saveLayerRec);
1108 break;
1109 }
1110 case 9:
1111 canvas->restore();
1112 break;
1113 case 10: {
1114 int saveCount;
1115 fuzz->next(&saveCount);
1116 canvas->restoreToCount(saveCount);
1117 break;
1118 }
1119 case 11: {
1120 SkScalar x, y;
1121 fuzz->next(&x, &y);
1122 canvas->translate(x, y);
1123 break;
1124 }
1125 case 12: {
1126 SkScalar x, y;
1127 fuzz->next(&x, &y);
1128 canvas->scale(x, y);
1129 break;
1130 }
1131 case 13: {
1132 SkScalar v;
1133 fuzz->next(&v);
1134 canvas->rotate(v);
1135 break;
1136 }
1137 case 14: {
1138 SkScalar x, y, v;
1139 fuzz->next(&x, &y, &v);
1140 canvas->rotate(v, x, y);
1141 break;
1142 }
1143 case 15: {
1144 SkScalar x, y;
1145 fuzz->next(&x, &y);
1146 canvas->skew(x, y);
1147 break;
1148 }
1149 case 16: {
1150 SkMatrix mat;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001151 FuzzNiceMatrix(fuzz, &mat);
Hal Canary24ac42b2017-02-14 13:35:14 -05001152 canvas->concat(mat);
1153 break;
1154 }
1155 case 17: {
1156 SkMatrix mat;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001157 FuzzNiceMatrix(fuzz, &mat);
Hal Canary24ac42b2017-02-14 13:35:14 -05001158 canvas->setMatrix(mat);
1159 break;
1160 }
1161 case 18:
1162 canvas->resetMatrix();
1163 break;
1164 case 19: {
1165 SkRect r;
1166 int op;
1167 bool doAntiAlias;
1168 fuzz->next(&r, &doAntiAlias);
1169 fuzz->nextRange(&op, 0, 1);
1170 r.sort();
1171 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1172 break;
1173 }
1174 case 20: {
1175 SkRRect rr;
1176 int op;
1177 bool doAntiAlias;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001178 FuzzNiceRRect(fuzz, &rr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001179 fuzz->next(&doAntiAlias);
1180 fuzz->nextRange(&op, 0, 1);
1181 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1182 break;
1183 }
1184 case 21: {
1185 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001186 FuzzNicePath(fuzz, &path, 30);
Hal Canary24ac42b2017-02-14 13:35:14 -05001187 int op;
1188 bool doAntiAlias;
1189 fuzz->next(&doAntiAlias);
1190 fuzz->nextRange(&op, 0, 1);
1191 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1192 break;
1193 }
1194 case 22: {
1195 SkRegion region;
Hal Canary24ac42b2017-02-14 13:35:14 -05001196 int op;
Hal Canarye03c3e52017-03-09 11:33:35 -05001197 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001198 fuzz->nextRange(&op, 0, 1);
1199 canvas->clipRegion(region, (SkClipOp)op);
1200 break;
1201 }
1202 case 23:
Hal Canary1e0138b2017-03-10 13:56:08 -05001203 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001204 canvas->drawPaint(paint);
1205 break;
1206 case 24: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001207 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001208 SkCanvas::PointMode pointMode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001209 fuzz->nextEnum(&pointMode,
Hal Canaryc8bebd42017-12-20 11:21:05 -05001210 SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001211 size_t count;
1212 constexpr int kMaxCount = 30;
1213 fuzz->nextRange(&count, 0, kMaxCount);
1214 SkPoint pts[kMaxCount];
1215 fuzz->nextN(pts, count);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001216 canvas->drawPoints(pointMode, count, pts, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001217 break;
1218 }
1219 case 25: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001220 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001221 SkRect r;
1222 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001223 if (!r.isFinite()) {
1224 break;
1225 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001226 canvas->drawRect(r, paint);
1227 break;
1228 }
1229 case 26: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001230 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001231 SkRegion region;
Hal Canarye03c3e52017-03-09 11:33:35 -05001232 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001233 canvas->drawRegion(region, paint);
1234 break;
1235 }
1236 case 27: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001237 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001238 SkRect r;
1239 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001240 if (!r.isFinite()) {
1241 break;
1242 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001243 canvas->drawOval(r, paint);
1244 break;
1245 }
Mike Reed9cec1bc2018-01-19 12:57:01 -05001246 case 28: break; // must have deleted this some time earlier
Hal Canary24ac42b2017-02-14 13:35:14 -05001247 case 29: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001248 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001249 SkRRect rr;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001250 FuzzNiceRRect(fuzz, &rr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001251 canvas->drawRRect(rr, paint);
1252 break;
1253 }
1254 case 30: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001255 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001256 SkRRect orr, irr;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001257 FuzzNiceRRect(fuzz, &orr);
1258 FuzzNiceRRect(fuzz, &irr);
Hal Canary27bece82017-03-07 16:23:20 -05001259 if (orr.getBounds().contains(irr.getBounds())) {
1260 canvas->drawDRRect(orr, irr, paint);
1261 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001262 break;
1263 }
1264 case 31: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001265 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001266 SkRect r;
1267 SkScalar start, sweep;
1268 bool useCenter;
1269 fuzz->next(&r, &start, &sweep, &useCenter);
1270 canvas->drawArc(r, start, sweep, useCenter, paint);
1271 break;
1272 }
1273 case 32: {
Kevin Lubick0938ce72018-05-21 21:17:15 -04001274 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001275 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001276 FuzzNicePath(fuzz, &path, 60);
Hal Canary24ac42b2017-02-14 13:35:14 -05001277 canvas->drawPath(path, paint);
1278 break;
1279 }
1280 case 33: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001281 sk_sp<SkImage> img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001282 SkScalar left, top;
1283 bool usePaint;
1284 fuzz->next(&left, &top, &usePaint);
1285 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001286 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001287 }
1288 canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
1289 break;
1290 }
1291 case 34: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001292 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001293 SkRect src, dst;
1294 bool usePaint;
1295 fuzz->next(&src, &dst, &usePaint);
1296 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001297 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001298 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001299 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001300 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1301 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001302 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1303 break;
1304 }
1305 case 35: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001306 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001307 SkIRect src;
1308 SkRect dst;
1309 bool usePaint;
1310 fuzz->next(&src, &dst, &usePaint);
1311 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001312 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001313 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001314 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001315 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1316 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001317 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1318 break;
1319 }
1320 case 36: {
1321 bool usePaint;
Hal Canary1e0138b2017-03-10 13:56:08 -05001322 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001323 SkRect dst;
1324 fuzz->next(&dst, &usePaint);
1325 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001326 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001327 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001328 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001329 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1330 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001331 canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr, constraint);
1332 break;
1333 }
1334 case 37: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001335 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001336 SkIRect center;
1337 SkRect dst;
1338 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001339 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001340 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001341 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001342 }
Hal Canary0361d492017-03-15 12:58:15 -04001343 if (make_fuzz_t<bool>(fuzz)) {
1344 fuzz->next(&center);
1345 } else { // Make valid center, see SkLatticeIter::Valid().
1346 fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1347 fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1348 fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1349 fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1350 }
1351 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001352 canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
1353 break;
1354 }
1355 case 38: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001356 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001357 SkScalar left, top;
1358 bool usePaint;
1359 fuzz->next(&left, &top, &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 }
1363 canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
1364 break;
1365 }
1366 case 39: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001367 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001368 SkRect src, dst;
1369 bool usePaint;
1370 fuzz->next(&src, &dst, &usePaint);
1371 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001372 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001373 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001374 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001375 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1376 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001377 canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
1378 break;
1379 }
1380 case 40: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001381 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001382 SkIRect src;
1383 SkRect dst;
1384 bool usePaint;
1385 fuzz->next(&src, &dst, &usePaint);
1386 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001387 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001388 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001389 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001390 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1391 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001392 canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1393 break;
1394 }
1395 case 41: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001396 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001397 SkRect dst;
1398 bool usePaint;
1399 fuzz->next(&dst, &usePaint);
1400 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001401 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001402 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001403 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001404 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1405 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -05001406 canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1407 break;
1408 }
1409 case 42: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001410 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001411 SkIRect center;
1412 SkRect dst;
1413 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001414 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001415 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001416 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001417 }
Hal Canary0361d492017-03-15 12:58:15 -04001418 if (make_fuzz_t<bool>(fuzz)) {
1419 fuzz->next(&center);
1420 } else { // Make valid center, see SkLatticeIter::Valid().
Kevin Lubick1991f552018-02-27 10:59:10 -05001421 if (img.width() == 0 || img.height() == 0) {
1422 // bitmap may not have had its pixels initialized.
1423 break;
1424 }
Hal Canary0361d492017-03-15 12:58:15 -04001425 fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
1426 fuzz->nextRange(&center.fTop, 0, img.height() - 1);
1427 fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
1428 fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
1429 }
1430 fuzz->next(&dst);
Hal Canary24ac42b2017-02-14 13:35:14 -05001431 canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1432 break;
1433 }
1434 case 43: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001435 SkBitmap img = make_fuzz_bitmap(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001436 bool usePaint;
1437 SkRect dst;
1438 fuzz->next(&usePaint, &dst);
1439 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001440 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001441 }
1442 constexpr int kMax = 6;
1443 int xDivs[kMax], yDivs[kMax];
Stan Ilievca8c0952017-12-11 13:01:58 -05001444 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
Hal Canary24ac42b2017-02-14 13:35:14 -05001445 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1446 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1447 fuzz->nextN(xDivs, lattice.fXCount);
1448 fuzz->nextN(yDivs, lattice.fYCount);
1449 canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1450 break;
1451 }
1452 case 44: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001453 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001454 bool usePaint;
1455 SkRect dst;
1456 fuzz->next(&usePaint, &dst);
1457 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001458 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001459 }
1460 constexpr int kMax = 6;
1461 int xDivs[kMax], yDivs[kMax];
Stan Ilievca8c0952017-12-11 13:01:58 -05001462 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
Hal Canary24ac42b2017-02-14 13:35:14 -05001463 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1464 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1465 fuzz->nextN(xDivs, lattice.fXCount);
1466 fuzz->nextN(yDivs, lattice.fYCount);
1467 canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1468 break;
1469 }
1470 case 45: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001471 fuzz_paint(fuzz, &paint, depth - 1);
1472 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001473 fuzz_paint_text_encoding(fuzz, &paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001474 SkScalar x, y;
1475 fuzz->next(&x, &y);
Hal Canary5395c592017-03-08 16:52:18 -05001476 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001477 canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001478 break;
1479 }
1480 case 46: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001481 fuzz_paint(fuzz, &paint, depth - 1);
1482 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001483 fuzz_paint_text_encoding(fuzz, &paint);
1484 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001485 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001486 if (glyphCount < 1) {
1487 break;
1488 }
1489 SkAutoTMalloc<SkPoint> pos(glyphCount);
1490 SkAutoTMalloc<SkScalar> widths(glyphCount);
Hal Canary671e4422017-02-27 13:36:38 -05001491 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001492 pos[0] = {0, 0};
1493 for (int i = 1; i < glyphCount; ++i) {
1494 float y;
Hal Canaryb69c4b82017-03-08 11:02:40 -05001495 fuzz->nextRange(&y, -0.5f * paint.getTextSize(), 0.5f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001496 pos[i] = {pos[i - 1].x() + widths[i - 1], y};
1497 }
Hal Canary671e4422017-02-27 13:36:38 -05001498 canvas->drawPosText(text.begin(), SkToSizeT(text.count()), pos.get(), paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001499 break;
1500 }
1501 case 47: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001502 fuzz_paint(fuzz, &paint, depth - 1);
1503 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001504 fuzz_paint_text_encoding(fuzz, &paint);
1505 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary671e4422017-02-27 13:36:38 -05001506 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001507 SkAutoTMalloc<SkScalar> widths(glyphCount);
1508 if (glyphCount < 1) {
1509 break;
1510 }
Hal Canary671e4422017-02-27 13:36:38 -05001511 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001512 SkScalar x = widths[0];
1513 for (int i = 0; i < glyphCount; ++i) {
Ben Wagnerf08d1d02018-06-18 15:11:00 -04001514 using std::swap;
1515 swap(x, widths[i]);
Hal Canary24ac42b2017-02-14 13:35:14 -05001516 x += widths[i];
1517 SkScalar offset;
1518 fuzz->nextRange(&offset, -0.125f * paint.getTextSize(),
Hal Canaryb69c4b82017-03-08 11:02:40 -05001519 0.125f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001520 widths[i] += offset;
1521 }
1522 SkScalar y;
1523 fuzz->next(&y);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001524 canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001525 break;
1526 }
1527 case 48: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001528 fuzz_paint(fuzz, &paint, depth - 1);
1529 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001530 fuzz_paint_text_encoding(fuzz, &paint);
1531 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001532 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001533 FuzzNicePath(fuzz, &path, 20);
Hal Canary24ac42b2017-02-14 13:35:14 -05001534 SkScalar hOffset, vOffset;
1535 fuzz->next(&hOffset, &vOffset);
Mike Reeda62d0362018-08-28 16:26:06 -04001536 SkDrawTextOnPathHV(text.begin(), SkToSizeT(text.count()), paint, path, hOffset,
1537 vOffset, canvas);
Hal Canary24ac42b2017-02-14 13:35:14 -05001538 break;
1539 }
1540 case 49: {
1541 SkMatrix matrix;
Hal Canary1e0138b2017-03-10 13:56:08 -05001542 bool useMatrix = make_fuzz_t<bool>(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001543 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001544 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -05001545 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001546 fuzz_paint(fuzz, &paint, depth - 1);
1547 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001548 fuzz_paint_text_encoding(fuzz, &paint);
1549 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001550 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001551 FuzzNicePath(fuzz, &path, 20);
Mike Reeda62d0362018-08-28 16:26:06 -04001552 SkDrawTextOnPath(text.begin(), SkToSizeT(text.count()), paint, path,
1553 useMatrix ? &matrix :nullptr, canvas);
Hal Canary24ac42b2017-02-14 13:35:14 -05001554 break;
1555 }
1556 case 50: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001557 fuzz_paint(fuzz, &paint, depth - 1);
1558 fuzz_paint_text(fuzz, &paint);
Hal Canary5395c592017-03-08 16:52:18 -05001559 fuzz_paint_text_encoding(fuzz, &paint);
1560 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1561 SkRSXform rSXform[kMaxGlyphCount];
1562 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1563 SkASSERT(glyphCount <= kMaxGlyphCount);
1564 fuzz->nextN(rSXform, glyphCount);
1565 SkRect cullRect;
1566 bool useCullRect;
1567 fuzz->next(&useCullRect);
1568 if (useCullRect) {
1569 fuzz->next(&cullRect);
1570 }
1571 canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
1572 useCullRect ? &cullRect : nullptr, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001573 break;
1574 }
1575 case 51: {
Hal Canary5395c592017-03-08 16:52:18 -05001576 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
Hal Canary1e0138b2017-03-10 13:56:08 -05001577 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -05001578 SkScalar x, y;
1579 fuzz->next(&x, &y);
1580 canvas->drawTextBlob(blob, x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001581 break;
1582 }
1583 case 52: {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001584 SkMatrix matrix;
Hal Canary24ac42b2017-02-14 13:35:14 -05001585 bool usePaint, useMatrix;
1586 fuzz->next(&usePaint, &useMatrix);
1587 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001588 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001589 }
1590 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001591 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -05001592 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001593 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001594 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1595 usePaint ? &paint : nullptr);
1596 break;
1597 }
1598 case 53: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001599 fuzz_paint(fuzz, &paint, depth - 1);
Mike Reed887cdf12017-04-03 11:11:09 -04001600 SkVertices::VertexMode vertexMode;
Hal Canary5af600e2017-03-09 14:10:36 -05001601 SkBlendMode blendMode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001602 fuzz->nextEnum(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1603 fuzz->nextEnum(&blendMode, 0, SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001604 constexpr int kMaxCount = 100;
1605 int vertexCount;
1606 SkPoint vertices[kMaxCount];
1607 SkPoint texs[kMaxCount];
1608 SkColor colors[kMaxCount];
Hal Canary24ac42b2017-02-14 13:35:14 -05001609 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1610 fuzz->nextN(vertices, vertexCount);
1611 bool useTexs, useColors;
1612 fuzz->next(&useTexs, &useColors);
1613 if (useTexs) {
1614 fuzz->nextN(texs, vertexCount);
1615 }
1616 if (useColors) {
1617 fuzz->nextN(colors, vertexCount);
1618 }
1619 int indexCount = 0;
Hal Canary68b9b572017-03-02 15:27:23 -05001620 uint16_t indices[kMaxCount * 2];
Hal Canary1e0138b2017-03-10 13:56:08 -05001621 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary68b9b572017-03-02 15:27:23 -05001622 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1623 for (int i = 0; i < indexCount; ++i) {
1624 fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1625 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001626 }
Mike Reed887cdf12017-04-03 11:11:09 -04001627 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1628 useTexs ? texs : nullptr,
1629 useColors ? colors : nullptr,
1630 indexCount, indices),
1631 blendMode, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001632 break;
1633 }
1634 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -05001635 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -05001636 break;
1637 }
1638 }
1639}
1640
Hal Canary1e0138b2017-03-10 13:56:08 -05001641static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001642 SkScalar w, h;
1643 fuzz->next(&w, &h);
1644 SkPictureRecorder pictureRecorder;
1645 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1646 return pictureRecorder.finishRecordingAsPicture();
1647}
1648
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001649DEF_FUZZ(NullCanvas, fuzz) {
1650 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001651}
1652
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001653constexpr SkISize kCanvasSize = {128, 160};
Hal Canary44801ca2017-03-15 11:39:06 -04001654
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001655DEF_FUZZ(RasterN32Canvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001656 auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001657 if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001658 fuzz_canvas(fuzz, surface->getCanvas());
1659}
1660
Hal Canarye2924432017-12-01 11:46:26 -05001661DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1662 SkPictureRecorder recorder;
1663 fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1664 SkIntToScalar(kCanvasSize.height())));
1665 sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1666 if (!pic) { fuzz->signalBug(); }
1667 sk_sp<SkData> data = pic->serialize();
1668 if (!data) { fuzz->signalBug(); }
Mike Reedfadbfcd2017-12-06 16:09:20 -05001669 SkReadBuffer rb(data->data(), data->size());
Cary Clarkefd99cc2018-06-11 16:25:43 -04001670 auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
Hal Canarye2924432017-12-01 11:46:26 -05001671 if (!deserialized) { fuzz->signalBug(); }
1672 auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1673 SkASSERT(surface && surface->getCanvas());
1674 surface->getCanvas()->drawPicture(deserialized);
1675}
1676
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001677DEF_FUZZ(ImageFilter, fuzz) {
1678 auto fil = make_fuzz_imageFilter(fuzz, 20);
1679
1680 SkPaint paint;
1681 paint.setImageFilter(fil);
1682 SkBitmap bitmap;
1683 SkCanvas canvas(bitmap);
1684 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1685}
1686
1687
1688//SkRandom _rand;
1689#define SK_ADD_RANDOM_BIT_FLIPS
1690
1691DEF_FUZZ(SerializedImageFilter, fuzz) {
1692 auto filter = make_fuzz_imageFilter(fuzz, 20);
Robert Phillips66f6ef42018-09-14 11:58:40 -04001693 if (!filter) {
1694 return;
1695 }
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001696 auto data = filter->serialize();
1697 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1698 size_t len = data->size();
1699#ifdef SK_ADD_RANDOM_BIT_FLIPS
1700 unsigned char* p = const_cast<unsigned char*>(ptr);
1701 for (size_t i = 0; i < len; ++i, ++p) {
1702 uint8_t j;
1703 fuzz->nextRange(&j, 1, 250);
1704 if (j == 1) { // 0.4% of the time, flip a bit or byte
1705 uint8_t k;
1706 fuzz->nextRange(&k, 1, 10);
1707 if (k == 1) { // Then 10% of the time, change a whole byte
1708 uint8_t s;
1709 fuzz->nextRange(&s, 0, 2);
1710 switch(s) {
1711 case 0:
1712 *p ^= 0xFF; // Flip entire byte
1713 break;
1714 case 1:
1715 *p = 0xFF; // Set all bits to 1
1716 break;
1717 case 2:
1718 *p = 0x00; // Set all bits to 0
1719 break;
1720 }
1721 } else {
1722 uint8_t s;
1723 fuzz->nextRange(&s, 0, 7);
1724 *p ^= (1 << 7);
1725 }
1726 }
1727 }
1728#endif // SK_ADD_RANDOM_BIT_FLIPS
1729 auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1730
1731 // uncomment below to write out a serialized image filter (to make corpus
1732 // for -t filter_fuzz)
1733 // SkString s("./serialized_filters/sf");
1734 // s.appendU32(_rand.nextU());
1735 // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1736 // sk_fwrite(data->bytes(), data->size(), file);
1737 // sk_fclose(file);
1738
1739 SkPaint paint;
1740 paint.setImageFilter(deserializedFil);
1741 SkBitmap bitmap;
1742 SkCanvas canvas(bitmap);
1743 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1744}
1745
Hal Canary44801ca2017-03-15 11:39:06 -04001746#if SK_SUPPORT_GPU
Kevin Lubickfaef5142018-06-07 10:33:11 -04001747
1748static void dump_GPU_info(GrContext* context) {
1749 const GrGLInterface* gl = static_cast<GrGLGpu*>(context->contextPriv().getGpu())
1750 ->glInterface();
1751 const GrGLubyte* output;
1752 GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1753 SkDebugf("GL_RENDERER %s\n", (const char*) output);
1754
1755 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1756 SkDebugf("GL_VENDOR %s\n", (const char*) output);
1757
1758 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1759 SkDebugf("GL_VERSION %s\n", (const char*) output);
1760}
1761
Hal Canary5aa91582017-03-21 11:11:44 -07001762static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
1763 SkASSERT(context);
1764 auto surface = SkSurface::MakeRenderTarget(
1765 context,
1766 SkBudgeted::kNo,
1767 SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1768 SkASSERT(surface && surface->getCanvas());
1769 fuzz_canvas(fuzz, surface->getCanvas());
1770}
1771
Hal Canary44801ca2017-03-15 11:39:06 -04001772DEF_FUZZ(NativeGLCanvas, fuzz) {
Hal Canary549be4a2018-01-05 16:59:53 -05001773 sk_gpu_test::GrContextFactory f;
1774 GrContext* context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
Brian Salomon6405e712017-03-20 08:54:16 -04001775 if (!context) {
Hal Canary549be4a2018-01-05 16:59:53 -05001776 context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
Brian Salomon6405e712017-03-20 08:54:16 -04001777 }
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001778 if (FLAGS_gpuInfo) {
Kevin Lubickfaef5142018-06-07 10:33:11 -04001779 dump_GPU_info(context);
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001780 }
Hal Canary5aa91582017-03-21 11:11:44 -07001781 fuzz_ganesh(fuzz, context);
1782}
1783
Kevin Lubick27d42192018-04-03 12:30:32 -04001784// This target is deprecated, NullGLContext is not well maintained.
1785// Please use MockGPUCanvas instead.
Hal Canary5aa91582017-03-21 11:11:44 -07001786DEF_FUZZ(NullGLCanvas, fuzz) {
Hal Canary549be4a2018-01-05 16:59:53 -05001787 sk_gpu_test::GrContextFactory f;
1788 fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kNullGL_ContextType));
Hal Canary5aa91582017-03-21 11:11:44 -07001789}
1790
Kevin Lubick27d42192018-04-03 12:30:32 -04001791DEF_FUZZ(MockGPUCanvas, fuzz) {
Kevin Lubick30709262018-04-02 11:06:41 -04001792 sk_gpu_test::GrContextFactory f;
1793 fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
1794}
Hal Canary44801ca2017-03-15 11:39:06 -04001795#endif
1796
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001797DEF_FUZZ(PDFCanvas, fuzz) {
Hal Canaryfe759302017-08-26 17:06:42 -04001798 SkNullWStream stream;
Hal Canary23564b92018-09-07 14:33:14 -04001799 auto doc = SkPDF::MakeDocument(&stream);
Hal Canary44801ca2017-03-15 11:39:06 -04001800 fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1801 SkIntToScalar(kCanvasSize.height())));
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001802}
1803
1804// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1805DEF_FUZZ(_DumpCanvas, fuzz) {
Hal Canary44801ca2017-03-15 11:39:06 -04001806 SkDebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001807 fuzz_canvas(fuzz, &debugCanvas);
1808 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1809 UrlDataManager dataManager(SkString("data"));
1810 Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
1811 Json::StyledStreamWriter(" ").write(std::cout, json);
1812}