Coverage Report

Created: 2024-05-20 07:14

/src/skia/fuzz/FuzzCanvas.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
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/Fuzz.h"
9
#include "fuzz/FuzzCommon.h"
10
#include "include/codec/SkPngDecoder.h"
11
#include "include/core/SkBitmap.h"
12
#include "include/core/SkBlurTypes.h"
13
#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"
24
#include "include/core/SkTextBlob.h"
25
#include "include/core/SkTypeface.h"
26
#include "include/core/SkVertices.h"
27
#include "include/docs/SkPDFDocument.h"
28
#include "include/effects/Sk1DPathEffect.h"
29
#include "include/effects/Sk2DPathEffect.h"
30
#include "include/effects/SkCornerPathEffect.h"
31
#include "include/effects/SkDashPathEffect.h"
32
#include "include/effects/SkDiscretePathEffect.h"
33
#include "include/effects/SkGradientShader.h"
34
#include "include/effects/SkHighContrastFilter.h"
35
#include "include/effects/SkImageFilters.h"
36
#include "include/effects/SkLumaColorFilter.h"
37
#include "include/effects/SkPerlinNoiseShader.h"
38
#include "include/encode/SkPngEncoder.h"
39
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
40
#include "include/private/base/SkTo.h"
41
#include "include/svg/SkSVGCanvas.h"
42
#include "include/utils/SkNullCanvas.h"
43
#include "src/base/SkUTF.h"
44
#include "src/core/SkFontPriv.h"
45
#include "src/core/SkOSFile.h"
46
#include "src/core/SkPaintPriv.h"
47
#include "src/core/SkPicturePriv.h"
48
#include "src/core/SkReadBuffer.h"
49
#include "src/utils/SkJSONWriter.h"
50
#include "tools/UrlDataManager.h"
51
#include "tools/debugger/DebugCanvas.h"
52
#include "tools/flags/CommandLineFlags.h"
53
#include "tools/fonts/FontToolUtils.h"
54
55
#if defined(SK_GANESH)
56
#include "include/gpu/GrDirectContext.h"
57
#include "src/gpu/ganesh/GrDirectContextPriv.h"
58
#include "tools/gpu/GrContextFactory.h"
59
#endif
60
61
#ifdef SK_GL
62
#include "include/gpu/gl/GrGLFunctions.h"
63
#include "src/gpu/ganesh/gl/GrGLGpu.h"
64
#include "src/gpu/ganesh/gl/GrGLUtil.h"
65
#endif
66
67
#include <iostream>
68
#include <utility>
69
70
using namespace skia_private;
71
72
static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
73
74
// TODO:
75
//   SkTextBlob with Unicode
76
//   SkImage: more types
77
78
// 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!
81
template <typename T>
82
413k
inline T make_fuzz_t(Fuzz* fuzz) {
83
413k
    T t;
84
413k
    fuzz->next(&t);
85
413k
    return t;
86
413k
}
unsigned int make_fuzz_t<unsigned int>(Fuzz*)
Line
Count
Source
82
67.3k
inline T make_fuzz_t(Fuzz* fuzz) {
83
67.3k
    T t;
84
67.3k
    fuzz->next(&t);
85
67.3k
    return t;
86
67.3k
}
float make_fuzz_t<float>(Fuzz*)
Line
Count
Source
82
110k
inline T make_fuzz_t(Fuzz* fuzz) {
83
110k
    T t;
84
110k
    fuzz->next(&t);
85
110k
    return t;
86
110k
}
bool make_fuzz_t<bool>(Fuzz*)
Line
Count
Source
82
235k
inline T make_fuzz_t(Fuzz* fuzz) {
83
235k
    T t;
84
235k
    fuzz->next(&t);
85
235k
    return t;
86
235k
}
87
88
static sk_sp<SkImage> make_fuzz_image(Fuzz*);
89
90
static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
91
92
79.6k
static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
93
79.6k
    if (depth <= 0) {
94
11.3k
        return nullptr;
95
11.3k
    }
96
68.2k
    int colorFilterType;
97
68.2k
    fuzz->nextRange(&colorFilterType, 0, 8);
98
68.2k
    switch (colorFilterType) {
99
49.4k
        case 0:
100
49.4k
            return nullptr;
101
1.23k
        case 1: {
102
1.23k
            SkColor color;
103
1.23k
            SkBlendMode mode;
104
1.23k
            fuzz->next(&color);
105
1.23k
            fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
106
1.23k
            return SkColorFilters::Blend(color, mode);
107
0
        }
108
5.64k
        case 2: {
109
5.64k
            sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
110
5.64k
            if (!outer) {
111
451
                return nullptr;
112
451
            }
113
5.19k
            sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
114
            // makeComposed should be able to handle nullptr.
115
5.19k
            return outer->makeComposed(std::move(inner));
116
5.64k
        }
117
694
        case 3: {
118
694
            float array[20];
119
694
            fuzz->nextN(array, std::size(array));
120
694
            return SkColorFilters::Matrix(array);
121
5.64k
        }
122
577
        case 4: {
123
577
            SkColor mul, add;
124
577
            fuzz->next(&mul, &add);
125
577
            return SkColorFilters::Lighting(mul, add);
126
5.64k
        }
127
3.03k
        case 5: {
128
3.03k
            bool grayscale;
129
3.03k
            int invertStyle;
130
3.03k
            float contrast;
131
3.03k
            fuzz->next(&grayscale);
132
3.03k
            fuzz->nextRange(&invertStyle, 0, 2);
133
3.03k
            fuzz->nextRange(&contrast, -1.0f, 1.0f);
134
3.03k
            return SkHighContrastFilter::Make(SkHighContrastConfig(
135
3.03k
                    grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
136
5.64k
        }
137
890
        case 6:
138
890
            return SkLumaColorFilter::Make();
139
68
        case 7: {
140
68
            uint8_t table[256];
141
68
            fuzz->nextN(table, std::size(table));
142
68
            return SkColorFilters::Table(table);
143
5.64k
        }
144
6.64k
        case 8: {
145
6.64k
            uint8_t tableA[256];
146
6.64k
            uint8_t tableR[256];
147
6.64k
            uint8_t tableG[256];
148
6.64k
            uint8_t tableB[256];
149
6.64k
            fuzz->nextN(tableA, std::size(tableA));
150
6.64k
            fuzz->nextN(tableR, std::size(tableR));
151
6.64k
            fuzz->nextN(tableG, std::size(tableG));
152
6.64k
            fuzz->nextN(tableB, std::size(tableB));
153
6.64k
            return SkColorFilters::TableARGB(tableA, tableR, tableG, tableB);
154
5.64k
        }
155
0
        default:
156
0
            SkASSERT(false);
157
0
            break;
158
68.2k
    }
159
0
    return nullptr;
160
68.2k
}
161
162
1.11k
static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
163
1.11k
    SkScalar totalPos = 0;
164
8.76k
    for (int i = 0; i < colorCount; ++i) {
165
7.64k
        fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
166
7.64k
        totalPos += pos[i];
167
7.64k
    }
168
1.11k
    totalPos = 1.0f / totalPos;
169
8.76k
    for (int i = 0; i < colorCount; ++i) {
170
7.64k
        pos[i] *= totalPos;
171
7.64k
    }
172
    // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
173
1.11k
    pos[colorCount - 1] = 1.0f;
174
1.11k
}
175
176
130k
static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
177
130k
    sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
178
130k
    sk_sp<SkColorFilter> colorFilter(nullptr);
179
130k
    SkBitmap bitmap;
180
130k
    sk_sp<SkImage> img;
181
130k
    SkTileMode tmX, tmY;
182
130k
    bool useMatrix;
183
130k
    SkColor color;
184
130k
    SkMatrix matrix;
185
130k
    SkBlendMode blendMode;
186
130k
    int shaderType;
187
130k
    if (depth <= 0) {
188
27.3k
        return nullptr;
189
27.3k
    }
190
102k
    fuzz->nextRange(&shaderType, 0, 14);
191
102k
    switch (shaderType) {
192
41.5k
        case 0:
193
41.5k
            return nullptr;
194
711
        case 1:
195
711
            return SkShaders::Empty();
196
389
        case 2:
197
389
            fuzz->next(&color);
198
389
            return SkShaders::Color(color);
199
616
        case 3:
200
616
            img = make_fuzz_image(fuzz);
201
616
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
202
616
            fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
203
616
            fuzz->next(&useMatrix);
204
616
            if (useMatrix) {
205
154
                FuzzNiceMatrix(fuzz, &matrix);
206
154
            }
207
616
            return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
208
415
        case 5:
209
415
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
210
415
            FuzzNiceMatrix(fuzz, &matrix);
211
415
            return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
212
348
        case 6:
213
348
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
214
348
            colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
215
348
            return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
216
2.14k
        case 7:
217
2.14k
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
218
2.14k
            shader2 = make_fuzz_shader(fuzz, depth - 1);
219
2.14k
            fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
220
2.14k
            return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
221
2.39k
        case 8: {
222
2.39k
            auto pic = make_fuzz_picture(fuzz, depth - 1);
223
2.39k
            bool useTile;
224
2.39k
            SkRect tile;
225
2.39k
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
226
2.39k
            fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
227
2.39k
            fuzz->next(&useMatrix, &useTile);
228
2.39k
            if (useMatrix) {
229
160
                FuzzNiceMatrix(fuzz, &matrix);
230
160
            }
231
2.39k
            if (useTile) {
232
164
                fuzz->next(&tile);
233
164
            }
234
2.39k
            return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
235
2.39k
                                   useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
236
0
        }
237
        // EFFECTS:
238
19
        case 9:
239
            // Deprecated SkGaussianEdgeShader
240
19
            return nullptr;
241
576
        case 10: {
242
576
            constexpr int kMaxColors = 12;
243
576
            SkPoint pts[2];
244
576
            SkColor colors[kMaxColors];
245
576
            SkScalar pos[kMaxColors];
246
576
            int colorCount;
247
576
            bool usePos;
248
576
            fuzz->nextN(pts, 2);
249
576
            fuzz->nextRange(&colorCount, 2, kMaxColors);
250
576
            fuzz->nextN(colors, colorCount);
251
576
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
252
576
            fuzz->next(&useMatrix, &usePos);
253
576
            if (useMatrix) {
254
234
                FuzzNiceMatrix(fuzz, &matrix);
255
234
            }
256
576
            if (usePos) {
257
218
                fuzz_gradient_stops(fuzz, pos, colorCount);
258
218
            }
259
576
            return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
260
576
                                                tmX, 0, useMatrix ? &matrix : nullptr);
261
0
        }
262
544
        case 11: {
263
544
            constexpr int kMaxColors = 12;
264
544
            SkPoint center;
265
544
            SkScalar radius;
266
544
            int colorCount;
267
544
            bool usePos;
268
544
            SkColor colors[kMaxColors];
269
544
            SkScalar pos[kMaxColors];
270
544
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
271
544
            fuzz->next(&useMatrix, &usePos, &center, &radius);
272
544
            fuzz->nextRange(&colorCount, 2, kMaxColors);
273
544
            fuzz->nextN(colors, colorCount);
274
544
            if (useMatrix) {
275
247
                FuzzNiceMatrix(fuzz, &matrix);
276
247
            }
277
544
            if (usePos) {
278
129
                fuzz_gradient_stops(fuzz, pos, colorCount);
279
129
            }
280
544
            return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
281
544
                                                colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
282
0
        }
283
1.66k
        case 12: {
284
1.66k
            constexpr int kMaxColors = 12;
285
1.66k
            SkPoint start, end;
286
1.66k
            SkScalar startRadius, endRadius;
287
1.66k
            int colorCount;
288
1.66k
            bool usePos;
289
1.66k
            SkColor colors[kMaxColors];
290
1.66k
            SkScalar pos[kMaxColors];
291
1.66k
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
292
1.66k
            fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
293
1.66k
            fuzz->nextRange(&colorCount, 2, kMaxColors);
294
1.66k
            fuzz->nextN(colors, colorCount);
295
1.66k
            if (useMatrix) {
296
527
                FuzzNiceMatrix(fuzz, &matrix);
297
527
            }
298
1.66k
            if (usePos) {
299
564
                fuzz_gradient_stops(fuzz, pos, colorCount);
300
564
            }
301
1.66k
            return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
302
1.66k
                                                         usePos ? pos : nullptr, colorCount, tmX, 0,
303
1.66k
                                                         useMatrix ? &matrix : nullptr);
304
0
        }
305
372
        case 13: {
306
372
            constexpr int kMaxColors = 12;
307
372
            SkScalar cx, cy;
308
372
            int colorCount;
309
372
            bool usePos;
310
372
            SkColor colors[kMaxColors];
311
372
            SkScalar pos[kMaxColors];
312
372
            fuzz->next(&cx, &cy, &useMatrix, &usePos);
313
372
            fuzz->nextRange(&colorCount, 2, kMaxColors);
314
372
            fuzz->nextN(colors, colorCount);
315
372
            if (useMatrix) {
316
206
                FuzzNiceMatrix(fuzz, &matrix);
317
206
            }
318
372
            if (usePos) {
319
208
                fuzz_gradient_stops(fuzz, pos, colorCount);
320
208
            }
321
372
            return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
322
372
                                               0, useMatrix ? &matrix : nullptr);
323
0
        }
324
51.0k
        case 14: {
325
51.0k
            SkScalar baseFrequencyX, baseFrequencyY, seed;
326
51.0k
            int numOctaves;
327
51.0k
            SkISize tileSize;
328
51.0k
            bool useTileSize, turbulence;
329
51.0k
            fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
330
51.0k
            if (useTileSize) {
331
15.7k
                fuzz->next(&tileSize);
332
15.7k
            }
333
51.0k
            fuzz->nextRange(&numOctaves, 2, 7);
334
51.0k
            if (turbulence) {
335
16.0k
                return SkShaders::MakeTurbulence(baseFrequencyX,
336
16.0k
                                                 baseFrequencyY,
337
16.0k
                                                 numOctaves,
338
16.0k
                                                 seed,
339
16.0k
                                                 useTileSize ? &tileSize : nullptr);
340
35.0k
            } else {
341
35.0k
                return SkShaders::MakeFractalNoise(baseFrequencyX,
342
35.0k
                                                   baseFrequencyY,
343
35.0k
                                                   numOctaves,
344
35.0k
                                                   seed,
345
35.0k
                                                   useTileSize ? &tileSize : nullptr);
346
35.0k
            }
347
51.0k
        }
348
103
        default:
349
103
            SkASSERT(false);
350
103
            break;
351
102k
    }
352
103
    return nullptr;
353
102k
}
354
355
149k
static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
356
149k
    if (depth <= 0) {
357
31.4k
        return nullptr;
358
31.4k
    }
359
117k
    uint8_t pathEffectType;
360
117k
    fuzz->nextRange(&pathEffectType, 0, 8);
361
117k
    switch (pathEffectType) {
362
36.1k
        case 0: {
363
36.1k
            return nullptr;
364
0
        }
365
16.8k
        case 1: {
366
16.8k
            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
367
16.8k
            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
368
16.8k
            return SkPathEffect::MakeSum(std::move(first), std::move(second));
369
0
        }
370
24.1k
        case 2: {
371
24.1k
            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
372
24.1k
            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
373
24.1k
            return SkPathEffect::MakeCompose(std::move(first), std::move(second));
374
0
        }
375
2.96k
        case 3: {
376
2.96k
            SkPath path;
377
2.96k
            FuzzNicePath(fuzz, &path, 20);
378
2.96k
            SkScalar advance, phase;
379
2.96k
            fuzz->next(&advance, &phase);
380
2.96k
            SkPath1DPathEffect::Style style;
381
2.96k
            fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
382
2.96k
            return SkPath1DPathEffect::Make(path, advance, phase, style);
383
0
        }
384
2.36k
        case 4: {
385
2.36k
            SkScalar width;
386
2.36k
            SkMatrix matrix;
387
2.36k
            fuzz->next(&width);
388
2.36k
            FuzzNiceMatrix(fuzz, &matrix);
389
2.36k
            return SkLine2DPathEffect::Make(width, matrix);
390
0
        }
391
1.69k
        case 5: {
392
1.69k
            SkPath path;
393
1.69k
            FuzzNicePath(fuzz, &path, 20);
394
1.69k
            SkMatrix matrix;
395
1.69k
            FuzzNiceMatrix(fuzz, &matrix);
396
1.69k
            return SkPath2DPathEffect::Make(matrix, path);
397
0
        }
398
4.44k
        case 6: {
399
4.44k
            SkScalar radius;
400
4.44k
            fuzz->next(&radius);
401
4.44k
            return SkCornerPathEffect::Make(radius);
402
0
        }
403
2.41k
        case 7: {
404
2.41k
            SkScalar phase;
405
2.41k
            fuzz->next(&phase);
406
2.41k
            SkScalar intervals[20];
407
2.41k
            int count;
408
2.41k
            fuzz->nextRange(&count, 0, (int)std::size(intervals));
409
2.41k
            fuzz->nextN(intervals, count);
410
2.41k
            return SkDashPathEffect::Make(intervals, count, phase);
411
0
        }
412
26.8k
        case 8: {
413
26.8k
            SkScalar segLength, dev;
414
26.8k
            uint32_t seed;
415
26.8k
            fuzz->next(&segLength, &dev, &seed);
416
26.8k
            return SkDiscretePathEffect::Make(segLength, dev, seed);
417
0
        }
418
0
        default:
419
0
            SkASSERT(false);
420
0
            return nullptr;
421
117k
    }
422
117k
}
423
424
67.3k
static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
425
67.3k
    int maskfilterType;
426
67.3k
    fuzz->nextRange(&maskfilterType, 0, 1);
427
67.3k
    switch (maskfilterType) {
428
33.5k
        case 0:
429
33.5k
            return nullptr;
430
33.7k
        case 1: {
431
33.7k
            SkBlurStyle blurStyle;
432
33.7k
            fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
433
33.7k
            SkScalar sigma;
434
33.7k
            fuzz->next(&sigma);
435
33.7k
            bool respectCTM;
436
33.7k
            fuzz->next(&respectCTM);
437
33.7k
            return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
438
0
        }
439
0
        default:
440
0
            SkASSERT(false);
441
0
            return nullptr;
442
67.3k
    }
443
67.3k
}
444
445
8.32k
static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
446
8.32k
    if (make_fuzz_t<bool>(fuzz)) {
447
1.09k
        return nullptr;
448
1.09k
    }
449
7.23k
    sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr();
450
7.23k
    int familyCount = mgr->countFamilies();
451
7.23k
    int i, j;
452
7.23k
    fuzz->nextRange(&i, 0, familyCount - 1);
453
7.23k
    sk_sp<SkFontStyleSet> family(mgr->createStyleSet(i));
454
7.23k
    int styleCount = family->count();
455
7.23k
    fuzz->nextRange(&j, 0, styleCount - 1);
456
7.23k
    return sk_sp<SkTypeface>(family->createTypeface(j));
457
8.32k
}
458
459
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
460
461
9.13k
static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
462
9.13k
    if (depth <= 0) {
463
3.25k
        return nullptr;
464
3.25k
    }
465
5.88k
    uint8_t imageFilterType;
466
5.88k
    fuzz->nextRange(&imageFilterType, 1, 6);
467
5.88k
    SkPoint3 p, q;
468
5.88k
    SkColor lightColor;
469
5.88k
    SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
470
5.88k
    sk_sp<SkImageFilter> input;
471
5.88k
    SkIRect cropRect;
472
5.88k
    bool useCropRect;
473
5.88k
    fuzz->next(&useCropRect);
474
5.88k
    if (useCropRect) {
475
545
        fuzz->next(&cropRect);
476
545
    }
477
5.88k
    switch (imageFilterType) {
478
590
        case 1:
479
590
            fuzz->next(&p, &lightColor, &surfaceScale, &k);
480
590
            input = make_fuzz_imageFilter(fuzz, depth - 1);
481
590
            return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
482
590
                                                     std::move(input),
483
590
                                                     useCropRect ? &cropRect : nullptr);
484
178
        case 2:
485
178
            fuzz->next(&p, &lightColor, &surfaceScale, &k);
486
178
            input = make_fuzz_imageFilter(fuzz, depth - 1);
487
178
            return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
488
178
                                                   std::move(input),
489
178
                                                   useCropRect ? &cropRect : nullptr);
490
115
        case 3:
491
115
            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
492
115
            input = make_fuzz_imageFilter(fuzz, depth - 1);
493
115
            return SkImageFilters::SpotLitDiffuse(
494
115
                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
495
115
                    std::move(input), useCropRect ? &cropRect : nullptr);
496
101
        case 4:
497
101
            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
498
101
            input = make_fuzz_imageFilter(fuzz, depth - 1);
499
101
            return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
500
101
                                                      shininess, std::move(input),
501
101
                                                      useCropRect ? &cropRect : nullptr);
502
583
        case 5:
503
583
            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
504
583
            input = make_fuzz_imageFilter(fuzz, depth - 1);
505
583
            return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
506
583
                                                    shininess, std::move(input),
507
583
                                                    useCropRect ? &cropRect : nullptr);
508
4.31k
        case 6:
509
4.31k
            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
510
4.31k
                       &shininess);
511
4.31k
            input = make_fuzz_imageFilter(fuzz, depth - 1);
512
4.31k
            return SkImageFilters::SpotLitSpecular(
513
4.31k
                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
514
4.31k
                    std::move(input), useCropRect ? &cropRect : nullptr);
515
0
        default:
516
0
            SkASSERT(false);
517
0
            return nullptr;
518
5.88k
    }
519
5.88k
}
520
521
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
522
523
8.17k
static SkSamplingOptions next_sampling(Fuzz* fuzz) {
524
8.17k
    if (fuzz->nextBool()) {
525
2.62k
        float B, C;
526
2.62k
        fuzz->next(&B, &C);
527
2.62k
        return SkSamplingOptions({B, C});
528
5.55k
    } else {
529
5.55k
        SkFilterMode fm;
530
5.55k
        SkMipmapMode mm;
531
5.55k
        fuzz->nextEnum(&fm, SkFilterMode::kLast);
532
5.55k
        fuzz->nextEnum(&mm, SkMipmapMode::kLast);
533
5.55k
        return SkSamplingOptions(fm, mm);
534
5.55k
    }
535
8.17k
}
536
537
542k
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
538
542k
    if (depth <= 0) {
539
193k
        return nullptr;
540
193k
    }
541
348k
    uint8_t imageFilterType;
542
348k
    fuzz->nextRange(&imageFilterType, 0, 22);
543
348k
    switch (imageFilterType) {
544
95.4k
        case 0:
545
95.4k
            return nullptr;
546
11.0k
        case 1: {
547
11.0k
            SkScalar sigmaX, sigmaY;
548
11.0k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
549
11.0k
            bool useCropRect;
550
11.0k
            fuzz->next(&sigmaX, &sigmaY, &useCropRect);
551
11.0k
            SkIRect cropRect;
552
11.0k
            if (useCropRect) {
553
2.32k
                fuzz->next(&cropRect);
554
2.32k
            }
555
11.0k
            return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
556
11.0k
                                        useCropRect ? &cropRect : nullptr);
557
0
        }
558
5.11k
        case 2: {
559
5.11k
            SkMatrix matrix;
560
5.11k
            FuzzNiceMatrix(fuzz, &matrix);
561
5.11k
            const auto sampling = next_sampling(fuzz);
562
5.11k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
563
5.11k
            return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
564
0
        }
565
4.78k
        case 3: {
566
4.78k
            float k1, k2, k3, k4;
567
4.78k
            bool enforcePMColor;
568
4.78k
            bool useCropRect;
569
4.78k
            fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
570
4.78k
            sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
571
4.78k
            sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
572
4.78k
            SkIRect cropRect;
573
4.78k
            if (useCropRect) {
574
1.48k
                fuzz->next(&cropRect);
575
1.48k
            }
576
4.78k
            return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
577
4.78k
                                              std::move(background), std::move(foreground),
578
4.78k
                                              useCropRect ? &cropRect : nullptr);
579
0
        }
580
1.09k
        case 4: {
581
1.09k
            sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
582
1.09k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
583
1.09k
            bool useCropRect;
584
1.09k
            SkIRect cropRect;
585
1.09k
            fuzz->next(&useCropRect);
586
1.09k
            if (useCropRect) {
587
209
                fuzz->next(&cropRect);
588
209
            }
589
1.09k
            return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
590
1.09k
                                               useCropRect ? &cropRect : nullptr);
591
0
        }
592
7.84k
        case 5: {
593
7.84k
            sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
594
7.84k
            sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
595
7.84k
            return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
596
0
        }
597
13.9k
        case 6: {
598
13.9k
            SkColorChannel xChannelSelector, yChannelSelector;
599
13.9k
            fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
600
13.9k
            fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
601
13.9k
            SkScalar scale;
602
13.9k
            bool useCropRect;
603
13.9k
            fuzz->next(&scale, &useCropRect);
604
13.9k
            SkIRect cropRect;
605
13.9k
            if (useCropRect) {
606
1.75k
                fuzz->next(&cropRect);
607
1.75k
            }
608
13.9k
            sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
609
13.9k
            sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
610
13.9k
            return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
611
13.9k
                                                   std::move(displacement), std::move(color),
612
13.9k
                                                   useCropRect ? &cropRect : nullptr);
613
0
        }
614
14.0k
        case 7: {
615
14.0k
            SkScalar dx, dy, sigmaX, sigmaY;
616
14.0k
            SkColor color;
617
14.0k
            bool shadowOnly, useCropRect;
618
14.0k
            fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
619
14.0k
            SkIRect cropRect;
620
14.0k
            if (useCropRect) {
621
2.58k
                fuzz->next(&cropRect);
622
2.58k
            }
623
14.0k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
624
14.0k
            if (shadowOnly) {
625
2.57k
                return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
626
2.57k
                                                      std::move(input),
627
2.57k
                                                      useCropRect ? &cropRect : nullptr);
628
11.4k
            } else {
629
11.4k
                return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
630
11.4k
                                                  useCropRect ? &cropRect : nullptr);
631
11.4k
            }
632
14.0k
        }
633
559
        case 8:
634
559
            return SkImageFilters::Image(make_fuzz_image(fuzz), SkCubicResampler::Mitchell());
635
413
        case 9: {
636
413
            sk_sp<SkImage> image = make_fuzz_image(fuzz);
637
413
            SkRect srcRect, dstRect;
638
413
            fuzz->next(&srcRect, &dstRect);
639
413
            return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
640
14.0k
        }
641
9.13k
        case 10:
642
9.13k
            return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
643
2.65k
        case 11: {
644
2.65k
            SkRect lensBounds;
645
2.65k
            SkScalar zoomAmount;
646
2.65k
            SkScalar inset;
647
2.65k
            bool useCropRect;
648
2.65k
            SkIRect cropRect;
649
2.65k
            fuzz->next(&lensBounds, &zoomAmount, &inset, &useCropRect);
650
2.65k
            if (useCropRect) {
651
1.16k
                fuzz->next(&cropRect);
652
1.16k
            }
653
2.65k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
654
2.65k
            const auto sampling = next_sampling(fuzz);
655
2.65k
            return SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling,
656
2.65k
                                             std::move(input), useCropRect ? &cropRect : nullptr);
657
14.0k
        }
658
5.42k
        case 12: {
659
5.42k
            constexpr int kMaxKernelSize = 5;
660
5.42k
            int32_t n, m;
661
5.42k
            fuzz->nextRange(&n, 1, kMaxKernelSize);
662
5.42k
            fuzz->nextRange(&m, 1, kMaxKernelSize);
663
5.42k
            SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
664
5.42k
            fuzz->nextN(kernel, n * m);
665
5.42k
            int32_t offsetX, offsetY;
666
5.42k
            fuzz->nextRange(&offsetX, 0, n - 1);
667
5.42k
            fuzz->nextRange(&offsetY, 0, m - 1);
668
5.42k
            SkScalar gain, bias;
669
5.42k
            bool convolveAlpha, useCropRect;
670
5.42k
            fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
671
5.42k
            SkTileMode tileMode;
672
5.42k
            fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
673
5.42k
            SkIRect cropRect;
674
5.42k
            if (useCropRect) {
675
2.03k
                fuzz->next(&cropRect);
676
2.03k
            }
677
5.42k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
678
5.42k
            return SkImageFilters::MatrixConvolution(
679
5.42k
                    SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
680
5.42k
                    convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
681
14.0k
        }
682
3.72k
        case 13: {
683
3.72k
            sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
684
3.72k
            sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
685
3.72k
            bool useCropRect;
686
3.72k
            fuzz->next(&useCropRect);
687
3.72k
            SkIRect cropRect;
688
3.72k
            if (useCropRect) {
689
2.28k
                fuzz->next(&cropRect);
690
2.28k
            }
691
3.72k
            return SkImageFilters::Merge(std::move(first), std::move(second),
692
3.72k
                                         useCropRect ? &cropRect : nullptr);
693
14.0k
        }
694
89.2k
        case 14: {
695
89.2k
            constexpr int kMaxCount = 4;
696
89.2k
            sk_sp<SkImageFilter> ifs[kMaxCount];
697
89.2k
            int count;
698
89.2k
            fuzz->nextRange(&count, 1, kMaxCount);
699
426k
            for (int i = 0; i < count; ++i) {
700
337k
                ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
701
337k
            }
702
89.2k
            bool useCropRect;
703
89.2k
            fuzz->next(&useCropRect);
704
89.2k
            SkIRect cropRect;
705
89.2k
            if (useCropRect) {
706
11.0k
                fuzz->next(&cropRect);
707
11.0k
            }
708
89.2k
            return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
709
14.0k
        }
710
4.06k
        case 15: {
711
4.06k
            int rx, ry;
712
4.06k
            fuzz->next(&rx, &ry);
713
4.06k
            bool useCropRect;
714
4.06k
            fuzz->next(&useCropRect);
715
4.06k
            SkIRect cropRect;
716
4.06k
            if (useCropRect) {
717
1.09k
                fuzz->next(&cropRect);
718
1.09k
            }
719
4.06k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
720
4.06k
            return SkImageFilters::Dilate(rx, ry, std::move(input),
721
4.06k
                                          useCropRect ? &cropRect : nullptr);
722
14.0k
        }
723
7.19k
        case 16: {
724
7.19k
            int rx, ry;
725
7.19k
            fuzz->next(&rx, &ry);
726
7.19k
            bool useCropRect;
727
7.19k
            fuzz->next(&useCropRect);
728
7.19k
            SkIRect cropRect;
729
7.19k
            if (useCropRect) {
730
846
                fuzz->next(&cropRect);
731
846
            }
732
7.19k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
733
7.19k
            return SkImageFilters::Erode(rx, ry, std::move(input),
734
7.19k
                                         useCropRect ? &cropRect : nullptr);
735
14.0k
        }
736
1.81k
        case 17: {
737
1.81k
            SkScalar dx, dy;
738
1.81k
            fuzz->next(&dx, &dy);
739
1.81k
            bool useCropRect;
740
1.81k
            fuzz->next(&useCropRect);
741
1.81k
            SkIRect cropRect;
742
1.81k
            if (useCropRect) {
743
479
                fuzz->next(&cropRect);
744
479
            }
745
1.81k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
746
1.81k
            return SkImageFilters::Offset(dx, dy, std::move(input),
747
1.81k
                                          useCropRect ? &cropRect : nullptr);
748
14.0k
        }
749
4.19k
        case 18: {
750
4.19k
            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
751
4.19k
            return SkImageFilters::Picture(std::move(picture));
752
14.0k
        }
753
564
        case 19: {
754
564
            SkRect cropRect;
755
564
            fuzz->next(&cropRect);
756
564
            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
757
564
            return SkImageFilters::Picture(std::move(picture), cropRect);
758
14.0k
        }
759
999
        case 20: {
760
999
            SkRect src, dst;
761
999
            fuzz->next(&src, &dst);
762
999
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
763
999
            return SkImageFilters::Tile(src, dst, std::move(input));
764
14.0k
        }
765
7.78k
        case 21: {
766
7.78k
            SkBlendMode blendMode;
767
7.78k
            bool useCropRect;
768
7.78k
            fuzz->next(&useCropRect);
769
7.78k
            fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
770
7.78k
            SkIRect cropRect;
771
7.78k
            if (useCropRect) {
772
1.86k
                fuzz->next(&cropRect);
773
1.86k
            }
774
7.78k
            sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
775
7.78k
            sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
776
7.78k
            return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
777
7.78k
                                         useCropRect ? &cropRect : nullptr);
778
14.0k
        }
779
57.8k
        case 22: {
780
57.8k
            sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
781
57.8k
            bool useCropRect;
782
57.8k
            fuzz->next(&useCropRect);
783
57.8k
            SkIRect cropRect;
784
57.8k
            if (useCropRect) {
785
19.5k
                fuzz->next(&cropRect);
786
19.5k
            }
787
57.8k
            return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
788
14.0k
        }
789
0
        default:
790
0
            SkASSERT(false);
791
0
            return nullptr;
792
348k
    }
793
348k
}
794
795
8.49k
static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
796
8.49k
    int w, h;
797
8.49k
    fuzz->nextRange(&w, 1, 1024);
798
8.49k
    fuzz->nextRange(&h, 1, 1024);
799
8.49k
    AutoTMalloc<SkPMColor> data(w * h);
800
8.49k
    SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
801
8.49k
    int n = w * h;
802
233M
    for (int i = 0; i < n; ++i) {
803
233M
        SkColor c;
804
233M
        fuzz->next(&c);
805
233M
        data[i] = SkPreMultiplyColor(c);
806
233M
    }
807
8.49k
    (void)data.release();
808
8.49k
    return SkImages::RasterFromPixmap(
809
8.49k
            pixmap, [](const void* p, void*) { sk_free(const_cast<void*>(p)); }, nullptr);
810
8.49k
}
811
812
template <typename T>
813
267k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
267k
    T value;
815
267k
    fuzz->nextEnum(&value, maxv);
816
267k
    return value;
817
267k
}
FuzzCanvas.cpp:SkBlendMode make_fuzz_enum_range<SkBlendMode>(Fuzz*, SkBlendMode)
Line
Count
Source
813
67.3k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
67.3k
    T value;
815
67.3k
    fuzz->nextEnum(&value, maxv);
816
67.3k
    return value;
817
67.3k
}
FuzzCanvas.cpp:SkPaint::Style make_fuzz_enum_range<SkPaint::Style>(Fuzz*, SkPaint::Style)
Line
Count
Source
813
67.3k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
67.3k
    T value;
815
67.3k
    fuzz->nextEnum(&value, maxv);
816
67.3k
    return value;
817
67.3k
}
FuzzCanvas.cpp:SkPaint::Cap make_fuzz_enum_range<SkPaint::Cap>(Fuzz*, SkPaint::Cap)
Line
Count
Source
813
42.6k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
42.6k
    T value;
815
42.6k
    fuzz->nextEnum(&value, maxv);
816
42.6k
    return value;
817
42.6k
}
FuzzCanvas.cpp:SkPaint::Join make_fuzz_enum_range<SkPaint::Join>(Fuzz*, SkPaint::Join)
Line
Count
Source
813
42.6k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
42.6k
    T value;
815
42.6k
    fuzz->nextEnum(&value, maxv);
816
42.6k
    return value;
817
42.6k
}
FuzzCanvas.cpp:SkFontHinting make_fuzz_enum_range<SkFontHinting>(Fuzz*, SkFontHinting)
Line
Count
Source
813
8.32k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
8.32k
    T value;
815
8.32k
    fuzz->nextEnum(&value, maxv);
816
8.32k
    return value;
817
8.32k
}
FuzzCanvas.cpp:SkFont::Edging make_fuzz_enum_range<SkFont::Edging>(Fuzz*, SkFont::Edging)
Line
Count
Source
813
8.32k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
8.32k
    T value;
815
8.32k
    fuzz->nextEnum(&value, maxv);
816
8.32k
    return value;
817
8.32k
}
FuzzCanvas.cpp:SkTextEncoding make_fuzz_enum_range<SkTextEncoding>(Fuzz*, SkTextEncoding)
Line
Count
Source
813
31.3k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
31.3k
    T value;
815
31.3k
    fuzz->nextEnum(&value, maxv);
816
31.3k
    return value;
817
31.3k
}
818
819
90.5k
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
820
90.5k
    if (!fuzz || !paint || depth <= 0) {
821
23.1k
        return;
822
23.1k
    }
823
824
67.3k
    paint->setAntiAlias(    make_fuzz_t<bool>(fuzz));
825
67.3k
    paint->setDither(       make_fuzz_t<bool>(fuzz));
826
67.3k
    paint->setColor(        make_fuzz_t<SkColor>(fuzz));
827
67.3k
    paint->setBlendMode(    make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
828
67.3k
    paint->setStyle(        make_fuzz_enum_range<SkPaint::Style>(fuzz,
829
67.3k
                                                 SkPaint::Style::kStrokeAndFill_Style));
830
67.3k
    paint->setShader(       make_fuzz_shader(fuzz, depth - 1));
831
67.3k
    paint->setPathEffect(   make_fuzz_patheffect(fuzz, depth - 1));
832
67.3k
    paint->setMaskFilter(   make_fuzz_maskfilter(fuzz));
833
67.3k
    paint->setImageFilter(  make_fuzz_imageFilter(fuzz, depth - 1));
834
67.3k
    paint->setColorFilter(  make_fuzz_colorfilter(fuzz, depth - 1));
835
836
67.3k
    if (paint->getStyle() != SkPaint::kFill_Style) {
837
42.6k
        paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
838
42.6k
        paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
839
42.6k
        paint->setStrokeCap(  make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
840
42.6k
        paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
841
42.6k
    }
842
67.3k
}
843
844
8.32k
static SkFont fuzz_font(Fuzz* fuzz) {
845
8.32k
    SkFont font;
846
8.32k
    font.setTypeface(           make_fuzz_typeface(fuzz));
847
8.32k
    font.setSize(               make_fuzz_t<SkScalar>(fuzz));
848
8.32k
    font.setScaleX(             make_fuzz_t<SkScalar>(fuzz));
849
8.32k
    font.setSkewX(              make_fuzz_t<SkScalar>(fuzz));
850
8.32k
    font.setLinearMetrics(      make_fuzz_t<bool>(fuzz));
851
8.32k
    font.setSubpixel(           make_fuzz_t<bool>(fuzz));
852
8.32k
    font.setEmbeddedBitmaps(    make_fuzz_t<bool>(fuzz));
853
8.32k
    font.setForceAutoHinting(   make_fuzz_t<bool>(fuzz));
854
8.32k
    font.setEmbolden(           make_fuzz_t<bool>(fuzz));
855
8.32k
    font.setHinting(            make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
856
8.32k
    font.setEdging(             make_fuzz_enum_range<SkFont::Edging>(fuzz,
857
8.32k
                                                     SkFont::Edging::kSubpixelAntiAlias));
858
8.32k
    return font;
859
8.32k
}
860
861
31.3k
static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
862
31.3k
    return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
863
31.3k
}
864
865
constexpr int kMaxGlyphCount = 30;
866
867
31.3k
static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
868
31.3k
    SkTDArray<uint8_t> array;
869
31.3k
    if (SkTextEncoding::kGlyphID == encoding) {
870
0
        int glyphRange = font.getTypeface()->countGlyphs();
871
0
        if (glyphRange == 0) {
872
            // Some fuzzing environments have no fonts, so empty array is the best
873
            // we can do.
874
0
            return array;
875
0
        }
876
0
        int glyphCount;
877
0
        fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
878
0
        SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
879
0
        for (int i = 0; i < glyphCount; ++i) {
880
0
            fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
881
0
        }
882
0
        return array;
883
0
    }
884
31.3k
    static const SkUnichar ranges[][2] = {
885
31.3k
        {0x0020, 0x007F},
886
31.3k
        {0x00A1, 0x0250},
887
31.3k
        {0x0400, 0x0500},
888
31.3k
    };
889
31.3k
    int32_t count = 0;
890
125k
    for (size_t i = 0; i < std::size(ranges); ++i) {
891
94.1k
        count += (ranges[i][1] - ranges[i][0]);
892
94.1k
    }
893
31.3k
    constexpr int kMaxLength = kMaxGlyphCount;
894
31.3k
    SkUnichar buffer[kMaxLength];
895
31.3k
    int length;
896
31.3k
    fuzz->nextRange(&length, 1, kMaxLength);
897
437k
    for (int j = 0; j < length; ++j) {
898
406k
        int32_t value;
899
406k
        fuzz->nextRange(&value, 0, count - 1);
900
852k
        for (size_t i = 0; i < std::size(ranges); ++i) {
901
852k
            if (value + ranges[i][0] < ranges[i][1]) {
902
406k
                buffer[j] = value + ranges[i][0];
903
406k
                break;
904
445k
            } else {
905
445k
                value -= (ranges[i][1] - ranges[i][0]);
906
445k
            }
907
852k
        }
908
406k
    }
909
31.3k
    switch (encoding) {
910
16.6k
        case SkTextEncoding::kUTF8: {
911
16.6k
            size_t utf8len = 0;
912
131k
            for (int j = 0; j < length; ++j) {
913
114k
                utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
914
114k
            }
915
16.6k
            char* ptr = (char*)array.append(utf8len);
916
131k
            for (int j = 0; j < length; ++j) {
917
114k
                ptr += SkUTF::ToUTF8(buffer[j], ptr);
918
114k
            }
919
16.6k
        } break;
920
182
        case SkTextEncoding::kUTF16: {
921
182
            size_t utf16len = 0;
922
3.17k
            for (int j = 0; j < length; ++j) {
923
2.99k
                utf16len += SkUTF::ToUTF16(buffer[j]);
924
2.99k
            }
925
182
            uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
926
3.17k
            for (int j = 0; j < length; ++j) {
927
2.99k
                ptr += SkUTF::ToUTF16(buffer[j], ptr);
928
2.99k
            }
929
182
        } break;
930
14.5k
        case SkTextEncoding::kUTF32:
931
14.5k
            memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
932
14.5k
            break;
933
0
        default:
934
0
            SkASSERT(false);
935
0
            break;
936
31.3k
    }
937
31.3k
    return array;
938
31.3k
}
939
940
2.59k
static std::string make_fuzz_string(Fuzz* fuzz) {
941
2.59k
    int len;
942
2.59k
    fuzz->nextRange(&len, 0, kMaxGlyphCount);
943
2.59k
    std::string str(len, 0);
944
69.5k
    for (int i = 0; i < len; i++) {
945
66.9k
        fuzz->next(&str[i]);
946
66.9k
    }
947
2.59k
    return str;
948
2.59k
}
949
950
4.25k
static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
951
4.25k
    SkTextBlobBuilder textBlobBuilder;
952
4.25k
    int8_t runCount;
953
4.25k
    fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
954
29.8k
    while (runCount-- > 0) {
955
25.6k
        SkFont font = ToolUtils::DefaultFont();
956
25.6k
        SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
957
25.6k
        font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
958
25.6k
        SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
959
25.6k
        int glyphCount = font.countText(text.begin(), SkToSizeT(text.size()), encoding);
960
25.6k
        SkASSERT(glyphCount <= kMaxGlyphCount);
961
25.6k
        SkScalar x, y;
962
25.6k
        const SkTextBlobBuilder::RunBuffer* buffer;
963
25.6k
        uint8_t runType;
964
25.6k
        fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
965
25.6k
        const void* textPtr = text.begin();
966
25.6k
        size_t textLen =  SkToSizeT(text.size());
967
25.6k
        switch (runType) {
968
13.4k
            case 0:
969
13.4k
                fuzz->next(&x, &y);
970
                // TODO: Test other variations of this.
971
13.4k
                buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
972
13.4k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
973
13.4k
                break;
974
1.65k
            case 1:
975
1.65k
                fuzz->next(&y);
976
                // TODO: Test other variations of this.
977
1.65k
                buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
978
1.65k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
979
1.65k
                fuzz->nextN(buffer->pos, glyphCount);
980
1.65k
                break;
981
10.4k
            case 2:
982
                // TODO: Test other variations of this.
983
10.4k
                buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
984
10.4k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
985
10.4k
                fuzz->nextN(buffer->pos, glyphCount * 2);
986
10.4k
                break;
987
0
            default:
988
0
                SkASSERT(false);
989
0
                break;
990
25.6k
        }
991
25.6k
    }
992
4.25k
    return textBlobBuilder.make();
993
4.25k
}
994
995
61.6k
static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
996
61.6k
    if (!fuzz || !canvas || depth <= 0) {
997
3.51k
        return;
998
3.51k
    }
999
58.0k
    SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1000
58.0k
    unsigned N;
1001
58.0k
    fuzz->nextRange(&N, 0, 2000);
1002
379k
    for (unsigned loop = 0; loop < N; ++loop) {
1003
371k
        if (fuzz->exhausted()) {
1004
50.0k
            return;
1005
50.0k
        }
1006
321k
        SkPaint paint;
1007
321k
        SkFont font = ToolUtils::DefaultFont();
1008
321k
        unsigned drawCommand;
1009
321k
        fuzz->nextRange(&drawCommand, 0, 62);
1010
321k
        switch (drawCommand) {
1011
125k
            case 0:
1012
125k
#if defined(SK_GANESH)
1013
125k
                if (auto dContext = GrAsDirectContext(canvas->recordingContext())) {
1014
15.8k
                    dContext->flushAndSubmit();
1015
15.8k
                }
1016
125k
#endif
1017
125k
                break;
1018
3.61k
            case 1:
1019
3.61k
                canvas->save();
1020
3.61k
                break;
1021
781
            case 2: {
1022
781
                SkRect bounds;
1023
781
                fuzz->next(&bounds);
1024
781
                fuzz_paint(fuzz, &paint, depth - 1);
1025
781
                canvas->saveLayer(&bounds, &paint);
1026
781
                break;
1027
0
            }
1028
378
            case 3: {
1029
378
                SkRect bounds;
1030
378
                fuzz->next(&bounds);
1031
378
                canvas->saveLayer(&bounds, nullptr);
1032
378
                break;
1033
0
            }
1034
1.79k
            case 4:
1035
1.79k
                fuzz_paint(fuzz, &paint, depth - 1);
1036
1.79k
                canvas->saveLayer(nullptr, &paint);
1037
1.79k
                break;
1038
12.4k
            case 5:
1039
12.4k
                canvas->saveLayer(nullptr, nullptr);
1040
12.4k
                break;
1041
17.7k
            case 6: {
1042
17.7k
                uint8_t alpha;
1043
17.7k
                fuzz->next(&alpha);
1044
17.7k
                canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1045
17.7k
                break;
1046
0
            }
1047
876
            case 7: {
1048
876
                SkRect bounds;
1049
876
                uint8_t alpha;
1050
876
                fuzz->next(&bounds, &alpha);
1051
876
                canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1052
876
                break;
1053
0
            }
1054
7.67k
            case 8: {
1055
7.67k
                SkCanvas::SaveLayerRec saveLayerRec;
1056
7.67k
                SkRect bounds;
1057
7.67k
                if (make_fuzz_t<bool>(fuzz)) {
1058
743
                    fuzz->next(&bounds);
1059
743
                    saveLayerRec.fBounds = &bounds;
1060
743
                }
1061
7.67k
                if (make_fuzz_t<bool>(fuzz)) {
1062
186
                    fuzz_paint(fuzz, &paint, depth - 1);
1063
186
                    saveLayerRec.fPaint = &paint;
1064
186
                }
1065
7.67k
                sk_sp<SkImageFilter> imageFilter;
1066
7.67k
                if (make_fuzz_t<bool>(fuzz)) {
1067
2.68k
                    imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1068
2.68k
                    saveLayerRec.fBackdrop = imageFilter.get();
1069
2.68k
                }
1070
                // _DumpCanvas can't handle this.
1071
                // if (make_fuzz_t<bool>(fuzz)) {
1072
                //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1073
                // }
1074
1075
7.67k
                canvas->saveLayer(saveLayerRec);
1076
7.67k
                break;
1077
0
            }
1078
1.75k
            case 9:
1079
1.75k
                canvas->restore();
1080
1.75k
                break;
1081
2.76k
            case 10: {
1082
2.76k
                int saveCount;
1083
2.76k
                fuzz->next(&saveCount);
1084
2.76k
                canvas->restoreToCount(saveCount);
1085
2.76k
                break;
1086
0
            }
1087
1.00k
            case 11: {
1088
1.00k
                SkScalar x, y;
1089
1.00k
                fuzz->next(&x, &y);
1090
1.00k
                canvas->translate(x, y);
1091
1.00k
                break;
1092
0
            }
1093
1.11k
            case 12: {
1094
1.11k
                SkScalar x, y;
1095
1.11k
                fuzz->next(&x, &y);
1096
1.11k
                canvas->scale(x, y);
1097
1.11k
                break;
1098
0
            }
1099
1.71k
            case 13: {
1100
1.71k
                SkScalar v;
1101
1.71k
                fuzz->next(&v);
1102
1.71k
                canvas->rotate(v);
1103
1.71k
                break;
1104
0
            }
1105
472
            case 14: {
1106
472
                SkScalar x, y, v;
1107
472
                fuzz->next(&x, &y, &v);
1108
472
                canvas->rotate(v, x, y);
1109
472
                break;
1110
0
            }
1111
2.43k
            case 15: {
1112
2.43k
                SkScalar x, y;
1113
2.43k
                fuzz->next(&x, &y);
1114
2.43k
                canvas->skew(x, y);
1115
2.43k
                break;
1116
0
            }
1117
1.15k
            case 16: {
1118
1.15k
                SkMatrix mat;
1119
1.15k
                FuzzNiceMatrix(fuzz, &mat);
1120
1.15k
                canvas->concat(mat);
1121
1.15k
                break;
1122
0
            }
1123
1.30k
            case 17: {
1124
1.30k
                SkMatrix mat;
1125
1.30k
                FuzzNiceMatrix(fuzz, &mat);
1126
1.30k
                canvas->setMatrix(mat);
1127
1.30k
                break;
1128
0
            }
1129
1.42k
            case 18:
1130
1.42k
                canvas->resetMatrix();
1131
1.42k
                break;
1132
3.53k
            case 19: {
1133
3.53k
                SkRect r;
1134
3.53k
                int op;
1135
3.53k
                bool doAntiAlias;
1136
3.53k
                fuzz->next(&r, &doAntiAlias);
1137
3.53k
                fuzz->nextRange(&op, 0, 1);
1138
3.53k
                r.sort();
1139
3.53k
                canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1140
3.53k
                break;
1141
0
            }
1142
3.18k
            case 20: {
1143
3.18k
                SkRRect rr;
1144
3.18k
                int op;
1145
3.18k
                bool doAntiAlias;
1146
3.18k
                FuzzNiceRRect(fuzz, &rr);
1147
3.18k
                fuzz->next(&doAntiAlias);
1148
3.18k
                fuzz->nextRange(&op, 0, 1);
1149
3.18k
                canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1150
3.18k
                break;
1151
0
            }
1152
11.0k
            case 21: {
1153
11.0k
                SkPath path;
1154
11.0k
                FuzzNicePath(fuzz, &path, 30);
1155
11.0k
                int op;
1156
11.0k
                bool doAntiAlias;
1157
11.0k
                fuzz->next(&doAntiAlias);
1158
11.0k
                fuzz->nextRange(&op, 0, 1);
1159
11.0k
                canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1160
11.0k
                break;
1161
0
            }
1162
4.40k
            case 22: {
1163
4.40k
                SkRegion region;
1164
4.40k
                int op;
1165
4.40k
                fuzz->next(&region);
1166
4.40k
                fuzz->nextRange(&op, 0, 1);
1167
4.40k
                canvas->clipRegion(region, (SkClipOp)op);
1168
4.40k
                break;
1169
0
            }
1170
752
            case 23:
1171
752
                fuzz_paint(fuzz, &paint, depth - 1);
1172
752
                canvas->drawPaint(paint);
1173
752
                break;
1174
4.40k
            case 24: {
1175
4.40k
                fuzz_paint(fuzz, &paint, depth - 1);
1176
4.40k
                SkCanvas::PointMode pointMode;
1177
4.40k
                fuzz->nextRange(&pointMode,
1178
4.40k
                                SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
1179
4.40k
                size_t count;
1180
4.40k
                constexpr int kMaxCount = 30;
1181
4.40k
                fuzz->nextRange(&count, 0, kMaxCount);
1182
4.40k
                SkPoint pts[kMaxCount];
1183
4.40k
                fuzz->nextN(pts, count);
1184
4.40k
                canvas->drawPoints(pointMode, count, pts, paint);
1185
4.40k
                break;
1186
0
            }
1187
310
            case 25: {
1188
310
                fuzz_paint(fuzz, &paint, depth - 1);
1189
310
                SkRect r;
1190
310
                fuzz->next(&r);
1191
310
                if (!r.isFinite()) {
1192
63
                    break;
1193
63
                }
1194
247
                canvas->drawRect(r, paint);
1195
247
                break;
1196
310
            }
1197
307
            case 26: {
1198
307
                fuzz_paint(fuzz, &paint, depth - 1);
1199
307
                SkRegion region;
1200
307
                fuzz->next(&region);
1201
307
                canvas->drawRegion(region, paint);
1202
307
                break;
1203
310
            }
1204
563
            case 27: {
1205
563
                fuzz_paint(fuzz, &paint, depth - 1);
1206
563
                SkRect r;
1207
563
                fuzz->next(&r);
1208
563
                if (!r.isFinite()) {
1209
33
                    break;
1210
33
                }
1211
530
                canvas->drawOval(r, paint);
1212
530
                break;
1213
563
            }
1214
160
            case 28: break; // must have deleted this some time earlier
1215
555
            case 29: {
1216
555
                fuzz_paint(fuzz, &paint, depth - 1);
1217
555
                SkRRect rr;
1218
555
                FuzzNiceRRect(fuzz, &rr);
1219
555
                canvas->drawRRect(rr, paint);
1220
555
                break;
1221
563
            }
1222
680
            case 30: {
1223
680
                fuzz_paint(fuzz, &paint, depth - 1);
1224
680
                SkRRect orr, irr;
1225
680
                FuzzNiceRRect(fuzz, &orr);
1226
680
                FuzzNiceRRect(fuzz, &irr);
1227
680
                if (orr.getBounds().contains(irr.getBounds())) {
1228
271
                    canvas->drawDRRect(orr, irr, paint);
1229
271
                }
1230
680
                break;
1231
563
            }
1232
62
            case 31: {
1233
62
                fuzz_paint(fuzz, &paint, depth - 1);
1234
62
                SkRect r;
1235
62
                SkScalar start, sweep;
1236
62
                bool useCenter;
1237
62
                fuzz->next(&r, &start, &sweep, &useCenter);
1238
62
                canvas->drawArc(r, start, sweep, useCenter, paint);
1239
62
                break;
1240
563
            }
1241
5.48k
            case 32: {
1242
5.48k
                fuzz_paint(fuzz, &paint, depth - 1);
1243
5.48k
                SkPath path;
1244
5.48k
                FuzzNicePath(fuzz, &path, 60);
1245
5.48k
                canvas->drawPath(path, paint);
1246
5.48k
                break;
1247
563
            }
1248
4.55k
            case 33: {
1249
4.55k
                sk_sp<SkImage> img = make_fuzz_image(fuzz);
1250
4.55k
                SkScalar left, top;
1251
4.55k
                bool usePaint;
1252
4.55k
                fuzz->next(&left, &top, &usePaint);
1253
4.55k
                if (usePaint) {
1254
434
                    fuzz_paint(fuzz, &paint, depth - 1);
1255
434
                }
1256
4.55k
                canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
1257
4.55k
                                  usePaint ? &paint : nullptr);
1258
4.55k
                break;
1259
563
            }
1260
268
            case 35: {
1261
268
                auto img = make_fuzz_image(fuzz);
1262
268
                SkIRect src;
1263
268
                SkRect dst;
1264
268
                bool usePaint;
1265
268
                fuzz->next(&src, &dst, &usePaint);
1266
268
                if (usePaint) {
1267
75
                    fuzz_paint(fuzz, &paint, depth - 1);
1268
75
                }
1269
268
                SkCanvas::SrcRectConstraint constraint =
1270
268
                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1271
268
                                                : SkCanvas::kFast_SrcRectConstraint;
1272
268
                canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
1273
268
                                      usePaint ? &paint : nullptr, constraint);
1274
268
                break;
1275
563
            }
1276
1.20k
            case 37: {
1277
1.20k
                auto img = make_fuzz_image(fuzz);
1278
1.20k
                SkIRect center;
1279
1.20k
                SkRect dst;
1280
1.20k
                bool usePaint;
1281
1.20k
                fuzz->next(&usePaint);
1282
1.20k
                if (usePaint) {
1283
213
                    fuzz_paint(fuzz, &paint, depth - 1);
1284
213
                }
1285
1.20k
                if (make_fuzz_t<bool>(fuzz)) {
1286
201
                    fuzz->next(&center);
1287
1.00k
                } else {  // Make valid center, see SkLatticeIter::Valid().
1288
1.00k
                    fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1289
1.00k
                    fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1290
1.00k
                    fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1291
1.00k
                    fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1292
1.00k
                }
1293
1.20k
                fuzz->next(&dst);
1294
1.20k
                canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
1295
1.20k
                                      usePaint ? &paint : nullptr);
1296
1.20k
                break;
1297
563
            }
1298
886
            case 44: {
1299
886
                auto img = make_fuzz_image(fuzz);
1300
886
                bool usePaint;
1301
886
                SkRect dst;
1302
886
                fuzz->next(&usePaint, &dst);
1303
886
                if (usePaint) {
1304
326
                    fuzz_paint(fuzz, &paint, depth - 1);
1305
326
                }
1306
886
                constexpr int kMax = 6;
1307
886
                int xDivs[kMax], yDivs[kMax];
1308
886
                SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1309
886
                fuzz->nextRange(&lattice.fXCount, 2, kMax);
1310
886
                fuzz->nextRange(&lattice.fYCount, 2, kMax);
1311
886
                fuzz->nextN(xDivs, lattice.fXCount);
1312
886
                fuzz->nextN(yDivs, lattice.fYCount);
1313
886
                canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
1314
886
                                         usePaint ? &paint : nullptr);
1315
886
                break;
1316
563
            }
1317
5.73k
            case 45: {
1318
5.73k
                fuzz_paint(fuzz, &paint, depth - 1);
1319
5.73k
                font = fuzz_font(fuzz);
1320
5.73k
                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
1321
5.73k
                SkScalar x, y;
1322
5.73k
                fuzz->next(&x, &y);
1323
5.73k
                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
1324
5.73k
                canvas->drawSimpleText(text.begin(), SkToSizeT(text.size()), encoding, x, y,
1325
5.73k
                                       font, paint);
1326
5.73k
                break;
1327
563
            }
1328
23
            case 46: {
1329
                // was drawPosText
1330
23
                break;
1331
563
            }
1332
152
            case 47: {
1333
                // was drawPosTextH
1334
152
                break;
1335
563
            }
1336
229
            case 48: {
1337
                // was drawtextonpath
1338
229
                break;
1339
563
            }
1340
118
            case 49: {
1341
                // was drawtextonpath
1342
118
                break;
1343
563
            }
1344
450
            case 50: {
1345
                // was drawTextRSXform
1346
450
                break;
1347
563
            }
1348
4.25k
            case 51: {
1349
4.25k
                sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
1350
4.25k
                fuzz_paint(fuzz, &paint, depth - 1);
1351
4.25k
                SkScalar x, y;
1352
4.25k
                fuzz->next(&x, &y);
1353
4.25k
                canvas->drawTextBlob(blob, x, y, paint);
1354
4.25k
                break;
1355
563
            }
1356
16.2k
            case 52: {
1357
16.2k
                SkMatrix matrix;
1358
16.2k
                bool usePaint, useMatrix;
1359
16.2k
                fuzz->next(&usePaint, &useMatrix);
1360
16.2k
                if (usePaint) {
1361
1.67k
                    fuzz_paint(fuzz, &paint, depth - 1);
1362
1.67k
                }
1363
16.2k
                if (useMatrix) {
1364
2.23k
                    FuzzNiceMatrix(fuzz, &matrix);
1365
2.23k
                }
1366
16.2k
                auto pic = make_fuzz_picture(fuzz, depth - 1);
1367
16.2k
                canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1368
16.2k
                                    usePaint ? &paint : nullptr);
1369
16.2k
                break;
1370
563
            }
1371
1.12k
            case 53: {
1372
1.12k
                fuzz_paint(fuzz, &paint, depth - 1);
1373
1.12k
                SkVertices::VertexMode vertexMode;
1374
1.12k
                SkBlendMode blendMode;
1375
1.12k
                fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1376
1.12k
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
1377
1.12k
                constexpr int kMaxCount = 100;
1378
1.12k
                int vertexCount;
1379
1.12k
                SkPoint vertices[kMaxCount];
1380
1.12k
                SkPoint texs[kMaxCount];
1381
1.12k
                SkColor colors[kMaxCount];
1382
1.12k
                fuzz->nextRange(&vertexCount, 3, kMaxCount);
1383
1.12k
                fuzz->nextN(vertices, vertexCount);
1384
1.12k
                bool useTexs, useColors;
1385
1.12k
                fuzz->next(&useTexs, &useColors);
1386
1.12k
                if (useTexs) {
1387
253
                    fuzz->nextN(texs, vertexCount);
1388
253
                }
1389
1.12k
                if (useColors) {
1390
214
                    fuzz->nextN(colors, vertexCount);
1391
214
                }
1392
1.12k
                int indexCount = 0;
1393
1.12k
                uint16_t indices[kMaxCount * 2];
1394
1.12k
                if (make_fuzz_t<bool>(fuzz)) {
1395
243
                    fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1396
11.9k
                    for (int index = 0; index < indexCount; ++index) {
1397
11.6k
                        fuzz->nextRange(&indices[index], 0, vertexCount - 1);
1398
11.6k
                    }
1399
243
                }
1400
1.12k
                canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1401
1.12k
                                                          useTexs ? texs : nullptr,
1402
1.12k
                                                          useColors ? colors : nullptr,
1403
1.12k
                                                          indexCount, indices),
1404
1.12k
                                     blendMode, paint);
1405
1.12k
                break;
1406
563
            }
1407
2.51k
            case 54: {
1408
2.51k
                SkColor color;
1409
2.51k
                SkBlendMode blendMode;
1410
2.51k
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1411
2.51k
                fuzz->next(&color);
1412
2.51k
                canvas->drawColor(color, blendMode);
1413
2.51k
                break;
1414
563
            }
1415
922
            case 55: {
1416
922
                SkColor4f color;
1417
922
                SkBlendMode blendMode;
1418
922
                float R, G, B, Alpha;
1419
922
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1420
922
                fuzz->nextRange(&R, -1, 2);
1421
922
                fuzz->nextRange(&G, -1, 2);
1422
922
                fuzz->nextRange(&B, -1, 2);
1423
922
                fuzz->nextRange(&Alpha, 0, 1);
1424
922
                color = {R, G, B, Alpha};
1425
922
                canvas->drawColor(color, blendMode);
1426
922
                break;
1427
563
            }
1428
1.55k
            case 56: {
1429
1.55k
                fuzz_paint(fuzz, &paint, depth - 1);
1430
1.55k
                SkPoint p0, p1;
1431
1.55k
                fuzz->next(&p0, &p1);
1432
1.55k
                canvas->drawLine(p0, p1, paint);
1433
1.55k
                break;
1434
563
            }
1435
189
            case 57: {
1436
189
                fuzz_paint(fuzz, &paint, depth - 1);
1437
189
                SkIRect r;
1438
189
                fuzz->next(&r);
1439
189
                canvas->drawIRect(r, paint);
1440
189
                break;
1441
563
            }
1442
574
            case 58: {
1443
574
                fuzz_paint(fuzz, &paint, depth - 1);
1444
574
                SkScalar radius;
1445
574
                SkPoint center;
1446
574
                fuzz->next(&radius, &center);
1447
574
                canvas->drawCircle(center, radius, paint);
1448
574
                break;
1449
563
            }
1450
483
            case 59: {
1451
483
                fuzz_paint(fuzz, &paint, depth - 1);
1452
483
                SkRect oval;
1453
483
                SkScalar startAngle, sweepAngle;
1454
483
                bool useCenter;
1455
483
                fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
1456
483
                canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1457
483
                break;
1458
563
            }
1459
932
            case 60: {
1460
932
                fuzz_paint(fuzz, &paint, depth - 1);
1461
932
                SkRect rect;
1462
932
                SkScalar rx, ry;
1463
932
                fuzz->next(&rect, &rx, &ry);
1464
932
                canvas->drawRoundRect(rect, rx, ry, paint);
1465
932
                break;
1466
563
            }
1467
2.59k
            case 61: {
1468
2.59k
                fuzz_paint(fuzz, &paint, depth - 1);
1469
2.59k
                font = fuzz_font(fuzz);
1470
2.59k
                std::string str = make_fuzz_string(fuzz);
1471
2.59k
                SkScalar x, y;
1472
2.59k
                fuzz->next(&x, &y);
1473
2.59k
                canvas->drawString(str.c_str(), x, y, font, paint);
1474
2.59k
                break;
1475
563
            }
1476
54.4k
            case 62: {
1477
54.4k
                fuzz_paint(fuzz, &paint, depth - 1);
1478
54.4k
                SkPoint cubics[12];
1479
54.4k
                SkColor colors[4];
1480
54.4k
                SkPoint texCoords[4];
1481
54.4k
                bool useTexCoords;
1482
54.4k
                fuzz->nextN(cubics, 12);
1483
54.4k
                fuzz->nextN(colors, 4);
1484
54.4k
                fuzz->next(&useTexCoords);
1485
54.4k
                if (useTexCoords) {
1486
9.65k
                    fuzz->nextN(texCoords, 4);
1487
9.65k
                }
1488
54.4k
                SkBlendMode mode;
1489
54.4k
                fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
1490
54.4k
                canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
1491
54.4k
                    , mode, paint);
1492
54.4k
                break;
1493
563
            }
1494
766
            default:
1495
766
                SkASSERT(false);
1496
766
                break;
1497
321k
        }
1498
321k
    }
1499
58.0k
}
1500
1501
23.4k
static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1502
23.4k
    SkScalar w, h;
1503
23.4k
    fuzz->next(&w, &h);
1504
23.4k
    SkPictureRecorder pictureRecorder;
1505
23.4k
    fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1506
23.4k
    return pictureRecorder.finishRecordingAsPicture();
1507
23.4k
}
1508
1509
10.3k
DEF_FUZZ(NullCanvas, fuzz) {
1510
10.3k
    fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1511
10.3k
}
1512
1513
constexpr SkISize kCanvasSize = {128, 160};
1514
1515
20.1k
DEF_FUZZ(RasterN32Canvas, fuzz) {
1516
20.1k
    auto surface = SkSurfaces::Raster(
1517
20.1k
            SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
1518
20.1k
    if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
1519
20.1k
    fuzz_canvas(fuzz, surface->getCanvas());
1520
20.1k
}
1521
1522
0
DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1523
0
    SkPictureRecorder recorder;
1524
0
    fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1525
0
                                              SkIntToScalar(kCanvasSize.height())));
1526
0
    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1527
0
    if (!pic) { fuzz->signalBug(); }
1528
0
    SkSerialProcs sProcs;
1529
0
    sProcs.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
1530
0
        return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
1531
0
    };
1532
0
    sk_sp<SkData> data = pic->serialize(&sProcs);
1533
0
    if (!data) { fuzz->signalBug(); }
1534
0
    SkReadBuffer rb(data->data(), data->size());
1535
0
    SkCodecs::Register(SkPngDecoder::Decoder());
1536
0
    auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
1537
0
    if (!deserialized) { fuzz->signalBug(); }
1538
0
    auto surface = SkSurfaces::Raster(
1539
0
            SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
1540
0
    SkASSERT(surface && surface->getCanvas());
1541
0
    surface->getCanvas()->drawPicture(deserialized);
1542
0
}
1543
1544
30
DEF_FUZZ(ImageFilter, fuzz) {
1545
30
    SkBitmap bitmap;
1546
30
    if (!bitmap.tryAllocN32Pixels(256, 256)) {
1547
30
        SkDEBUGF("Could not allocate 256x256 bitmap in ImageFilter");
1548
30
        return;
1549
30
    }
1550
1551
0
    auto fil = make_fuzz_imageFilter(fuzz, 20);
1552
1553
0
    SkPaint paint;
1554
0
    paint.setImageFilter(fil);
1555
0
    SkCanvas canvas(bitmap);
1556
0
    canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1557
0
}
1558
1559
1560
//SkRandom _rand;
1561
#define SK_ADD_RANDOM_BIT_FLIPS
1562
1563
0
DEF_FUZZ(SerializedImageFilter, fuzz) {
1564
0
    SkBitmap bitmap;
1565
0
    if (!bitmap.tryAllocN32Pixels(256, 256)) {
1566
0
        SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
1567
0
        return;
1568
0
    }
1569
1570
0
    auto filter = make_fuzz_imageFilter(fuzz, 20);
1571
0
    if (!filter) {
1572
0
        return;
1573
0
    }
1574
0
    auto data = filter->serialize();
1575
0
    const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1576
0
    size_t len = data->size();
1577
0
#ifdef SK_ADD_RANDOM_BIT_FLIPS
1578
0
    unsigned char* p = const_cast<unsigned char*>(ptr);
1579
0
    for (size_t i = 0; i < len; ++i, ++p) {
1580
0
        uint8_t j;
1581
0
        fuzz->nextRange(&j, 1, 250);
1582
0
        if (j == 1) { // 0.4% of the time, flip a bit or byte
1583
0
            uint8_t k;
1584
0
            fuzz->nextRange(&k, 1, 10);
1585
0
            if (k == 1) { // Then 10% of the time, change a whole byte
1586
0
                uint8_t s;
1587
0
                fuzz->nextRange(&s, 0, 2);
1588
0
                switch(s) {
1589
0
                case 0:
1590
0
                    *p ^= 0xFF; // Flip entire byte
1591
0
                    break;
1592
0
                case 1:
1593
0
                    *p = 0xFF; // Set all bits to 1
1594
0
                    break;
1595
0
                case 2:
1596
0
                    *p = 0x00; // Set all bits to 0
1597
0
                    break;
1598
0
                }
1599
0
            } else {
1600
0
                uint8_t s;
1601
0
                fuzz->nextRange(&s, 0, 7);
1602
0
                *p ^= (1 << 7);
1603
0
            }
1604
0
        }
1605
0
    }
1606
0
#endif // SK_ADD_RANDOM_BIT_FLIPS
1607
0
    auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1608
1609
    // uncomment below to write out a serialized image filter (to make corpus
1610
    // for -t filter_fuzz)
1611
    // SkString s("./serialized_filters/sf");
1612
    // s.appendU32(_rand.nextU());
1613
    // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1614
    // sk_fwrite(data->bytes(), data->size(), file);
1615
    // sk_fclose(file);
1616
1617
0
    SkPaint paint;
1618
0
    paint.setImageFilter(deserializedFil);
1619
1620
0
    SkCanvas canvas(bitmap);
1621
0
    canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
1622
0
    canvas.restore();
1623
0
}
1624
1625
#if defined(SK_GANESH)
1626
2.58k
static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
1627
2.58k
    SkASSERT(context);
1628
2.58k
    auto surface = SkSurfaces::RenderTarget(
1629
2.58k
            context,
1630
2.58k
            skgpu::Budgeted::kNo,
1631
2.58k
            SkImageInfo::Make(kCanvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1632
2.58k
    SkASSERT(surface && surface->getCanvas());
1633
2.58k
    fuzz_canvas(fuzz, surface->getCanvas());
1634
2.58k
}
1635
1636
2.58k
DEF_FUZZ(MockGPUCanvas, fuzz) {
1637
2.58k
    sk_gpu_test::GrContextFactory f;
1638
2.58k
    fuzz_ganesh(fuzz, f.get(skgpu::ContextType::kMock));
1639
2.58k
}
1640
#endif
1641
1642
#ifdef SK_GL
1643
static void dump_GPU_info(GrDirectContext* context) {
1644
    const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
1645
                                    ->glInterface();
1646
    const GrGLubyte* output;
1647
    GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1648
    SkDebugf("GL_RENDERER %s\n", (const char*) output);
1649
1650
    GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1651
    SkDebugf("GL_VENDOR %s\n", (const char*) output);
1652
1653
    GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1654
    SkDebugf("GL_VERSION %s\n", (const char*) output);
1655
}
1656
1657
DEF_FUZZ(NativeGLCanvas, fuzz) {
1658
    sk_gpu_test::GrContextFactory f;
1659
    auto context = f.get(skgpu::ContextType::kGL);
1660
    if (!context) {
1661
        context = f.get(skgpu::ContextType::kGLES);
1662
    }
1663
    if (FLAGS_gpuInfo) {
1664
        dump_GPU_info(context);
1665
    }
1666
    fuzz_ganesh(fuzz, context);
1667
}
1668
#endif
1669
1670
0
DEF_FUZZ(PDFCanvas, fuzz) {
1671
0
    SkNullWStream stream;
1672
0
    auto doc = SkPDF::MakeDocument(&stream);
1673
0
    fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1674
0
                                     SkIntToScalar(kCanvasSize.height())));
1675
0
}
1676
1677
// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1678
0
DEF_FUZZ(_DumpCanvas, fuzz) {
1679
0
    DebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
1680
0
    fuzz_canvas(fuzz, &debugCanvas);
1681
0
    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1682
0
    UrlDataManager dataManager(SkString("data"));
1683
0
    SkDynamicMemoryWStream stream;
1684
0
    SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1685
0
    writer.beginObject(); // root
1686
0
    debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
1687
0
    writer.endObject(); // root
1688
0
    writer.flush();
1689
0
    sk_sp<SkData> json = stream.detachAsData();
1690
0
    fwrite(json->data(), json->size(), 1, stdout);
1691
0
}
1692
1693
5.12k
DEF_FUZZ(SVGCanvas, fuzz) {
1694
5.12k
    SkNullWStream stream;
1695
5.12k
    SkRect bounds = SkRect::MakeIWH(150, 150);
1696
5.12k
    std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
1697
5.12k
    fuzz_canvas(fuzz, canvas.get());
1698
5.12k
}