blob: 99621936c997e0d9961b26847ff036b4ec81200a [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "fuzz/Fuzz.h"
9#include "fuzz/FuzzCommon.h"
Kevin Lubickc3bac5b2023-09-25 08:43:57 -040010#include "include/codec/SkPngDecoder.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040011#include "include/core/SkBitmap.h"
Kevin Lubick87a2e792023-03-23 15:06:36 -040012#include "include/core/SkBlurTypes.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050013#include "include/core/SkCanvas.h"
14#include "include/core/SkColorFilter.h"
15#include "include/core/SkFontMgr.h"
16#include "include/core/SkImageFilter.h"
17#include "include/core/SkMaskFilter.h"
18#include "include/core/SkPathEffect.h"
19#include "include/core/SkPictureRecorder.h"
20#include "include/core/SkPoint3.h"
21#include "include/core/SkRSXform.h"
22#include "include/core/SkRegion.h"
23#include "include/core/SkSurface.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "include/core/SkTextBlob.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040025#include "include/core/SkTypeface.h"
26#include "include/core/SkVertices.h"
27#include "include/docs/SkPDFDocument.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050028#include "include/effects/Sk1DPathEffect.h"
29#include "include/effects/Sk2DPathEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "include/effects/SkCornerPathEffect.h"
31#include "include/effects/SkDashPathEffect.h"
32#include "include/effects/SkDiscretePathEffect.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050033#include "include/effects/SkGradientShader.h"
34#include "include/effects/SkHighContrastFilter.h"
Michael Ludwigef43f682019-08-01 16:38:46 -040035#include "include/effects/SkImageFilters.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050036#include "include/effects/SkLumaColorFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "include/effects/SkPerlinNoiseShader.h"
Kevin Lubickc3bac5b2023-09-25 08:43:57 -040038#include "include/encode/SkPngEncoder.h"
Kevin Lubick5c93acf2023-05-09 12:11:43 -040039#include "include/gpu/ganesh/SkSurfaceGanesh.h"
Kevin Lubick19936eb2023-01-05 09:00:37 -050040#include "include/private/base/SkTo.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040041#include "include/svg/SkSVGCanvas.h"
42#include "include/utils/SkNullCanvas.h"
Kevin Lubick1b3aa8b2023-01-19 14:03:31 -050043#include "src/base/SkUTF.h"
Kevin Lubicke5c37862023-10-16 17:21:15 -040044#include "src/core/SkFontPriv.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040045#include "src/core/SkOSFile.h"
46#include "src/core/SkPaintPriv.h"
47#include "src/core/SkPicturePriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050048#include "src/core/SkReadBuffer.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040049#include "src/utils/SkJSONWriter.h"
Kevin Lubick556ca8f2022-03-30 09:00:12 -040050#include "tools/UrlDataManager.h"
51#include "tools/debugger/DebugCanvas.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050052#include "tools/flags/CommandLineFlags.h"
Kevin Lubick1e971192023-11-10 16:14:44 -050053#include "tools/fonts/FontToolUtils.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050054
Kevin Lubick0f7b44e2023-02-28 09:13:11 -050055#if defined(SK_GANESH)
Robert Phillips7b4e43c2020-07-01 16:59:17 -040056#include "include/gpu/GrDirectContext.h"
Greg Daniel719239c2022-04-07 11:20:24 -040057#include "src/gpu/ganesh/GrDirectContextPriv.h"
Kevin Lubick94303e82022-02-01 09:03:41 -050058#include "tools/gpu/GrContextFactory.h"
59#endif
60
61#ifdef SK_GL
62#include "include/gpu/gl/GrGLFunctions.h"
Greg Daniel719239c2022-04-07 11:20:24 -040063#include "src/gpu/ganesh/gl/GrGLGpu.h"
64#include "src/gpu/ganesh/gl/GrGLUtil.h"
Hal Canary44801ca2017-03-15 11:39:06 -040065#endif
66
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050067#include <iostream>
Ben Wagnerf08d1d02018-06-18 15:11:00 -040068#include <utility>
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050069
Herb Derbyf7e2ca22022-11-30 10:10:49 -050070using namespace skia_private;
71
Mike Klein84836b72019-03-21 11:31:36 -050072static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
Kevin Lubickfaef5142018-06-07 10:33:11 -040073
Hal Canary24ac42b2017-02-14 13:35:14 -050074// TODO:
Hal Canary5395c592017-03-08 16:52:18 -050075// SkTextBlob with Unicode
Hal Canary44801ca2017-03-15 11:39:06 -040076// SkImage: more types
Hal Canary24ac42b2017-02-14 13:35:14 -050077
Hal Canary1e0138b2017-03-10 13:56:08 -050078// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
79// In fact, all make_fuzz_foo() functions have this potential problem.
80// Use sequence points!
81template <typename T>
82inline T make_fuzz_t(Fuzz* fuzz) {
83 T t;
84 fuzz->next(&t);
85 return t;
Hal Canary24ac42b2017-02-14 13:35:14 -050086}
87
Hal Canary1e0138b2017-03-10 13:56:08 -050088static sk_sp<SkImage> make_fuzz_image(Fuzz*);
Hal Canary671e4422017-02-27 13:36:38 -050089
Hal Canary1e0138b2017-03-10 13:56:08 -050090static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
Hal Canary671e4422017-02-27 13:36:38 -050091
Hal Canary1e0138b2017-03-10 13:56:08 -050092static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
Hal Canary27bece82017-03-07 16:23:20 -050093 if (depth <= 0) {
94 return nullptr;
95 }
96 int colorFilterType;
97 fuzz->nextRange(&colorFilterType, 0, 8);
98 switch (colorFilterType) {
99 case 0:
100 return nullptr;
101 case 1: {
102 SkColor color;
103 SkBlendMode mode;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400104 fuzz->next(&color);
Kevin Lubick00587e32019-06-03 11:27:16 -0400105 fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
Mike Reedb286bc22019-04-08 16:23:20 -0400106 return SkColorFilters::Blend(color, mode);
Hal Canary27bece82017-03-07 16:23:20 -0500107 }
108 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500109 sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500110 if (!outer) {
111 return nullptr;
112 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500113 sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
Kevin Lubick23888662018-02-21 08:07:26 -0500114 // makeComposed should be able to handle nullptr.
Mike Reed19d7bd62018-02-19 14:10:57 -0500115 return outer->makeComposed(std::move(inner));
Hal Canary27bece82017-03-07 16:23:20 -0500116 }
117 case 3: {
Mike Reede869a1e2019-04-30 12:18:54 -0400118 float array[20];
Herb Derbyafe25662022-06-16 14:50:33 -0400119 fuzz->nextN(array, std::size(array));
Mike Reede869a1e2019-04-30 12:18:54 -0400120 return SkColorFilters::Matrix(array);
Hal Canary27bece82017-03-07 16:23:20 -0500121 }
122 case 4: {
123 SkColor mul, add;
124 fuzz->next(&mul, &add);
Robert Phillips70ed99d2022-08-18 17:28:17 -0400125 return SkColorFilters::Lighting(mul, add);
Hal Canary27bece82017-03-07 16:23:20 -0500126 }
127 case 5: {
128 bool grayscale;
129 int invertStyle;
130 float contrast;
131 fuzz->next(&grayscale);
132 fuzz->nextRange(&invertStyle, 0, 2);
133 fuzz->nextRange(&contrast, -1.0f, 1.0f);
134 return SkHighContrastFilter::Make(SkHighContrastConfig(
135 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
136 }
137 case 6:
138 return SkLumaColorFilter::Make();
139 case 7: {
140 uint8_t table[256];
Herb Derbyafe25662022-06-16 14:50:33 -0400141 fuzz->nextN(table, std::size(table));
Robert Phillips70ed99d2022-08-18 17:28:17 -0400142 return SkColorFilters::Table(table);
Hal Canary27bece82017-03-07 16:23:20 -0500143 }
144 case 8: {
145 uint8_t tableA[256];
146 uint8_t tableR[256];
147 uint8_t tableG[256];
148 uint8_t tableB[256];
Herb Derbyafe25662022-06-16 14:50:33 -0400149 fuzz->nextN(tableA, std::size(tableA));
150 fuzz->nextN(tableR, std::size(tableR));
151 fuzz->nextN(tableG, std::size(tableG));
152 fuzz->nextN(tableB, std::size(tableB));
Robert Phillips70ed99d2022-08-18 17:28:17 -0400153 return SkColorFilters::TableARGB(tableA, tableR, tableG, tableB);
Hal Canary27bece82017-03-07 16:23:20 -0500154 }
Kevin Lubick54f20e02018-01-11 14:50:21 -0500155 default:
156 SkASSERT(false);
157 break;
Hal Canary27bece82017-03-07 16:23:20 -0500158 }
159 return nullptr;
160}
Hal Canary24ac42b2017-02-14 13:35:14 -0500161
Hal Canary1e0138b2017-03-10 13:56:08 -0500162static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500163 SkScalar totalPos = 0;
164 for (int i = 0; i < colorCount; ++i) {
165 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
166 totalPos += pos[i];
167 }
168 totalPos = 1.0f / totalPos;
169 for (int i = 0; i < colorCount; ++i) {
170 pos[i] *= totalPos;
171 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500172 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500173 pos[colorCount - 1] = 1.0f;
174}
175
Hal Canary1e0138b2017-03-10 13:56:08 -0500176static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500177 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
178 sk_sp<SkColorFilter> colorFilter(nullptr);
179 SkBitmap bitmap;
180 sk_sp<SkImage> img;
Mike Reedfae8fce2019-04-03 10:27:45 -0400181 SkTileMode tmX, tmY;
Hal Canary24ac42b2017-02-14 13:35:14 -0500182 bool useMatrix;
183 SkColor color;
184 SkMatrix matrix;
185 SkBlendMode blendMode;
186 int shaderType;
187 if (depth <= 0) {
188 return nullptr;
189 }
Hal Canary671e4422017-02-27 13:36:38 -0500190 fuzz->nextRange(&shaderType, 0, 14);
Hal Canary24ac42b2017-02-14 13:35:14 -0500191 switch (shaderType) {
192 case 0:
193 return nullptr;
194 case 1:
Mike Reedc8bea7d2019-04-09 13:55:36 -0400195 return SkShaders::Empty();
Hal Canary24ac42b2017-02-14 13:35:14 -0500196 case 2:
197 fuzz->next(&color);
Mike Reedc8bea7d2019-04-09 13:55:36 -0400198 return SkShaders::Color(color);
Hal Canary24ac42b2017-02-14 13:35:14 -0500199 case 3:
Hal Canary1e0138b2017-03-10 13:56:08 -0500200 img = make_fuzz_image(fuzz);
Kevin Lubick00587e32019-06-03 11:27:16 -0400201 fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
202 fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400203 fuzz->next(&useMatrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500204 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400205 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500206 }
Mike Reed99c94462020-12-08 13:16:56 -0500207 return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500208 case 5:
Hal Canary1e0138b2017-03-10 13:56:08 -0500209 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400210 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500211 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
212 case 6:
Hal Canary1e0138b2017-03-10 13:56:08 -0500213 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
214 colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -0500215 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
216 case 7:
Hal Canary1e0138b2017-03-10 13:56:08 -0500217 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
218 shader2 = make_fuzz_shader(fuzz, depth - 1);
Kevin Lubick00587e32019-06-03 11:27:16 -0400219 fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
Mike Reedc8bea7d2019-04-09 13:55:36 -0400220 return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
Hal Canaryb69c4b82017-03-08 11:02:40 -0500221 case 8: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500222 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500223 bool useTile;
224 SkRect tile;
Kevin Lubick00587e32019-06-03 11:27:16 -0400225 fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
226 fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400227 fuzz->next(&useMatrix, &useTile);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500228 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400229 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary671e4422017-02-27 13:36:38 -0500230 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500231 if (useTile) {
232 fuzz->next(&tile);
233 }
Mike Reed10a5ff22021-03-18 17:18:58 -0400234 return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
235 useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500236 }
Hal Canary671e4422017-02-27 13:36:38 -0500237 // EFFECTS:
Hal Canary24ac42b2017-02-14 13:35:14 -0500238 case 9:
Florin Malitabb3f5622017-05-31 14:20:12 +0000239 // Deprecated SkGaussianEdgeShader
240 return nullptr;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500241 case 10: {
242 constexpr int kMaxColors = 12;
243 SkPoint pts[2];
244 SkColor colors[kMaxColors];
245 SkScalar pos[kMaxColors];
246 int colorCount;
247 bool usePos;
248 fuzz->nextN(pts, 2);
249 fuzz->nextRange(&colorCount, 2, kMaxColors);
250 fuzz->nextN(colors, colorCount);
Kevin Lubick00587e32019-06-03 11:27:16 -0400251 fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400252 fuzz->next(&useMatrix, &usePos);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500253 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400254 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500255 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500256 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500257 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500258 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500259 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
260 tmX, 0, useMatrix ? &matrix : nullptr);
261 }
262 case 11: {
263 constexpr int kMaxColors = 12;
264 SkPoint center;
265 SkScalar radius;
266 int colorCount;
267 bool usePos;
268 SkColor colors[kMaxColors];
269 SkScalar pos[kMaxColors];
Kevin Lubick00587e32019-06-03 11:27:16 -0400270 fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400271 fuzz->next(&useMatrix, &usePos, &center, &radius);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500272 fuzz->nextRange(&colorCount, 2, kMaxColors);
273 fuzz->nextN(colors, colorCount);
274 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400275 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500276 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500277 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500278 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500279 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500280 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
281 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
282 }
283 case 12: {
284 constexpr int kMaxColors = 12;
285 SkPoint start, end;
286 SkScalar startRadius, endRadius;
287 int colorCount;
288 bool usePos;
289 SkColor colors[kMaxColors];
290 SkScalar pos[kMaxColors];
Kevin Lubick00587e32019-06-03 11:27:16 -0400291 fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400292 fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500293 fuzz->nextRange(&colorCount, 2, kMaxColors);
294 fuzz->nextN(colors, colorCount);
295 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400296 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500297 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500298 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500299 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500300 }
301 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
302 usePos ? pos : nullptr, colorCount, tmX, 0,
303 useMatrix ? &matrix : nullptr);
304 }
305 case 13: {
306 constexpr int kMaxColors = 12;
307 SkScalar cx, cy;
308 int colorCount;
309 bool usePos;
310 SkColor colors[kMaxColors];
311 SkScalar pos[kMaxColors];
312 fuzz->next(&cx, &cy, &useMatrix, &usePos);
313 fuzz->nextRange(&colorCount, 2, kMaxColors);
314 fuzz->nextN(colors, colorCount);
315 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400316 FuzzNiceMatrix(fuzz, &matrix);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500317 }
318 if (usePos) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500319 fuzz_gradient_stops(fuzz, pos, colorCount);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500320 }
321 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
322 0, useMatrix ? &matrix : nullptr);
323 }
324 case 14: {
325 SkScalar baseFrequencyX, baseFrequencyY, seed;
326 int numOctaves;
327 SkISize tileSize;
328 bool useTileSize, turbulence;
329 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
330 if (useTileSize) {
331 fuzz->next(&tileSize);
332 }
333 fuzz->nextRange(&numOctaves, 2, 7);
334 if (turbulence) {
Kevin Lubick8fdbbca2023-06-07 16:14:51 -0400335 return SkShaders::MakeTurbulence(baseFrequencyX,
336 baseFrequencyY,
337 numOctaves,
338 seed,
339 useTileSize ? &tileSize : nullptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500340 } else {
Kevin Lubick8fdbbca2023-06-07 16:14:51 -0400341 return SkShaders::MakeFractalNoise(baseFrequencyX,
342 baseFrequencyY,
343 numOctaves,
344 seed,
345 useTileSize ? &tileSize : nullptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500346 }
347 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500348 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -0500349 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -0500350 break;
351 }
Kevin Lubickedbeb8b2017-02-27 16:45:32 -0500352 return nullptr;
Hal Canary24ac42b2017-02-14 13:35:14 -0500353}
354
Hal Canary1e0138b2017-03-10 13:56:08 -0500355static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
Hal Canary5395c592017-03-08 16:52:18 -0500356 if (depth <= 0) {
357 return nullptr;
358 }
359 uint8_t pathEffectType;
Mike Reed40e7e652017-07-22 22:12:59 -0400360 fuzz->nextRange(&pathEffectType, 0, 8);
Hal Canary5395c592017-03-08 16:52:18 -0500361 switch (pathEffectType) {
362 case 0: {
363 return nullptr;
364 }
365 case 1: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500366 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
367 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500368 return SkPathEffect::MakeSum(std::move(first), std::move(second));
369 }
370 case 2: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500371 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
372 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -0500373 return SkPathEffect::MakeCompose(std::move(first), std::move(second));
374 }
375 case 3: {
376 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -0400377 FuzzNicePath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500378 SkScalar advance, phase;
379 fuzz->next(&advance, &phase);
Hal Canaryf7005202017-03-10 08:48:28 -0500380 SkPath1DPathEffect::Style style;
Kevin Lubick00587e32019-06-03 11:27:16 -0400381 fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
Hal Canaryf7005202017-03-10 08:48:28 -0500382 return SkPath1DPathEffect::Make(path, advance, phase, style);
Hal Canary5395c592017-03-08 16:52:18 -0500383 }
384 case 4: {
385 SkScalar width;
386 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400387 fuzz->next(&width);
388 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary5395c592017-03-08 16:52:18 -0500389 return SkLine2DPathEffect::Make(width, matrix);
390 }
391 case 5: {
392 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -0400393 FuzzNicePath(fuzz, &path, 20);
Hal Canary5395c592017-03-08 16:52:18 -0500394 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400395 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary5395c592017-03-08 16:52:18 -0500396 return SkPath2DPathEffect::Make(matrix, path);
397 }
398 case 6: {
399 SkScalar radius;
400 fuzz->next(&radius);
Hal Canary5395c592017-03-08 16:52:18 -0500401 return SkCornerPathEffect::Make(radius);
402 }
Mike Reed40e7e652017-07-22 22:12:59 -0400403 case 7: {
Hal Canary5395c592017-03-08 16:52:18 -0500404 SkScalar phase;
405 fuzz->next(&phase);
406 SkScalar intervals[20];
407 int count;
Herb Derbyafe25662022-06-16 14:50:33 -0400408 fuzz->nextRange(&count, 0, (int)std::size(intervals));
Hal Canary5395c592017-03-08 16:52:18 -0500409 fuzz->nextN(intervals, count);
410 return SkDashPathEffect::Make(intervals, count, phase);
411 }
Mike Reed40e7e652017-07-22 22:12:59 -0400412 case 8: {
Hal Canary5395c592017-03-08 16:52:18 -0500413 SkScalar segLength, dev;
414 uint32_t seed;
415 fuzz->next(&segLength, &dev, &seed);
416 return SkDiscretePathEffect::Make(segLength, dev, seed);
417 }
418 default:
419 SkASSERT(false);
420 return nullptr;
421 }
422}
Hal Canary24ac42b2017-02-14 13:35:14 -0500423
Hal Canary1e0138b2017-03-10 13:56:08 -0500424static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
Hal Canary5395c592017-03-08 16:52:18 -0500425 int maskfilterType;
Robert Phillipsab4f5bd2018-04-18 10:05:00 -0400426 fuzz->nextRange(&maskfilterType, 0, 1);
Hal Canary5395c592017-03-08 16:52:18 -0500427 switch (maskfilterType) {
428 case 0:
429 return nullptr;
430 case 1: {
Hal Canaryf7005202017-03-10 08:48:28 -0500431 SkBlurStyle blurStyle;
Kevin Lubick00587e32019-06-03 11:27:16 -0400432 fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
Hal Canary5395c592017-03-08 16:52:18 -0500433 SkScalar sigma;
434 fuzz->next(&sigma);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400435 bool respectCTM;
436 fuzz->next(&respectCTM);
Kevin Lubick1b1a5572018-06-04 17:02:46 -0400437 return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
Hal Canary5395c592017-03-08 16:52:18 -0500438 }
Hal Canary5395c592017-03-08 16:52:18 -0500439 default:
440 SkASSERT(false);
441 return nullptr;
442 }
443}
Hal Canary24ac42b2017-02-14 13:35:14 -0500444
Hal Canary1e0138b2017-03-10 13:56:08 -0500445static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
446 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary671e4422017-02-27 13:36:38 -0500447 return nullptr;
448 }
Kevin Lubick1e971192023-11-10 16:14:44 -0500449 sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr();
450 int familyCount = mgr->countFamilies();
Hal Canary671e4422017-02-27 13:36:38 -0500451 int i, j;
452 fuzz->nextRange(&i, 0, familyCount - 1);
Kevin Lubick1e971192023-11-10 16:14:44 -0500453 sk_sp<SkFontStyleSet> family(mgr->createStyleSet(i));
Hal Canary671e4422017-02-27 13:36:38 -0500454 int styleCount = family->count();
455 fuzz->nextRange(&j, 0, styleCount - 1);
456 return sk_sp<SkTypeface>(family->createTypeface(j));
457}
Hal Canary24ac42b2017-02-14 13:35:14 -0500458
Hal Canary1e0138b2017-03-10 13:56:08 -0500459static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500460
461static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
462 if (depth <= 0) {
463 return nullptr;
464 }
465 uint8_t imageFilterType;
466 fuzz->nextRange(&imageFilterType, 1, 6);
467 SkPoint3 p, q;
468 SkColor lightColor;
469 SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
470 sk_sp<SkImageFilter> input;
Michael Ludwigef43f682019-08-01 16:38:46 -0400471 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500472 bool useCropRect;
473 fuzz->next(&useCropRect);
474 if (useCropRect) {
475 fuzz->next(&cropRect);
476 }
477 switch (imageFilterType) {
478 case 1:
479 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500480 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400481 return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
482 std::move(input),
483 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500484 case 2:
485 fuzz->next(&p, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500486 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400487 return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
488 std::move(input),
489 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500490 case 3:
491 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
Hal Canary1e0138b2017-03-10 13:56:08 -0500492 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400493 return SkImageFilters::SpotLitDiffuse(
Hal Canarye03c3e52017-03-09 11:33:35 -0500494 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
495 std::move(input), useCropRect ? &cropRect : nullptr);
496 case 4:
497 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500498 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400499 return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
500 shininess, std::move(input),
501 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500502 case 5:
503 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500504 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400505 return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
506 shininess, std::move(input),
507 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500508 case 6:
509 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
510 &shininess);
Hal Canary1e0138b2017-03-10 13:56:08 -0500511 input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400512 return SkImageFilters::SpotLitSpecular(
Hal Canarye03c3e52017-03-09 11:33:35 -0500513 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
514 std::move(input), useCropRect ? &cropRect : nullptr);
515 default:
516 SkASSERT(false);
517 return nullptr;
518 }
519}
520
Hal Canary1e0138b2017-03-10 13:56:08 -0500521static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
Hal Canarye03c3e52017-03-09 11:33:35 -0500522
Mike Reed1f261da2021-07-18 10:54:25 -0400523static SkSamplingOptions next_sampling(Fuzz* fuzz) {
524 if (fuzz->nextBool()) {
525 float B, C;
526 fuzz->next(&B, &C);
527 return SkSamplingOptions({B, C});
528 } else {
529 SkFilterMode fm;
530 SkMipmapMode mm;
531 fuzz->nextEnum(&fm, SkFilterMode::kLast);
532 fuzz->nextEnum(&mm, SkMipmapMode::kLast);
533 return SkSamplingOptions(fm, mm);
534 }
535}
536
Hal Canary1e0138b2017-03-10 13:56:08 -0500537static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
Hal Canarye03c3e52017-03-09 11:33:35 -0500538 if (depth <= 0) {
539 return nullptr;
540 }
541 uint8_t imageFilterType;
Brian Osman78781102023-06-20 15:21:21 +0000542 fuzz->nextRange(&imageFilterType, 0, 22);
Hal Canarye03c3e52017-03-09 11:33:35 -0500543 switch (imageFilterType) {
544 case 0:
545 return nullptr;
546 case 1: {
547 SkScalar sigmaX, sigmaY;
Hal Canary1e0138b2017-03-10 13:56:08 -0500548 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500549 bool useCropRect;
550 fuzz->next(&sigmaX, &sigmaY, &useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400551 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500552 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400553 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500554 }
Michael Ludwigef43f682019-08-01 16:38:46 -0400555 return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
556 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500557 }
558 case 2: {
559 SkMatrix matrix;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400560 FuzzNiceMatrix(fuzz, &matrix);
Mike Reed1f261da2021-07-18 10:54:25 -0400561 const auto sampling = next_sampling(fuzz);
Hal Canary1e0138b2017-03-10 13:56:08 -0500562 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Mike Reed92236652021-02-01 13:07:32 -0500563 return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
Hal Canarye03c3e52017-03-09 11:33:35 -0500564 }
565 case 3: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500566 float k1, k2, k3, k4;
567 bool enforcePMColor;
568 bool useCropRect;
569 fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500570 sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
571 sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400572 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500573 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400574 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500575 }
Michael Ludwigef43f682019-08-01 16:38:46 -0400576 return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
577 std::move(background), std::move(foreground),
578 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500579 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400580 case 4: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500581 sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
582 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500583 bool useCropRect;
Michael Ludwigef43f682019-08-01 16:38:46 -0400584 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500585 fuzz->next(&useCropRect);
586 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400587 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500588 }
Michael Ludwigef43f682019-08-01 16:38:46 -0400589 return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
590 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500591 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400592 case 5: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500593 sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
594 sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400595 return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
Hal Canarye03c3e52017-03-09 11:33:35 -0500596 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400597 case 6: {
Michael Ludwigef43f682019-08-01 16:38:46 -0400598 SkColorChannel xChannelSelector, yChannelSelector;
599 fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
600 fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
Hal Canarye03c3e52017-03-09 11:33:35 -0500601 SkScalar scale;
602 bool useCropRect;
603 fuzz->next(&scale, &useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400604 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500605 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400606 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500607 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500608 sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
609 sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400610 return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
611 std::move(displacement), std::move(color),
612 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500613 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400614 case 7: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500615 SkScalar dx, dy, sigmaX, sigmaY;
616 SkColor color;
Michael Ludwigef43f682019-08-01 16:38:46 -0400617 bool shadowOnly, useCropRect;
618 fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
619 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500620 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400621 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500622 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500623 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400624 if (shadowOnly) {
625 return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
626 std::move(input),
627 useCropRect ? &cropRect : nullptr);
628 } else {
629 return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
630 useCropRect ? &cropRect : nullptr);
631 }
Hal Canarye03c3e52017-03-09 11:33:35 -0500632 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400633 case 8:
Michael Ludwig642f2182023-05-30 20:57:39 -0400634 return SkImageFilters::Image(make_fuzz_image(fuzz), SkCubicResampler::Mitchell());
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400635 case 9: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500636 sk_sp<SkImage> image = make_fuzz_image(fuzz);
Hal Canarye03c3e52017-03-09 11:33:35 -0500637 SkRect srcRect, dstRect;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400638 fuzz->next(&srcRect, &dstRect);
Mike Reed1f261da2021-07-18 10:54:25 -0400639 return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
Hal Canarye03c3e52017-03-09 11:33:35 -0500640 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400641 case 10:
Hal Canarye03c3e52017-03-09 11:33:35 -0500642 return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400643 case 11: {
Michael Ludwig0dc9e8d2023-05-02 16:23:56 -0400644 SkRect lensBounds;
645 SkScalar zoomAmount;
Hal Canarye03c3e52017-03-09 11:33:35 -0500646 SkScalar inset;
647 bool useCropRect;
Michael Ludwigef43f682019-08-01 16:38:46 -0400648 SkIRect cropRect;
Michael Ludwig0dc9e8d2023-05-02 16:23:56 -0400649 fuzz->next(&lensBounds, &zoomAmount, &inset, &useCropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500650 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400651 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500652 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500653 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwig0dc9e8d2023-05-02 16:23:56 -0400654 const auto sampling = next_sampling(fuzz);
655 return SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling,
656 std::move(input), useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500657 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400658 case 12: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500659 constexpr int kMaxKernelSize = 5;
660 int32_t n, m;
661 fuzz->nextRange(&n, 1, kMaxKernelSize);
662 fuzz->nextRange(&m, 1, kMaxKernelSize);
663 SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
664 fuzz->nextN(kernel, n * m);
665 int32_t offsetX, offsetY;
666 fuzz->nextRange(&offsetX, 0, n - 1);
667 fuzz->nextRange(&offsetY, 0, m - 1);
668 SkScalar gain, bias;
669 bool convolveAlpha, useCropRect;
670 fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400671 SkTileMode tileMode;
672 fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
673 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500674 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400675 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500676 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500677 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400678 return SkImageFilters::MatrixConvolution(
Hal Canarye03c3e52017-03-09 11:33:35 -0500679 SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
680 convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
681 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400682 case 13: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500683 sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
684 sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canarye03c3e52017-03-09 11:33:35 -0500685 bool useCropRect;
686 fuzz->next(&useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400687 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500688 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400689 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500690 }
Michael Ludwigef43f682019-08-01 16:38:46 -0400691 return SkImageFilters::Merge(std::move(first), std::move(second),
692 useCropRect ? &cropRect : nullptr);
Mike Reed0bdaf052017-06-18 23:35:57 -0400693 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400694 case 14: {
Mike Reed0bdaf052017-06-18 23:35:57 -0400695 constexpr int kMaxCount = 4;
696 sk_sp<SkImageFilter> ifs[kMaxCount];
697 int count;
698 fuzz->nextRange(&count, 1, kMaxCount);
699 for (int i = 0; i < count; ++i) {
700 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
701 }
702 bool useCropRect;
703 fuzz->next(&useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400704 SkIRect cropRect;
Mike Reed0bdaf052017-06-18 23:35:57 -0400705 if (useCropRect) {
706 fuzz->next(&cropRect);
707 }
Michael Ludwigef43f682019-08-01 16:38:46 -0400708 return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500709 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400710 case 15: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500711 int rx, ry;
712 fuzz->next(&rx, &ry);
713 bool useCropRect;
714 fuzz->next(&useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400715 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500716 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400717 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500718 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500719 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400720 return SkImageFilters::Dilate(rx, ry, std::move(input),
721 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500722 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400723 case 16: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500724 int rx, ry;
725 fuzz->next(&rx, &ry);
726 bool useCropRect;
727 fuzz->next(&useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400728 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500729 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400730 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500731 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500732 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400733 return SkImageFilters::Erode(rx, ry, std::move(input),
734 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500735 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400736 case 17: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500737 SkScalar dx, dy;
738 fuzz->next(&dx, &dy);
739 bool useCropRect;
740 fuzz->next(&useCropRect);
Michael Ludwigef43f682019-08-01 16:38:46 -0400741 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500742 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400743 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500744 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500745 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400746 return SkImageFilters::Offset(dx, dy, std::move(input),
747 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500748 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400749 case 18: {
Hal Canary1e0138b2017-03-10 13:56:08 -0500750 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400751 return SkImageFilters::Picture(std::move(picture));
Hal Canarye03c3e52017-03-09 11:33:35 -0500752 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400753 case 19: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500754 SkRect cropRect;
755 fuzz->next(&cropRect);
Hal Canary1e0138b2017-03-10 13:56:08 -0500756 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400757 return SkImageFilters::Picture(std::move(picture), cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500758 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400759 case 20: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500760 SkRect src, dst;
761 fuzz->next(&src, &dst);
Hal Canary1e0138b2017-03-10 13:56:08 -0500762 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwigef43f682019-08-01 16:38:46 -0400763 return SkImageFilters::Tile(src, dst, std::move(input));
Hal Canarye03c3e52017-03-09 11:33:35 -0500764 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400765 case 21: {
Hal Canarye03c3e52017-03-09 11:33:35 -0500766 SkBlendMode blendMode;
767 bool useCropRect;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -0400768 fuzz->next(&useCropRect);
Kevin Lubick00587e32019-06-03 11:27:16 -0400769 fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
Michael Ludwigef43f682019-08-01 16:38:46 -0400770 SkIRect cropRect;
Hal Canarye03c3e52017-03-09 11:33:35 -0500771 if (useCropRect) {
Kevin Lubickdad29a02017-03-14 17:20:24 -0400772 fuzz->next(&cropRect);
Hal Canarye03c3e52017-03-09 11:33:35 -0500773 }
Hal Canary1e0138b2017-03-10 13:56:08 -0500774 sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
775 sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
Michael Ludwig01b93ea2020-10-09 10:45:07 -0400776 return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
777 useCropRect ? &cropRect : nullptr);
Hal Canarye03c3e52017-03-09 11:33:35 -0500778 }
Michael Ludwig0092c0a2023-06-09 16:06:58 -0400779 case 22: {
Michael Ludwig7d0f8532020-10-07 15:27:20 -0400780 sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
781 bool useCropRect;
782 fuzz->next(&useCropRect);
783 SkIRect cropRect;
784 if (useCropRect) {
785 fuzz->next(&cropRect);
786 }
787 return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
788 }
Hal Canarye03c3e52017-03-09 11:33:35 -0500789 default:
790 SkASSERT(false);
791 return nullptr;
792 }
793}
Hal Canary24ac42b2017-02-14 13:35:14 -0500794
Hal Canary1e0138b2017-03-10 13:56:08 -0500795static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500796 int w, h;
797 fuzz->nextRange(&w, 1, 1024);
798 fuzz->nextRange(&h, 1, 1024);
Herb Derbyf7e2ca22022-11-30 10:10:49 -0500799 AutoTMalloc<SkPMColor> data(w * h);
Hal Canary24ac42b2017-02-14 13:35:14 -0500800 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
801 int n = w * h;
802 for (int i = 0; i < n; ++i) {
803 SkColor c;
804 fuzz->next(&c);
805 data[i] = SkPreMultiplyColor(c);
806 }
807 (void)data.release();
Kevin Lubick77472bf2023-03-24 07:11:17 -0400808 return SkImages::RasterFromPixmap(
Brian Osmanc9943f12023-11-17 16:39:23 -0500809 pixmap, [](const void* p, void*) { sk_free(const_cast<void*>(p)); }, nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500810}
811
Kevin Lubick00587e32019-06-03 11:27:16 -0400812template <typename T>
813static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500814 T value;
Kevin Lubick00587e32019-06-03 11:27:16 -0400815 fuzz->nextEnum(&value, maxv);
Hal Canary1e0138b2017-03-10 13:56:08 -0500816 return value;
817}
818
819static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500820 if (!fuzz || !paint || depth <= 0) {
821 return;
822 }
823
Hal Canary1e0138b2017-03-10 13:56:08 -0500824 paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
825 paint->setDither( make_fuzz_t<bool>(fuzz));
826 paint->setColor( make_fuzz_t<SkColor>(fuzz));
Kevin Lubick00587e32019-06-03 11:27:16 -0400827 paint->setBlendMode( make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
Kevin Lubick00587e32019-06-03 11:27:16 -0400828 paint->setStyle( make_fuzz_enum_range<SkPaint::Style>(fuzz,
829 SkPaint::Style::kStrokeAndFill_Style));
Hal Canary1e0138b2017-03-10 13:56:08 -0500830 paint->setShader( make_fuzz_shader(fuzz, depth - 1));
831 paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
832 paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
833 paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
834 paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
Hal Canary24ac42b2017-02-14 13:35:14 -0500835
836 if (paint->getStyle() != SkPaint::kFill_Style) {
Hal Canary1e0138b2017-03-10 13:56:08 -0500837 paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
838 paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
Kevin Lubick00587e32019-06-03 11:27:16 -0400839 paint->setStrokeCap( make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
840 paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
Hal Canary24ac42b2017-02-14 13:35:14 -0500841 }
842}
843
Mike Reed358fcad2018-11-23 15:27:51 -0500844static SkFont fuzz_font(Fuzz* fuzz) {
845 SkFont font;
846 font.setTypeface( make_fuzz_typeface(fuzz));
847 font.setSize( make_fuzz_t<SkScalar>(fuzz));
848 font.setScaleX( make_fuzz_t<SkScalar>(fuzz));
849 font.setSkewX( make_fuzz_t<SkScalar>(fuzz));
850 font.setLinearMetrics( make_fuzz_t<bool>(fuzz));
851 font.setSubpixel( make_fuzz_t<bool>(fuzz));
852 font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
853 font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
854 font.setEmbolden( make_fuzz_t<bool>(fuzz));
Kevin Lubick00587e32019-06-03 11:27:16 -0400855 font.setHinting( make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
856 font.setEdging( make_fuzz_enum_range<SkFont::Edging>(fuzz,
857 SkFont::Edging::kSubpixelAntiAlias));
Mike Reed358fcad2018-11-23 15:27:51 -0500858 return font;
Hal Canary5395c592017-03-08 16:52:18 -0500859}
860
Mike Reed2ed78202018-11-21 15:10:08 -0500861static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
Kevin Lubick00587e32019-06-03 11:27:16 -0400862 return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
Hal Canary24ac42b2017-02-14 13:35:14 -0500863}
864
Hal Canary5395c592017-03-08 16:52:18 -0500865constexpr int kMaxGlyphCount = 30;
866
Mike Reed2ed78202018-11-21 15:10:08 -0500867static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
Hal Canary671e4422017-02-27 13:36:38 -0500868 SkTDArray<uint8_t> array;
Ben Wagner51e15a62019-05-07 15:38:46 -0400869 if (SkTextEncoding::kGlyphID == encoding) {
Kevin Lubickb696ca22023-12-11 11:16:16 -0500870 int glyphRange = font.getTypeface()->countGlyphs();
Kevin Lubick1991f552018-02-27 10:59:10 -0500871 if (glyphRange == 0) {
872 // Some fuzzing environments have no fonts, so empty array is the best
873 // we can do.
874 return array;
875 }
Hal Canary671e4422017-02-27 13:36:38 -0500876 int glyphCount;
Hal Canary5395c592017-03-08 16:52:18 -0500877 fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
Hal Canary671e4422017-02-27 13:36:38 -0500878 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
879 for (int i = 0; i < glyphCount; ++i) {
880 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
881 }
882 return array;
883 }
884 static const SkUnichar ranges[][2] = {
885 {0x0020, 0x007F},
886 {0x00A1, 0x0250},
887 {0x0400, 0x0500},
888 };
889 int32_t count = 0;
Herb Derbyafe25662022-06-16 14:50:33 -0400890 for (size_t i = 0; i < std::size(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500891 count += (ranges[i][1] - ranges[i][0]);
892 }
Hal Canary5395c592017-03-08 16:52:18 -0500893 constexpr int kMaxLength = kMaxGlyphCount;
Hal Canary671e4422017-02-27 13:36:38 -0500894 SkUnichar buffer[kMaxLength];
895 int length;
896 fuzz->nextRange(&length, 1, kMaxLength);
897 for (int j = 0; j < length; ++j) {
898 int32_t value;
899 fuzz->nextRange(&value, 0, count - 1);
Herb Derbyafe25662022-06-16 14:50:33 -0400900 for (size_t i = 0; i < std::size(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500901 if (value + ranges[i][0] < ranges[i][1]) {
902 buffer[j] = value + ranges[i][0];
903 break;
904 } else {
905 value -= (ranges[i][1] - ranges[i][0]);
906 }
907 }
908 }
Mike Reed2ed78202018-11-21 15:10:08 -0500909 switch (encoding) {
Ben Wagner51e15a62019-05-07 15:38:46 -0400910 case SkTextEncoding::kUTF8: {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500911 size_t utf8len = 0;
912 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400913 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
Hal Canary671e4422017-02-27 13:36:38 -0500914 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500915 char* ptr = (char*)array.append(utf8len);
916 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400917 ptr += SkUTF::ToUTF8(buffer[j], ptr);
Hal Canary671e4422017-02-27 13:36:38 -0500918 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500919 } break;
Ben Wagner51e15a62019-05-07 15:38:46 -0400920 case SkTextEncoding::kUTF16: {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500921 size_t utf16len = 0;
922 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400923 utf16len += SkUTF::ToUTF16(buffer[j]);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500924 }
925 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
926 for (int j = 0; j < length; ++j) {
Hal Canaryf107a2f2018-07-25 16:52:48 -0400927 ptr += SkUTF::ToUTF16(buffer[j], ptr);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500928 }
929 } break;
Ben Wagner51e15a62019-05-07 15:38:46 -0400930 case SkTextEncoding::kUTF32:
Hal Canary671e4422017-02-27 13:36:38 -0500931 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
Hal Canaryc1a70e22017-03-01 15:40:46 -0500932 break;
Hal Canary671e4422017-02-27 13:36:38 -0500933 default:
Hal Canaryb69c4b82017-03-08 11:02:40 -0500934 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -0500935 break;
Hal Canary671e4422017-02-27 13:36:38 -0500936 }
937 return array;
938}
939
Zepeng Huba7cbf72020-07-01 13:21:03 +0000940static std::string make_fuzz_string(Fuzz* fuzz) {
941 int len;
942 fuzz->nextRange(&len, 0, kMaxGlyphCount);
943 std::string str(len, 0);
944 for (int i = 0; i < len; i++) {
945 fuzz->next(&str[i]);
946 }
947 return str;
948}
949
Hal Canary5395c592017-03-08 16:52:18 -0500950static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
951 SkTextBlobBuilder textBlobBuilder;
952 int8_t runCount;
953 fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
954 while (runCount-- > 0) {
Kevin Lubick4631c542023-12-08 15:45:45 -0500955 SkFont font = ToolUtils::DefaultFont();
Mike Reed2ed78202018-11-21 15:10:08 -0500956 SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
957 font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
958 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
Herb Derby3050ef52022-09-29 21:12:37 -0400959 int glyphCount = font.countText(text.begin(), SkToSizeT(text.size()), encoding);
Hal Canary5395c592017-03-08 16:52:18 -0500960 SkASSERT(glyphCount <= kMaxGlyphCount);
961 SkScalar x, y;
962 const SkTextBlobBuilder::RunBuffer* buffer;
963 uint8_t runType;
964 fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
Hal Canaryfc97f222018-12-17 13:48:44 -0500965 const void* textPtr = text.begin();
Herb Derby3050ef52022-09-29 21:12:37 -0400966 size_t textLen = SkToSizeT(text.size());
Hal Canary5395c592017-03-08 16:52:18 -0500967 switch (runType) {
968 case 0:
969 fuzz->next(&x, &y);
970 // TODO: Test other variations of this.
Mike Reed2ed78202018-11-21 15:10:08 -0500971 buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
Hal Canaryfc97f222018-12-17 13:48:44 -0500972 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
Hal Canary5395c592017-03-08 16:52:18 -0500973 break;
974 case 1:
975 fuzz->next(&y);
976 // TODO: Test other variations of this.
Mike Reed2ed78202018-11-21 15:10:08 -0500977 buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
Hal Canaryfc97f222018-12-17 13:48:44 -0500978 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
Hal Canary5395c592017-03-08 16:52:18 -0500979 fuzz->nextN(buffer->pos, glyphCount);
980 break;
981 case 2:
982 // TODO: Test other variations of this.
Mike Reed2ed78202018-11-21 15:10:08 -0500983 buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
Hal Canaryfc97f222018-12-17 13:48:44 -0500984 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
Hal Canary5395c592017-03-08 16:52:18 -0500985 fuzz->nextN(buffer->pos, glyphCount * 2);
986 break;
987 default:
988 SkASSERT(false);
Kevin Lubick54f20e02018-01-11 14:50:21 -0500989 break;
Hal Canary5395c592017-03-08 16:52:18 -0500990 }
991 }
992 return textBlobBuilder.make();
993}
994
Hal Canary1e0138b2017-03-10 13:56:08 -0500995static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500996 if (!fuzz || !canvas || depth <= 0) {
997 return;
998 }
999 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1000 unsigned N;
1001 fuzz->nextRange(&N, 0, 2000);
John Stiles13c9f662021-08-16 12:16:29 -04001002 for (unsigned loop = 0; loop < N; ++loop) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001003 if (fuzz->exhausted()) {
1004 return;
1005 }
1006 SkPaint paint;
Kevin Lubick4631c542023-12-08 15:45:45 -05001007 SkFont font = ToolUtils::DefaultFont();
Hal Canary24ac42b2017-02-14 13:35:14 -05001008 unsigned drawCommand;
Zepeng Huba7cbf72020-07-01 13:21:03 +00001009 fuzz->nextRange(&drawCommand, 0, 62);
Hal Canary24ac42b2017-02-14 13:35:14 -05001010 switch (drawCommand) {
1011 case 0:
Kevin Lubickedb06e12023-06-28 08:27:51 -04001012#if defined(SK_GANESH)
1013 if (auto dContext = GrAsDirectContext(canvas->recordingContext())) {
1014 dContext->flushAndSubmit();
1015 }
1016#endif
Hal Canary24ac42b2017-02-14 13:35:14 -05001017 break;
1018 case 1:
1019 canvas->save();
1020 break;
1021 case 2: {
1022 SkRect bounds;
1023 fuzz->next(&bounds);
Hal Canary1e0138b2017-03-10 13:56:08 -05001024 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001025 canvas->saveLayer(&bounds, &paint);
1026 break;
1027 }
1028 case 3: {
1029 SkRect bounds;
1030 fuzz->next(&bounds);
1031 canvas->saveLayer(&bounds, nullptr);
1032 break;
1033 }
1034 case 4:
Hal Canary1e0138b2017-03-10 13:56:08 -05001035 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001036 canvas->saveLayer(nullptr, &paint);
1037 break;
1038 case 5:
1039 canvas->saveLayer(nullptr, nullptr);
1040 break;
1041 case 6: {
1042 uint8_t alpha;
1043 fuzz->next(&alpha);
1044 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1045 break;
1046 }
1047 case 7: {
1048 SkRect bounds;
1049 uint8_t alpha;
1050 fuzz->next(&bounds, &alpha);
1051 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1052 break;
1053 }
1054 case 8: {
1055 SkCanvas::SaveLayerRec saveLayerRec;
1056 SkRect bounds;
Hal Canary1e0138b2017-03-10 13:56:08 -05001057 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001058 fuzz->next(&bounds);
1059 saveLayerRec.fBounds = &bounds;
1060 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001061 if (make_fuzz_t<bool>(fuzz)) {
1062 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001063 saveLayerRec.fPaint = &paint;
1064 }
1065 sk_sp<SkImageFilter> imageFilter;
Hal Canary1e0138b2017-03-10 13:56:08 -05001066 if (make_fuzz_t<bool>(fuzz)) {
1067 imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001068 saveLayerRec.fBackdrop = imageFilter.get();
1069 }
Hal Canary5395c592017-03-08 16:52:18 -05001070 // _DumpCanvas can't handle this.
Hal Canary1e0138b2017-03-10 13:56:08 -05001071 // if (make_fuzz_t<bool>(fuzz)) {
Hal Canary5395c592017-03-08 16:52:18 -05001072 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1073 // }
1074
Hal Canary24ac42b2017-02-14 13:35:14 -05001075 canvas->saveLayer(saveLayerRec);
1076 break;
1077 }
1078 case 9:
1079 canvas->restore();
1080 break;
1081 case 10: {
1082 int saveCount;
1083 fuzz->next(&saveCount);
1084 canvas->restoreToCount(saveCount);
1085 break;
1086 }
1087 case 11: {
1088 SkScalar x, y;
1089 fuzz->next(&x, &y);
1090 canvas->translate(x, y);
1091 break;
1092 }
1093 case 12: {
1094 SkScalar x, y;
1095 fuzz->next(&x, &y);
1096 canvas->scale(x, y);
1097 break;
1098 }
1099 case 13: {
1100 SkScalar v;
1101 fuzz->next(&v);
1102 canvas->rotate(v);
1103 break;
1104 }
1105 case 14: {
1106 SkScalar x, y, v;
1107 fuzz->next(&x, &y, &v);
1108 canvas->rotate(v, x, y);
1109 break;
1110 }
1111 case 15: {
1112 SkScalar x, y;
1113 fuzz->next(&x, &y);
1114 canvas->skew(x, y);
1115 break;
1116 }
1117 case 16: {
1118 SkMatrix mat;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001119 FuzzNiceMatrix(fuzz, &mat);
Hal Canary24ac42b2017-02-14 13:35:14 -05001120 canvas->concat(mat);
1121 break;
1122 }
1123 case 17: {
1124 SkMatrix mat;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001125 FuzzNiceMatrix(fuzz, &mat);
Hal Canary24ac42b2017-02-14 13:35:14 -05001126 canvas->setMatrix(mat);
1127 break;
1128 }
1129 case 18:
1130 canvas->resetMatrix();
1131 break;
1132 case 19: {
1133 SkRect r;
1134 int op;
1135 bool doAntiAlias;
1136 fuzz->next(&r, &doAntiAlias);
1137 fuzz->nextRange(&op, 0, 1);
1138 r.sort();
1139 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1140 break;
1141 }
1142 case 20: {
1143 SkRRect rr;
1144 int op;
1145 bool doAntiAlias;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001146 FuzzNiceRRect(fuzz, &rr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001147 fuzz->next(&doAntiAlias);
1148 fuzz->nextRange(&op, 0, 1);
1149 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1150 break;
1151 }
1152 case 21: {
1153 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001154 FuzzNicePath(fuzz, &path, 30);
Hal Canary24ac42b2017-02-14 13:35:14 -05001155 int op;
1156 bool doAntiAlias;
1157 fuzz->next(&doAntiAlias);
1158 fuzz->nextRange(&op, 0, 1);
1159 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1160 break;
1161 }
1162 case 22: {
1163 SkRegion region;
Hal Canary24ac42b2017-02-14 13:35:14 -05001164 int op;
Hal Canarye03c3e52017-03-09 11:33:35 -05001165 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001166 fuzz->nextRange(&op, 0, 1);
1167 canvas->clipRegion(region, (SkClipOp)op);
1168 break;
1169 }
1170 case 23:
Hal Canary1e0138b2017-03-10 13:56:08 -05001171 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001172 canvas->drawPaint(paint);
1173 break;
1174 case 24: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001175 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001176 SkCanvas::PointMode pointMode;
Mike Kleinf88f5ef2018-11-19 12:21:46 -05001177 fuzz->nextRange(&pointMode,
Hal Canaryc8bebd42017-12-20 11:21:05 -05001178 SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001179 size_t count;
1180 constexpr int kMaxCount = 30;
1181 fuzz->nextRange(&count, 0, kMaxCount);
1182 SkPoint pts[kMaxCount];
1183 fuzz->nextN(pts, count);
Hal Canaryc8bebd42017-12-20 11:21:05 -05001184 canvas->drawPoints(pointMode, count, pts, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001185 break;
1186 }
1187 case 25: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001188 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001189 SkRect r;
1190 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001191 if (!r.isFinite()) {
1192 break;
1193 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001194 canvas->drawRect(r, paint);
1195 break;
1196 }
1197 case 26: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001198 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001199 SkRegion region;
Hal Canarye03c3e52017-03-09 11:33:35 -05001200 fuzz->next(&region);
Hal Canary24ac42b2017-02-14 13:35:14 -05001201 canvas->drawRegion(region, paint);
1202 break;
1203 }
1204 case 27: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001205 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001206 SkRect r;
1207 fuzz->next(&r);
Kevin Lubickc5f04272018-04-05 12:54:00 -04001208 if (!r.isFinite()) {
1209 break;
1210 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001211 canvas->drawOval(r, paint);
1212 break;
1213 }
Mike Reed9cec1bc2018-01-19 12:57:01 -05001214 case 28: break; // must have deleted this some time earlier
Hal Canary24ac42b2017-02-14 13:35:14 -05001215 case 29: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001216 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001217 SkRRect rr;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001218 FuzzNiceRRect(fuzz, &rr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001219 canvas->drawRRect(rr, paint);
1220 break;
1221 }
1222 case 30: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001223 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001224 SkRRect orr, irr;
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001225 FuzzNiceRRect(fuzz, &orr);
1226 FuzzNiceRRect(fuzz, &irr);
Hal Canary27bece82017-03-07 16:23:20 -05001227 if (orr.getBounds().contains(irr.getBounds())) {
1228 canvas->drawDRRect(orr, irr, paint);
1229 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001230 break;
1231 }
1232 case 31: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001233 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001234 SkRect r;
1235 SkScalar start, sweep;
1236 bool useCenter;
1237 fuzz->next(&r, &start, &sweep, &useCenter);
1238 canvas->drawArc(r, start, sweep, useCenter, paint);
1239 break;
1240 }
1241 case 32: {
Kevin Lubick0938ce72018-05-21 21:17:15 -04001242 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001243 SkPath path;
Mike Klein7ffa40c2018-09-25 12:16:53 -04001244 FuzzNicePath(fuzz, &path, 60);
Hal Canary24ac42b2017-02-14 13:35:14 -05001245 canvas->drawPath(path, paint);
1246 break;
1247 }
1248 case 33: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001249 sk_sp<SkImage> img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001250 SkScalar left, top;
1251 bool usePaint;
1252 fuzz->next(&left, &top, &usePaint);
1253 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001254 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001255 }
Mike Reed34c56a52021-01-22 15:26:41 -05001256 canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
1257 usePaint ? &paint : nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001258 break;
1259 }
1260 case 35: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001261 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001262 SkIRect src;
1263 SkRect dst;
1264 bool usePaint;
1265 fuzz->next(&src, &dst, &usePaint);
1266 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001267 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001268 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001269 SkCanvas::SrcRectConstraint constraint =
Hal Canary1e0138b2017-03-10 13:56:08 -05001270 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1271 : SkCanvas::kFast_SrcRectConstraint;
Mike Reed34c56a52021-01-22 15:26:41 -05001272 canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
1273 usePaint ? &paint : nullptr, constraint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001274 break;
1275 }
1276 case 37: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001277 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001278 SkIRect center;
1279 SkRect dst;
1280 bool usePaint;
Hal Canary0361d492017-03-15 12:58:15 -04001281 fuzz->next(&usePaint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001282 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001283 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001284 }
Hal Canary0361d492017-03-15 12:58:15 -04001285 if (make_fuzz_t<bool>(fuzz)) {
1286 fuzz->next(&center);
1287 } else { // Make valid center, see SkLatticeIter::Valid().
1288 fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1289 fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1290 fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1291 fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1292 }
1293 fuzz->next(&dst);
Mike Reed99116302021-01-25 11:37:10 -05001294 canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
1295 usePaint ? &paint : nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001296 break;
1297 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001298 case 44: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001299 auto img = make_fuzz_image(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001300 bool usePaint;
1301 SkRect dst;
1302 fuzz->next(&usePaint, &dst);
1303 if (usePaint) {
Hal Canary1e0138b2017-03-10 13:56:08 -05001304 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001305 }
1306 constexpr int kMax = 6;
1307 int xDivs[kMax], yDivs[kMax];
Stan Ilievca8c0952017-12-11 13:01:58 -05001308 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
Hal Canary24ac42b2017-02-14 13:35:14 -05001309 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1310 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1311 fuzz->nextN(xDivs, lattice.fXCount);
1312 fuzz->nextN(yDivs, lattice.fYCount);
Mike Reed99116302021-01-25 11:37:10 -05001313 canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
1314 usePaint ? &paint : nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -05001315 break;
1316 }
1317 case 45: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001318 fuzz_paint(fuzz, &paint, depth - 1);
Mike Reed358fcad2018-11-23 15:27:51 -05001319 font = fuzz_font(fuzz);
1320 SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
Hal Canary24ac42b2017-02-14 13:35:14 -05001321 SkScalar x, y;
1322 fuzz->next(&x, &y);
Mike Reed358fcad2018-11-23 15:27:51 -05001323 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
Herb Derby3050ef52022-09-29 21:12:37 -04001324 canvas->drawSimpleText(text.begin(), SkToSizeT(text.size()), encoding, x, y,
Mike Reed358fcad2018-11-23 15:27:51 -05001325 font, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001326 break;
1327 }
1328 case 46: {
Mike Reed212e9062018-12-25 17:35:49 -05001329 // was drawPosText
Hal Canary24ac42b2017-02-14 13:35:14 -05001330 break;
1331 }
1332 case 47: {
Mike Reed212e9062018-12-25 17:35:49 -05001333 // was drawPosTextH
Hal Canary24ac42b2017-02-14 13:35:14 -05001334 break;
1335 }
1336 case 48: {
Mike Reed1eb9af92018-10-01 12:16:59 -04001337 // was drawtextonpath
Hal Canary24ac42b2017-02-14 13:35:14 -05001338 break;
1339 }
1340 case 49: {
Mike Reed1eb9af92018-10-01 12:16:59 -04001341 // was drawtextonpath
Hal Canary24ac42b2017-02-14 13:35:14 -05001342 break;
1343 }
1344 case 50: {
Mike Reed212e9062018-12-25 17:35:49 -05001345 // was drawTextRSXform
Hal Canary24ac42b2017-02-14 13:35:14 -05001346 break;
1347 }
1348 case 51: {
Hal Canary5395c592017-03-08 16:52:18 -05001349 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
Hal Canary1e0138b2017-03-10 13:56:08 -05001350 fuzz_paint(fuzz, &paint, depth - 1);
Hal Canary5395c592017-03-08 16:52:18 -05001351 SkScalar x, y;
1352 fuzz->next(&x, &y);
1353 canvas->drawTextBlob(blob, x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001354 break;
1355 }
1356 case 52: {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001357 SkMatrix matrix;
Hal Canary24ac42b2017-02-14 13:35:14 -05001358 bool usePaint, useMatrix;
1359 fuzz->next(&usePaint, &useMatrix);
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 if (useMatrix) {
Kevin Lubickbc9a1a82018-09-17 14:46:57 -04001364 FuzzNiceMatrix(fuzz, &matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -05001365 }
Hal Canary1e0138b2017-03-10 13:56:08 -05001366 auto pic = make_fuzz_picture(fuzz, depth - 1);
Hal Canary24ac42b2017-02-14 13:35:14 -05001367 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1368 usePaint ? &paint : nullptr);
1369 break;
1370 }
1371 case 53: {
Hal Canary1e0138b2017-03-10 13:56:08 -05001372 fuzz_paint(fuzz, &paint, depth - 1);
Mike Reed887cdf12017-04-03 11:11:09 -04001373 SkVertices::VertexMode vertexMode;
Hal Canary5af600e2017-03-09 14:10:36 -05001374 SkBlendMode blendMode;
Mike Kleinf88f5ef2018-11-19 12:21:46 -05001375 fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1376 fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001377 constexpr int kMaxCount = 100;
1378 int vertexCount;
1379 SkPoint vertices[kMaxCount];
1380 SkPoint texs[kMaxCount];
1381 SkColor colors[kMaxCount];
Hal Canary24ac42b2017-02-14 13:35:14 -05001382 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1383 fuzz->nextN(vertices, vertexCount);
1384 bool useTexs, useColors;
1385 fuzz->next(&useTexs, &useColors);
1386 if (useTexs) {
1387 fuzz->nextN(texs, vertexCount);
1388 }
1389 if (useColors) {
1390 fuzz->nextN(colors, vertexCount);
1391 }
1392 int indexCount = 0;
Hal Canary68b9b572017-03-02 15:27:23 -05001393 uint16_t indices[kMaxCount * 2];
Hal Canary1e0138b2017-03-10 13:56:08 -05001394 if (make_fuzz_t<bool>(fuzz)) {
Hal Canary68b9b572017-03-02 15:27:23 -05001395 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
John Stiles13c9f662021-08-16 12:16:29 -04001396 for (int index = 0; index < indexCount; ++index) {
1397 fuzz->nextRange(&indices[index], 0, vertexCount - 1);
Hal Canary68b9b572017-03-02 15:27:23 -05001398 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001399 }
Mike Reed887cdf12017-04-03 11:11:09 -04001400 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1401 useTexs ? texs : nullptr,
1402 useColors ? colors : nullptr,
1403 indexCount, indices),
1404 blendMode, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001405 break;
1406 }
Zepeng Huba7cbf72020-07-01 13:21:03 +00001407 case 54: {
1408 SkColor color;
1409 SkBlendMode blendMode;
1410 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1411 fuzz->next(&color);
1412 canvas->drawColor(color, blendMode);
1413 break;
1414 }
1415 case 55: {
1416 SkColor4f color;
1417 SkBlendMode blendMode;
1418 float R, G, B, Alpha;
1419 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1420 fuzz->nextRange(&R, -1, 2);
1421 fuzz->nextRange(&G, -1, 2);
1422 fuzz->nextRange(&B, -1, 2);
1423 fuzz->nextRange(&Alpha, 0, 1);
1424 color = {R, G, B, Alpha};
1425 canvas->drawColor(color, blendMode);
1426 break;
1427 }
1428 case 56: {
1429 fuzz_paint(fuzz, &paint, depth - 1);
1430 SkPoint p0, p1;
1431 fuzz->next(&p0, &p1);
1432 canvas->drawLine(p0, p1, paint);
1433 break;
1434 }
1435 case 57: {
1436 fuzz_paint(fuzz, &paint, depth - 1);
1437 SkIRect r;
1438 fuzz->next(&r);
1439 canvas->drawIRect(r, paint);
1440 break;
1441 }
1442 case 58: {
1443 fuzz_paint(fuzz, &paint, depth - 1);
1444 SkScalar radius;
1445 SkPoint center;
1446 fuzz->next(&radius, &center);
1447 canvas->drawCircle(center, radius, paint);
1448 break;
1449 }
1450 case 59: {
1451 fuzz_paint(fuzz, &paint, depth - 1);
1452 SkRect oval;
1453 SkScalar startAngle, sweepAngle;
1454 bool useCenter;
1455 fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
1456 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1457 break;
1458 }
1459 case 60: {
1460 fuzz_paint(fuzz, &paint, depth - 1);
1461 SkRect rect;
1462 SkScalar rx, ry;
1463 fuzz->next(&rect, &rx, &ry);
1464 canvas->drawRoundRect(rect, rx, ry, paint);
1465 break;
1466 }
1467 case 61: {
1468 fuzz_paint(fuzz, &paint, depth - 1);
1469 font = fuzz_font(fuzz);
1470 std::string str = make_fuzz_string(fuzz);
1471 SkScalar x, y;
1472 fuzz->next(&x, &y);
1473 canvas->drawString(str.c_str(), x, y, font, paint);
1474 break;
1475 }
1476 case 62: {
1477 fuzz_paint(fuzz, &paint, depth - 1);
1478 SkPoint cubics[12];
1479 SkColor colors[4];
1480 SkPoint texCoords[4];
1481 bool useTexCoords;
1482 fuzz->nextN(cubics, 12);
1483 fuzz->nextN(colors, 4);
1484 fuzz->next(&useTexCoords);
1485 if (useTexCoords) {
1486 fuzz->nextN(texCoords, 4);
1487 }
1488 SkBlendMode mode;
1489 fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
1490 canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
1491 , mode, paint);
1492 break;
1493 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001494 default:
Kevin Lubick54f20e02018-01-11 14:50:21 -05001495 SkASSERT(false);
Hal Canary24ac42b2017-02-14 13:35:14 -05001496 break;
1497 }
1498 }
1499}
1500
Hal Canary1e0138b2017-03-10 13:56:08 -05001501static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
Hal Canary24ac42b2017-02-14 13:35:14 -05001502 SkScalar w, h;
1503 fuzz->next(&w, &h);
1504 SkPictureRecorder pictureRecorder;
1505 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1506 return pictureRecorder.finishRecordingAsPicture();
1507}
1508
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001509DEF_FUZZ(NullCanvas, fuzz) {
1510 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001511}
1512
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001513constexpr SkISize kCanvasSize = {128, 160};
Hal Canary44801ca2017-03-15 11:39:06 -04001514
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001515DEF_FUZZ(RasterN32Canvas, fuzz) {
Kevin Lubick5c93acf2023-05-09 12:11:43 -04001516 auto surface = SkSurfaces::Raster(
1517 SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
Kevin Lubick486ee3d2018-03-21 10:17:25 -04001518 if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001519 fuzz_canvas(fuzz, surface->getCanvas());
1520}
1521
Hal Canarye2924432017-12-01 11:46:26 -05001522DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1523 SkPictureRecorder recorder;
1524 fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1525 SkIntToScalar(kCanvasSize.height())));
1526 sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1527 if (!pic) { fuzz->signalBug(); }
Kevin Lubickc3bac5b2023-09-25 08:43:57 -04001528 SkSerialProcs sProcs;
1529 sProcs.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
1530 return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
1531 };
1532 sk_sp<SkData> data = pic->serialize(&sProcs);
Hal Canarye2924432017-12-01 11:46:26 -05001533 if (!data) { fuzz->signalBug(); }
Mike Reedfadbfcd2017-12-06 16:09:20 -05001534 SkReadBuffer rb(data->data(), data->size());
Kevin Lubickc3bac5b2023-09-25 08:43:57 -04001535 SkCodecs::Register(SkPngDecoder::Decoder());
Cary Clarkefd99cc2018-06-11 16:25:43 -04001536 auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
Hal Canarye2924432017-12-01 11:46:26 -05001537 if (!deserialized) { fuzz->signalBug(); }
Kevin Lubick5c93acf2023-05-09 12:11:43 -04001538 auto surface = SkSurfaces::Raster(
1539 SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
Hal Canarye2924432017-12-01 11:46:26 -05001540 SkASSERT(surface && surface->getCanvas());
1541 surface->getCanvas()->drawPicture(deserialized);
1542}
1543
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001544DEF_FUZZ(ImageFilter, fuzz) {
1545 auto fil = make_fuzz_imageFilter(fuzz, 20);
1546
1547 SkPaint paint;
1548 paint.setImageFilter(fil);
1549 SkBitmap bitmap;
1550 SkCanvas canvas(bitmap);
1551 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1552}
1553
1554
1555//SkRandom _rand;
1556#define SK_ADD_RANDOM_BIT_FLIPS
1557
1558DEF_FUZZ(SerializedImageFilter, fuzz) {
Robert Phillipse5476bb2019-03-14 13:30:08 -04001559 SkBitmap bitmap;
1560 if (!bitmap.tryAllocN32Pixels(256, 256)) {
1561 SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
1562 return;
1563 }
1564
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001565 auto filter = make_fuzz_imageFilter(fuzz, 20);
Robert Phillips66f6ef42018-09-14 11:58:40 -04001566 if (!filter) {
1567 return;
1568 }
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001569 auto data = filter->serialize();
1570 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1571 size_t len = data->size();
1572#ifdef SK_ADD_RANDOM_BIT_FLIPS
1573 unsigned char* p = const_cast<unsigned char*>(ptr);
1574 for (size_t i = 0; i < len; ++i, ++p) {
1575 uint8_t j;
1576 fuzz->nextRange(&j, 1, 250);
1577 if (j == 1) { // 0.4% of the time, flip a bit or byte
1578 uint8_t k;
1579 fuzz->nextRange(&k, 1, 10);
1580 if (k == 1) { // Then 10% of the time, change a whole byte
1581 uint8_t s;
1582 fuzz->nextRange(&s, 0, 2);
1583 switch(s) {
1584 case 0:
1585 *p ^= 0xFF; // Flip entire byte
1586 break;
1587 case 1:
1588 *p = 0xFF; // Set all bits to 1
1589 break;
1590 case 2:
1591 *p = 0x00; // Set all bits to 0
1592 break;
1593 }
1594 } else {
1595 uint8_t s;
1596 fuzz->nextRange(&s, 0, 7);
1597 *p ^= (1 << 7);
1598 }
1599 }
1600 }
1601#endif // SK_ADD_RANDOM_BIT_FLIPS
1602 auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1603
1604 // uncomment below to write out a serialized image filter (to make corpus
1605 // for -t filter_fuzz)
1606 // SkString s("./serialized_filters/sf");
1607 // s.appendU32(_rand.nextU());
1608 // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1609 // sk_fwrite(data->bytes(), data->size(), file);
1610 // sk_fclose(file);
1611
1612 SkPaint paint;
1613 paint.setImageFilter(deserializedFil);
Robert Phillipse5476bb2019-03-14 13:30:08 -04001614
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001615 SkCanvas canvas(bitmap);
Robert Phillipse5476bb2019-03-14 13:30:08 -04001616 canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
1617 canvas.restore();
Kevin Lubickedef8ec2018-01-09 15:32:58 -05001618}
1619
Kevin Lubick0f7b44e2023-02-28 09:13:11 -05001620#if defined(SK_GANESH)
Kevin Lubick94303e82022-02-01 09:03:41 -05001621static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
1622 SkASSERT(context);
Kevin Lubick5c93acf2023-05-09 12:11:43 -04001623 auto surface = SkSurfaces::RenderTarget(
Kevin Lubick94303e82022-02-01 09:03:41 -05001624 context,
Kevin Lubickecd3a2f2023-01-05 08:17:45 -05001625 skgpu::Budgeted::kNo,
Kevin Lubick94303e82022-02-01 09:03:41 -05001626 SkImageInfo::Make(kCanvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1627 SkASSERT(surface && surface->getCanvas());
1628 fuzz_canvas(fuzz, surface->getCanvas());
1629}
Kevin Lubickfaef5142018-06-07 10:33:11 -04001630
Kevin Lubick94303e82022-02-01 09:03:41 -05001631DEF_FUZZ(MockGPUCanvas, fuzz) {
1632 sk_gpu_test::GrContextFactory f;
John Stilesba7c5252023-08-25 10:50:10 -04001633 fuzz_ganesh(fuzz, f.get(skgpu::ContextType::kMock));
Kevin Lubick94303e82022-02-01 09:03:41 -05001634}
1635#endif
1636
1637#ifdef SK_GL
Robert Phillips7b4e43c2020-07-01 16:59:17 -04001638static void dump_GPU_info(GrDirectContext* context) {
Robert Phillips9da87e02019-02-04 13:26:26 -05001639 const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
Kevin Lubickfaef5142018-06-07 10:33:11 -04001640 ->glInterface();
1641 const GrGLubyte* output;
1642 GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1643 SkDebugf("GL_RENDERER %s\n", (const char*) output);
1644
1645 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1646 SkDebugf("GL_VENDOR %s\n", (const char*) output);
1647
1648 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1649 SkDebugf("GL_VERSION %s\n", (const char*) output);
1650}
1651
Hal Canary44801ca2017-03-15 11:39:06 -04001652DEF_FUZZ(NativeGLCanvas, fuzz) {
Hal Canary549be4a2018-01-05 16:59:53 -05001653 sk_gpu_test::GrContextFactory f;
John Stilesba7c5252023-08-25 10:50:10 -04001654 auto context = f.get(skgpu::ContextType::kGL);
Brian Salomon6405e712017-03-20 08:54:16 -04001655 if (!context) {
John Stilesba7c5252023-08-25 10:50:10 -04001656 context = f.get(skgpu::ContextType::kGLES);
Brian Salomon6405e712017-03-20 08:54:16 -04001657 }
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001658 if (FLAGS_gpuInfo) {
Kevin Lubickfaef5142018-06-07 10:33:11 -04001659 dump_GPU_info(context);
Kevin Lubickfe6b4892018-06-05 17:21:30 -04001660 }
Hal Canary5aa91582017-03-21 11:11:44 -07001661 fuzz_ganesh(fuzz, context);
1662}
Hal Canary44801ca2017-03-15 11:39:06 -04001663#endif
1664
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001665DEF_FUZZ(PDFCanvas, fuzz) {
Hal Canaryfe759302017-08-26 17:06:42 -04001666 SkNullWStream stream;
Hal Canary23564b92018-09-07 14:33:14 -04001667 auto doc = SkPDF::MakeDocument(&stream);
Hal Canary44801ca2017-03-15 11:39:06 -04001668 fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1669 SkIntToScalar(kCanvasSize.height())));
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001670}
1671
1672// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1673DEF_FUZZ(_DumpCanvas, fuzz) {
Mike Klein8f4e2242019-03-20 11:59:00 -05001674 DebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001675 fuzz_canvas(fuzz, &debugCanvas);
1676 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1677 UrlDataManager dataManager(SkString("data"));
Brian Osmand8a90f92019-01-28 13:41:19 -05001678 SkDynamicMemoryWStream stream;
1679 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1680 writer.beginObject(); // root
Nathaniel Nifonga072b7b2019-12-13 13:51:14 -05001681 debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
Brian Osmand8a90f92019-01-28 13:41:19 -05001682 writer.endObject(); // root
1683 writer.flush();
1684 sk_sp<SkData> json = stream.detachAsData();
1685 fwrite(json->data(), json->size(), 1, stdout);
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001686}
Zepeng Huba7cbf72020-07-01 13:21:03 +00001687
1688DEF_FUZZ(SVGCanvas, fuzz) {
1689 SkNullWStream stream;
1690 SkRect bounds = SkRect::MakeIWH(150, 150);
1691 std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
1692 fuzz_canvas(fuzz, canvas.get());
1693}