Coverage Report

Created: 2024-09-14 07:19

/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/ganesh/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/ganesh/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
396k
inline T make_fuzz_t(Fuzz* fuzz) {
83
396k
    T t;
84
396k
    fuzz->next(&t);
85
396k
    return t;
86
396k
}
unsigned int make_fuzz_t<unsigned int>(Fuzz*)
Line
Count
Source
82
66.1k
inline T make_fuzz_t(Fuzz* fuzz) {
83
66.1k
    T t;
84
66.1k
    fuzz->next(&t);
85
66.1k
    return t;
86
66.1k
}
float make_fuzz_t<float>(Fuzz*)
Line
Count
Source
82
103k
inline T make_fuzz_t(Fuzz* fuzz) {
83
103k
    T t;
84
103k
    fuzz->next(&t);
85
103k
    return t;
86
103k
}
bool make_fuzz_t<bool>(Fuzz*)
Line
Count
Source
82
227k
inline T make_fuzz_t(Fuzz* fuzz) {
83
227k
    T t;
84
227k
    fuzz->next(&t);
85
227k
    return t;
86
227k
}
87
88
static sk_sp<SkImage> make_fuzz_image(Fuzz*);
89
90
static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
91
92
76.5k
static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
93
76.5k
    if (depth <= 0) {
94
13.3k
        return nullptr;
95
13.3k
    }
96
63.2k
    int colorFilterType;
97
63.2k
    fuzz->nextRange(&colorFilterType, 0, 8);
98
63.2k
    switch (colorFilterType) {
99
47.0k
        case 0:
100
47.0k
            return nullptr;
101
998
        case 1: {
102
998
            SkColor color;
103
998
            SkBlendMode mode;
104
998
            fuzz->next(&color);
105
998
            fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
106
998
            return SkColorFilters::Blend(color, mode);
107
0
        }
108
4.80k
        case 2: {
109
4.80k
            sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
110
4.80k
            if (!outer) {
111
497
                return nullptr;
112
497
            }
113
4.30k
            sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
114
            // makeComposed should be able to handle nullptr.
115
4.30k
            return outer->makeComposed(std::move(inner));
116
4.80k
        }
117
581
        case 3: {
118
581
            float array[20];
119
581
            fuzz->nextN(array, std::size(array));
120
581
            return SkColorFilters::Matrix(array);
121
4.80k
        }
122
593
        case 4: {
123
593
            SkColor mul, add;
124
593
            fuzz->next(&mul, &add);
125
593
            return SkColorFilters::Lighting(mul, add);
126
4.80k
        }
127
2.64k
        case 5: {
128
2.64k
            bool grayscale;
129
2.64k
            int invertStyle;
130
2.64k
            float contrast;
131
2.64k
            fuzz->next(&grayscale);
132
2.64k
            fuzz->nextRange(&invertStyle, 0, 2);
133
2.64k
            fuzz->nextRange(&contrast, -1.0f, 1.0f);
134
2.64k
            return SkHighContrastFilter::Make(SkHighContrastConfig(
135
2.64k
                    grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
136
4.80k
        }
137
652
        case 6:
138
652
            return SkLumaColorFilter::Make();
139
73
        case 7: {
140
73
            uint8_t table[256];
141
73
            fuzz->nextN(table, std::size(table));
142
73
            return SkColorFilters::Table(table);
143
4.80k
        }
144
5.80k
        case 8: {
145
5.80k
            uint8_t tableA[256];
146
5.80k
            uint8_t tableR[256];
147
5.80k
            uint8_t tableG[256];
148
5.80k
            uint8_t tableB[256];
149
5.80k
            fuzz->nextN(tableA, std::size(tableA));
150
5.80k
            fuzz->nextN(tableR, std::size(tableR));
151
5.80k
            fuzz->nextN(tableG, std::size(tableG));
152
5.80k
            fuzz->nextN(tableB, std::size(tableB));
153
5.80k
            return SkColorFilters::TableARGB(tableA, tableR, tableG, tableB);
154
4.80k
        }
155
0
        default:
156
0
            SkASSERT(false);
157
0
            break;
158
63.2k
    }
159
0
    return nullptr;
160
63.2k
}
161
162
1.05k
static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
163
1.05k
    SkScalar totalPos = 0;
164
8.36k
    for (int i = 0; i < colorCount; ++i) {
165
7.31k
        fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
166
7.31k
        totalPos += pos[i];
167
7.31k
    }
168
1.05k
    totalPos = 1.0f / totalPos;
169
8.36k
    for (int i = 0; i < colorCount; ++i) {
170
7.31k
        pos[i] *= totalPos;
171
7.31k
    }
172
    // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
173
1.05k
    pos[colorCount - 1] = 1.0f;
174
1.05k
}
175
176
123k
static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
177
123k
    sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
178
123k
    sk_sp<SkColorFilter> colorFilter(nullptr);
179
123k
    SkBitmap bitmap;
180
123k
    sk_sp<SkImage> img;
181
123k
    SkTileMode tmX, tmY;
182
123k
    bool useMatrix;
183
123k
    SkColor color;
184
123k
    SkMatrix matrix;
185
123k
    SkBlendMode blendMode;
186
123k
    int shaderType;
187
123k
    if (depth <= 0) {
188
28.9k
        return nullptr;
189
28.9k
    }
190
94.9k
    fuzz->nextRange(&shaderType, 0, 14);
191
94.9k
    switch (shaderType) {
192
40.0k
        case 0:
193
40.0k
            return nullptr;
194
541
        case 1:
195
541
            return SkShaders::Empty();
196
274
        case 2:
197
274
            fuzz->next(&color);
198
274
            return SkShaders::Color(color);
199
593
        case 3:
200
593
            img = make_fuzz_image(fuzz);
201
593
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
202
593
            fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
203
593
            fuzz->next(&useMatrix);
204
593
            if (useMatrix) {
205
138
                FuzzNiceMatrix(fuzz, &matrix);
206
138
            }
207
593
            return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
208
344
        case 5:
209
344
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
210
344
            FuzzNiceMatrix(fuzz, &matrix);
211
344
            return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
212
284
        case 6:
213
284
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
214
284
            colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
215
284
            return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
216
2.61k
        case 7:
217
2.61k
            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
218
2.61k
            shader2 = make_fuzz_shader(fuzz, depth - 1);
219
2.61k
            fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
220
2.61k
            return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
221
1.79k
        case 8: {
222
1.79k
            auto pic = make_fuzz_picture(fuzz, depth - 1);
223
1.79k
            bool useTile;
224
1.79k
            SkRect tile;
225
1.79k
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
226
1.79k
            fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
227
1.79k
            fuzz->next(&useMatrix, &useTile);
228
1.79k
            if (useMatrix) {
229
192
                FuzzNiceMatrix(fuzz, &matrix);
230
192
            }
231
1.79k
            if (useTile) {
232
164
                fuzz->next(&tile);
233
164
            }
234
1.79k
            return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
235
1.79k
                                   useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
236
0
        }
237
        // EFFECTS:
238
17
        case 9:
239
            // Deprecated SkGaussianEdgeShader
240
17
            return nullptr;
241
522
        case 10: {
242
522
            constexpr int kMaxColors = 12;
243
522
            SkPoint pts[2];
244
522
            SkColor colors[kMaxColors];
245
522
            SkScalar pos[kMaxColors];
246
522
            int colorCount;
247
522
            bool usePos;
248
522
            fuzz->nextN(pts, 2);
249
522
            fuzz->nextRange(&colorCount, 2, kMaxColors);
250
522
            fuzz->nextN(colors, colorCount);
251
522
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
252
522
            fuzz->next(&useMatrix, &usePos);
253
522
            if (useMatrix) {
254
251
                FuzzNiceMatrix(fuzz, &matrix);
255
251
            }
256
522
            if (usePos) {
257
237
                fuzz_gradient_stops(fuzz, pos, colorCount);
258
237
            }
259
522
            return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
260
522
                                                tmX, 0, useMatrix ? &matrix : nullptr);
261
0
        }
262
599
        case 11: {
263
599
            constexpr int kMaxColors = 12;
264
599
            SkPoint center;
265
599
            SkScalar radius;
266
599
            int colorCount;
267
599
            bool usePos;
268
599
            SkColor colors[kMaxColors];
269
599
            SkScalar pos[kMaxColors];
270
599
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
271
599
            fuzz->next(&useMatrix, &usePos, &center, &radius);
272
599
            fuzz->nextRange(&colorCount, 2, kMaxColors);
273
599
            fuzz->nextN(colors, colorCount);
274
599
            if (useMatrix) {
275
214
                FuzzNiceMatrix(fuzz, &matrix);
276
214
            }
277
599
            if (usePos) {
278
92
                fuzz_gradient_stops(fuzz, pos, colorCount);
279
92
            }
280
599
            return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
281
599
                                                colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
282
0
        }
283
1.72k
        case 12: {
284
1.72k
            constexpr int kMaxColors = 12;
285
1.72k
            SkPoint start, end;
286
1.72k
            SkScalar startRadius, endRadius;
287
1.72k
            int colorCount;
288
1.72k
            bool usePos;
289
1.72k
            SkColor colors[kMaxColors];
290
1.72k
            SkScalar pos[kMaxColors];
291
1.72k
            fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
292
1.72k
            fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
293
1.72k
            fuzz->nextRange(&colorCount, 2, kMaxColors);
294
1.72k
            fuzz->nextN(colors, colorCount);
295
1.72k
            if (useMatrix) {
296
521
                FuzzNiceMatrix(fuzz, &matrix);
297
521
            }
298
1.72k
            if (usePos) {
299
590
                fuzz_gradient_stops(fuzz, pos, colorCount);
300
590
            }
301
1.72k
            return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
302
1.72k
                                                         usePos ? pos : nullptr, colorCount, tmX, 0,
303
1.72k
                                                         useMatrix ? &matrix : nullptr);
304
0
        }
305
288
        case 13: {
306
288
            constexpr int kMaxColors = 12;
307
288
            SkScalar cx, cy;
308
288
            int colorCount;
309
288
            bool usePos;
310
288
            SkColor colors[kMaxColors];
311
288
            SkScalar pos[kMaxColors];
312
288
            fuzz->next(&cx, &cy, &useMatrix, &usePos);
313
288
            fuzz->nextRange(&colorCount, 2, kMaxColors);
314
288
            fuzz->nextN(colors, colorCount);
315
288
            if (useMatrix) {
316
156
                FuzzNiceMatrix(fuzz, &matrix);
317
156
            }
318
288
            if (usePos) {
319
131
                fuzz_gradient_stops(fuzz, pos, colorCount);
320
131
            }
321
288
            return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
322
288
                                               0, useMatrix ? &matrix : nullptr);
323
0
        }
324
45.2k
        case 14: {
325
45.2k
            SkScalar baseFrequencyX, baseFrequencyY, seed;
326
45.2k
            int numOctaves;
327
45.2k
            SkISize tileSize;
328
45.2k
            bool useTileSize, turbulence;
329
45.2k
            fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
330
45.2k
            if (useTileSize) {
331
14.0k
                fuzz->next(&tileSize);
332
14.0k
            }
333
45.2k
            fuzz->nextRange(&numOctaves, 2, 7);
334
45.2k
            if (turbulence) {
335
14.4k
                return SkShaders::MakeTurbulence(baseFrequencyX,
336
14.4k
                                                 baseFrequencyY,
337
14.4k
                                                 numOctaves,
338
14.4k
                                                 seed,
339
14.4k
                                                 useTileSize ? &tileSize : nullptr);
340
30.8k
            } else {
341
30.8k
                return SkShaders::MakeFractalNoise(baseFrequencyX,
342
30.8k
                                                   baseFrequencyY,
343
30.8k
                                                   numOctaves,
344
30.8k
                                                   seed,
345
30.8k
                                                   useTileSize ? &tileSize : nullptr);
346
30.8k
            }
347
45.2k
        }
348
105
        default:
349
105
            SkASSERT(false);
350
105
            break;
351
94.9k
    }
352
105
    return nullptr;
353
94.9k
}
354
355
145k
static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
356
145k
    if (depth <= 0) {
357
32.0k
        return nullptr;
358
32.0k
    }
359
113k
    uint8_t pathEffectType;
360
113k
    fuzz->nextRange(&pathEffectType, 0, 8);
361
113k
    switch (pathEffectType) {
362
35.3k
        case 0: {
363
35.3k
            return nullptr;
364
0
        }
365
18.9k
        case 1: {
366
18.9k
            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
367
18.9k
            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
368
18.9k
            return SkPathEffect::MakeSum(std::move(first), std::move(second));
369
0
        }
370
20.5k
        case 2: {
371
20.5k
            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
372
20.5k
            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
373
20.5k
            return SkPathEffect::MakeCompose(std::move(first), std::move(second));
374
0
        }
375
2.93k
        case 3: {
376
2.93k
            SkPath path;
377
2.93k
            FuzzNicePath(fuzz, &path, 20);
378
2.93k
            SkScalar advance, phase;
379
2.93k
            fuzz->next(&advance, &phase);
380
2.93k
            SkPath1DPathEffect::Style style;
381
2.93k
            fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
382
2.93k
            return SkPath1DPathEffect::Make(path, advance, phase, style);
383
0
        }
384
2.47k
        case 4: {
385
2.47k
            SkScalar width;
386
2.47k
            SkMatrix matrix;
387
2.47k
            fuzz->next(&width);
388
2.47k
            FuzzNiceMatrix(fuzz, &matrix);
389
2.47k
            return SkLine2DPathEffect::Make(width, matrix);
390
0
        }
391
1.59k
        case 5: {
392
1.59k
            SkPath path;
393
1.59k
            FuzzNicePath(fuzz, &path, 20);
394
1.59k
            SkMatrix matrix;
395
1.59k
            FuzzNiceMatrix(fuzz, &matrix);
396
1.59k
            return SkPath2DPathEffect::Make(matrix, path);
397
0
        }
398
3.83k
        case 6: {
399
3.83k
            SkScalar radius;
400
3.83k
            fuzz->next(&radius);
401
3.83k
            return SkCornerPathEffect::Make(radius);
402
0
        }
403
2.33k
        case 7: {
404
2.33k
            SkScalar phase;
405
2.33k
            fuzz->next(&phase);
406
2.33k
            SkScalar intervals[20];
407
2.33k
            int count;
408
2.33k
            fuzz->nextRange(&count, 0, (int)std::size(intervals));
409
2.33k
            fuzz->nextN(intervals, count);
410
2.33k
            return SkDashPathEffect::Make(intervals, count, phase);
411
0
        }
412
25.0k
        case 8: {
413
25.0k
            SkScalar segLength, dev;
414
25.0k
            uint32_t seed;
415
25.0k
            fuzz->next(&segLength, &dev, &seed);
416
25.0k
            return SkDiscretePathEffect::Make(segLength, dev, seed);
417
0
        }
418
0
        default:
419
0
            SkASSERT(false);
420
0
            return nullptr;
421
113k
    }
422
113k
}
423
424
66.1k
static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
425
66.1k
    int maskfilterType;
426
66.1k
    fuzz->nextRange(&maskfilterType, 0, 1);
427
66.1k
    switch (maskfilterType) {
428
31.4k
        case 0:
429
31.4k
            return nullptr;
430
34.6k
        case 1: {
431
34.6k
            SkBlurStyle blurStyle;
432
34.6k
            fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
433
34.6k
            SkScalar sigma;
434
34.6k
            fuzz->next(&sigma);
435
34.6k
            bool respectCTM;
436
34.6k
            fuzz->next(&respectCTM);
437
34.6k
            return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
438
0
        }
439
0
        default:
440
0
            SkASSERT(false);
441
0
            return nullptr;
442
66.1k
    }
443
66.1k
}
444
445
7.53k
static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
446
7.53k
    if (make_fuzz_t<bool>(fuzz)) {
447
983
        return nullptr;
448
983
    }
449
6.54k
    sk_sp<SkFontMgr> mgr = ToolUtils::TestFontMgr();
450
6.54k
    int familyCount = mgr->countFamilies();
451
6.54k
    int i, j;
452
6.54k
    fuzz->nextRange(&i, 0, familyCount - 1);
453
6.54k
    sk_sp<SkFontStyleSet> family(mgr->createStyleSet(i));
454
6.54k
    int styleCount = family->count();
455
6.54k
    fuzz->nextRange(&j, 0, styleCount - 1);
456
6.54k
    return sk_sp<SkTypeface>(family->createTypeface(j));
457
7.53k
}
458
459
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
460
461
6.89k
static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
462
6.89k
    if (depth <= 0) {
463
2.26k
        return nullptr;
464
2.26k
    }
465
4.62k
    uint8_t imageFilterType;
466
4.62k
    fuzz->nextRange(&imageFilterType, 1, 6);
467
4.62k
    SkPoint3 p, q;
468
4.62k
    SkColor lightColor;
469
4.62k
    SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
470
4.62k
    sk_sp<SkImageFilter> input;
471
4.62k
    SkIRect cropRect;
472
4.62k
    bool useCropRect;
473
4.62k
    fuzz->next(&useCropRect);
474
4.62k
    if (useCropRect) {
475
536
        fuzz->next(&cropRect);
476
536
    }
477
4.62k
    switch (imageFilterType) {
478
340
        case 1:
479
340
            fuzz->next(&p, &lightColor, &surfaceScale, &k);
480
340
            input = make_fuzz_imageFilter(fuzz, depth - 1);
481
340
            return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
482
340
                                                     std::move(input),
483
340
                                                     useCropRect ? &cropRect : nullptr);
484
143
        case 2:
485
143
            fuzz->next(&p, &lightColor, &surfaceScale, &k);
486
143
            input = make_fuzz_imageFilter(fuzz, depth - 1);
487
143
            return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
488
143
                                                   std::move(input),
489
143
                                                   useCropRect ? &cropRect : nullptr);
490
111
        case 3:
491
111
            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
492
111
            input = make_fuzz_imageFilter(fuzz, depth - 1);
493
111
            return SkImageFilters::SpotLitDiffuse(
494
111
                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
495
111
                    std::move(input), useCropRect ? &cropRect : nullptr);
496
158
        case 4:
497
158
            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
498
158
            input = make_fuzz_imageFilter(fuzz, depth - 1);
499
158
            return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
500
158
                                                      shininess, std::move(input),
501
158
                                                      useCropRect ? &cropRect : nullptr);
502
717
        case 5:
503
717
            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
504
717
            input = make_fuzz_imageFilter(fuzz, depth - 1);
505
717
            return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
506
717
                                                    shininess, std::move(input),
507
717
                                                    useCropRect ? &cropRect : nullptr);
508
3.15k
        case 6:
509
3.15k
            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
510
3.15k
                       &shininess);
511
3.15k
            input = make_fuzz_imageFilter(fuzz, depth - 1);
512
3.15k
            return SkImageFilters::SpotLitSpecular(
513
3.15k
                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
514
3.15k
                    std::move(input), useCropRect ? &cropRect : nullptr);
515
0
        default:
516
0
            SkASSERT(false);
517
0
            return nullptr;
518
4.62k
    }
519
4.62k
}
520
521
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
522
523
6.67k
static SkSamplingOptions next_sampling(Fuzz* fuzz) {
524
6.67k
    if (fuzz->nextBool()) {
525
2.20k
        float B, C;
526
2.20k
        fuzz->next(&B, &C);
527
2.20k
        return SkSamplingOptions({B, C});
528
4.46k
    } else {
529
4.46k
        SkFilterMode fm;
530
4.46k
        SkMipmapMode mm;
531
4.46k
        fuzz->nextEnum(&fm, SkFilterMode::kLast);
532
4.46k
        fuzz->nextEnum(&mm, SkMipmapMode::kLast);
533
4.46k
        return SkSamplingOptions(fm, mm);
534
4.46k
    }
535
6.67k
}
536
537
490k
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
538
490k
    if (depth <= 0) {
539
171k
        return nullptr;
540
171k
    }
541
318k
    uint8_t imageFilterType;
542
318k
    fuzz->nextRange(&imageFilterType, 0, 22);
543
318k
    switch (imageFilterType) {
544
86.3k
        case 0:
545
86.3k
            return nullptr;
546
16.7k
        case 1: {
547
16.7k
            SkScalar sigmaX, sigmaY;
548
16.7k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
549
16.7k
            bool useCropRect;
550
16.7k
            fuzz->next(&sigmaX, &sigmaY, &useCropRect);
551
16.7k
            SkIRect cropRect;
552
16.7k
            if (useCropRect) {
553
1.97k
                fuzz->next(&cropRect);
554
1.97k
            }
555
16.7k
            return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
556
16.7k
                                        useCropRect ? &cropRect : nullptr);
557
0
        }
558
3.73k
        case 2: {
559
3.73k
            SkMatrix matrix;
560
3.73k
            FuzzNiceMatrix(fuzz, &matrix);
561
3.73k
            const auto sampling = next_sampling(fuzz);
562
3.73k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
563
3.73k
            return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
564
0
        }
565
3.30k
        case 3: {
566
3.30k
            float k1, k2, k3, k4;
567
3.30k
            bool enforcePMColor;
568
3.30k
            bool useCropRect;
569
3.30k
            fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
570
3.30k
            sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
571
3.30k
            sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
572
3.30k
            SkIRect cropRect;
573
3.30k
            if (useCropRect) {
574
1.13k
                fuzz->next(&cropRect);
575
1.13k
            }
576
3.30k
            return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
577
3.30k
                                              std::move(background), std::move(foreground),
578
3.30k
                                              useCropRect ? &cropRect : nullptr);
579
0
        }
580
1.06k
        case 4: {
581
1.06k
            sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
582
1.06k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
583
1.06k
            bool useCropRect;
584
1.06k
            SkIRect cropRect;
585
1.06k
            fuzz->next(&useCropRect);
586
1.06k
            if (useCropRect) {
587
180
                fuzz->next(&cropRect);
588
180
            }
589
1.06k
            return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
590
1.06k
                                               useCropRect ? &cropRect : nullptr);
591
0
        }
592
6.25k
        case 5: {
593
6.25k
            sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
594
6.25k
            sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
595
6.25k
            return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
596
0
        }
597
10.0k
        case 6: {
598
10.0k
            SkColorChannel xChannelSelector, yChannelSelector;
599
10.0k
            fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
600
10.0k
            fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
601
10.0k
            SkScalar scale;
602
10.0k
            bool useCropRect;
603
10.0k
            fuzz->next(&scale, &useCropRect);
604
10.0k
            SkIRect cropRect;
605
10.0k
            if (useCropRect) {
606
1.51k
                fuzz->next(&cropRect);
607
1.51k
            }
608
10.0k
            sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
609
10.0k
            sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
610
10.0k
            return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
611
10.0k
                                                   std::move(displacement), std::move(color),
612
10.0k
                                                   useCropRect ? &cropRect : nullptr);
613
0
        }
614
14.1k
        case 7: {
615
14.1k
            SkScalar dx, dy, sigmaX, sigmaY;
616
14.1k
            SkColor color;
617
14.1k
            bool shadowOnly, useCropRect;
618
14.1k
            fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
619
14.1k
            SkIRect cropRect;
620
14.1k
            if (useCropRect) {
621
2.24k
                fuzz->next(&cropRect);
622
2.24k
            }
623
14.1k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
624
14.1k
            if (shadowOnly) {
625
2.32k
                return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
626
2.32k
                                                      std::move(input),
627
2.32k
                                                      useCropRect ? &cropRect : nullptr);
628
11.7k
            } else {
629
11.7k
                return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
630
11.7k
                                                  useCropRect ? &cropRect : nullptr);
631
11.7k
            }
632
14.1k
        }
633
441
        case 8:
634
441
            return SkImageFilters::Image(make_fuzz_image(fuzz), SkCubicResampler::Mitchell());
635
420
        case 9: {
636
420
            sk_sp<SkImage> image = make_fuzz_image(fuzz);
637
420
            SkRect srcRect, dstRect;
638
420
            fuzz->next(&srcRect, &dstRect);
639
420
            return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
640
14.1k
        }
641
6.89k
        case 10:
642
6.89k
            return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
643
2.52k
        case 11: {
644
2.52k
            SkRect lensBounds;
645
2.52k
            SkScalar zoomAmount;
646
2.52k
            SkScalar inset;
647
2.52k
            bool useCropRect;
648
2.52k
            SkIRect cropRect;
649
2.52k
            fuzz->next(&lensBounds, &zoomAmount, &inset, &useCropRect);
650
2.52k
            if (useCropRect) {
651
1.22k
                fuzz->next(&cropRect);
652
1.22k
            }
653
2.52k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
654
2.52k
            const auto sampling = next_sampling(fuzz);
655
2.52k
            return SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling,
656
2.52k
                                             std::move(input), useCropRect ? &cropRect : nullptr);
657
14.1k
        }
658
4.91k
        case 12: {
659
4.91k
            constexpr int kMaxKernelSize = 5;
660
4.91k
            int32_t n, m;
661
4.91k
            fuzz->nextRange(&n, 1, kMaxKernelSize);
662
4.91k
            fuzz->nextRange(&m, 1, kMaxKernelSize);
663
4.91k
            SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
664
4.91k
            fuzz->nextN(kernel, n * m);
665
4.91k
            int32_t offsetX, offsetY;
666
4.91k
            fuzz->nextRange(&offsetX, 0, n - 1);
667
4.91k
            fuzz->nextRange(&offsetY, 0, m - 1);
668
4.91k
            SkScalar gain, bias;
669
4.91k
            bool convolveAlpha, useCropRect;
670
4.91k
            fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
671
4.91k
            SkTileMode tileMode;
672
4.91k
            fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
673
4.91k
            SkIRect cropRect;
674
4.91k
            if (useCropRect) {
675
1.83k
                fuzz->next(&cropRect);
676
1.83k
            }
677
4.91k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
678
4.91k
            return SkImageFilters::MatrixConvolution(
679
4.91k
                    SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
680
4.91k
                    convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
681
14.1k
        }
682
3.67k
        case 13: {
683
3.67k
            sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
684
3.67k
            sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
685
3.67k
            bool useCropRect;
686
3.67k
            fuzz->next(&useCropRect);
687
3.67k
            SkIRect cropRect;
688
3.67k
            if (useCropRect) {
689
2.31k
                fuzz->next(&cropRect);
690
2.31k
            }
691
3.67k
            return SkImageFilters::Merge(std::move(first), std::move(second),
692
3.67k
                                         useCropRect ? &cropRect : nullptr);
693
14.1k
        }
694
79.5k
        case 14: {
695
79.5k
            constexpr int kMaxCount = 4;
696
79.5k
            sk_sp<SkImageFilter> ifs[kMaxCount];
697
79.5k
            int count;
698
79.5k
            fuzz->nextRange(&count, 1, kMaxCount);
699
379k
            for (int i = 0; i < count; ++i) {
700
299k
                ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
701
299k
            }
702
79.5k
            bool useCropRect;
703
79.5k
            fuzz->next(&useCropRect);
704
79.5k
            SkIRect cropRect;
705
79.5k
            if (useCropRect) {
706
10.5k
                fuzz->next(&cropRect);
707
10.5k
            }
708
79.5k
            return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
709
14.1k
        }
710
3.33k
        case 15: {
711
3.33k
            int rx, ry;
712
3.33k
            fuzz->next(&rx, &ry);
713
3.33k
            bool useCropRect;
714
3.33k
            fuzz->next(&useCropRect);
715
3.33k
            SkIRect cropRect;
716
3.33k
            if (useCropRect) {
717
1.12k
                fuzz->next(&cropRect);
718
1.12k
            }
719
3.33k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
720
3.33k
            return SkImageFilters::Dilate(rx, ry, std::move(input),
721
3.33k
                                          useCropRect ? &cropRect : nullptr);
722
14.1k
        }
723
7.36k
        case 16: {
724
7.36k
            int rx, ry;
725
7.36k
            fuzz->next(&rx, &ry);
726
7.36k
            bool useCropRect;
727
7.36k
            fuzz->next(&useCropRect);
728
7.36k
            SkIRect cropRect;
729
7.36k
            if (useCropRect) {
730
854
                fuzz->next(&cropRect);
731
854
            }
732
7.36k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
733
7.36k
            return SkImageFilters::Erode(rx, ry, std::move(input),
734
7.36k
                                         useCropRect ? &cropRect : nullptr);
735
14.1k
        }
736
1.25k
        case 17: {
737
1.25k
            SkScalar dx, dy;
738
1.25k
            fuzz->next(&dx, &dy);
739
1.25k
            bool useCropRect;
740
1.25k
            fuzz->next(&useCropRect);
741
1.25k
            SkIRect cropRect;
742
1.25k
            if (useCropRect) {
743
269
                fuzz->next(&cropRect);
744
269
            }
745
1.25k
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
746
1.25k
            return SkImageFilters::Offset(dx, dy, std::move(input),
747
1.25k
                                          useCropRect ? &cropRect : nullptr);
748
14.1k
        }
749
5.86k
        case 18: {
750
5.86k
            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
751
5.86k
            return SkImageFilters::Picture(std::move(picture));
752
14.1k
        }
753
521
        case 19: {
754
521
            SkRect cropRect;
755
521
            fuzz->next(&cropRect);
756
521
            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
757
521
            return SkImageFilters::Picture(std::move(picture), cropRect);
758
14.1k
        }
759
887
        case 20: {
760
887
            SkRect src, dst;
761
887
            fuzz->next(&src, &dst);
762
887
            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
763
887
            return SkImageFilters::Tile(src, dst, std::move(input));
764
14.1k
        }
765
7.32k
        case 21: {
766
7.32k
            SkBlendMode blendMode;
767
7.32k
            bool useCropRect;
768
7.32k
            fuzz->next(&useCropRect);
769
7.32k
            fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
770
7.32k
            SkIRect cropRect;
771
7.32k
            if (useCropRect) {
772
1.84k
                fuzz->next(&cropRect);
773
1.84k
            }
774
7.32k
            sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
775
7.32k
            sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
776
7.32k
            return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
777
7.32k
                                         useCropRect ? &cropRect : nullptr);
778
14.1k
        }
779
51.9k
        case 22: {
780
51.9k
            sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
781
51.9k
            bool useCropRect;
782
51.9k
            fuzz->next(&useCropRect);
783
51.9k
            SkIRect cropRect;
784
51.9k
            if (useCropRect) {
785
17.3k
                fuzz->next(&cropRect);
786
17.3k
            }
787
51.9k
            return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
788
14.1k
        }
789
0
        default:
790
0
            SkASSERT(false);
791
0
            return nullptr;
792
318k
    }
793
318k
}
794
795
8.69k
static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
796
8.69k
    int w, h;
797
8.69k
    fuzz->nextRange(&w, 1, 1024);
798
8.69k
    fuzz->nextRange(&h, 1, 1024);
799
8.69k
    AutoTMalloc<SkPMColor> data(w * h);
800
8.69k
    SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
801
8.69k
    int n = w * h;
802
300M
    for (int i = 0; i < n; ++i) {
803
300M
        SkColor c;
804
300M
        fuzz->next(&c);
805
300M
        data[i] = SkPreMultiplyColor(c);
806
300M
    }
807
8.69k
    (void)data.release();
808
8.69k
    return SkImages::RasterFromPixmap(
809
8.69k
            pixmap, [](const void* p, void*) { sk_free(const_cast<void*>(p)); }, nullptr);
810
8.69k
}
811
812
template <typename T>
813
256k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
256k
    T value;
815
256k
    fuzz->nextEnum(&value, maxv);
816
256k
    return value;
817
256k
}
FuzzCanvas.cpp:SkBlendMode make_fuzz_enum_range<SkBlendMode>(Fuzz*, SkBlendMode)
Line
Count
Source
813
66.1k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
66.1k
    T value;
815
66.1k
    fuzz->nextEnum(&value, maxv);
816
66.1k
    return value;
817
66.1k
}
FuzzCanvas.cpp:SkPaint::Style make_fuzz_enum_range<SkPaint::Style>(Fuzz*, SkPaint::Style)
Line
Count
Source
813
66.1k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
66.1k
    T value;
815
66.1k
    fuzz->nextEnum(&value, maxv);
816
66.1k
    return value;
817
66.1k
}
FuzzCanvas.cpp:SkPaint::Cap make_fuzz_enum_range<SkPaint::Cap>(Fuzz*, SkPaint::Cap)
Line
Count
Source
813
40.4k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
40.4k
    T value;
815
40.4k
    fuzz->nextEnum(&value, maxv);
816
40.4k
    return value;
817
40.4k
}
FuzzCanvas.cpp:SkPaint::Join make_fuzz_enum_range<SkPaint::Join>(Fuzz*, SkPaint::Join)
Line
Count
Source
813
40.4k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
40.4k
    T value;
815
40.4k
    fuzz->nextEnum(&value, maxv);
816
40.4k
    return value;
817
40.4k
}
FuzzCanvas.cpp:SkFontHinting make_fuzz_enum_range<SkFontHinting>(Fuzz*, SkFontHinting)
Line
Count
Source
813
7.53k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
7.53k
    T value;
815
7.53k
    fuzz->nextEnum(&value, maxv);
816
7.53k
    return value;
817
7.53k
}
FuzzCanvas.cpp:SkFont::Edging make_fuzz_enum_range<SkFont::Edging>(Fuzz*, SkFont::Edging)
Line
Count
Source
813
7.53k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
7.53k
    T value;
815
7.53k
    fuzz->nextEnum(&value, maxv);
816
7.53k
    return value;
817
7.53k
}
FuzzCanvas.cpp:SkTextEncoding make_fuzz_enum_range<SkTextEncoding>(Fuzz*, SkTextEncoding)
Line
Count
Source
813
28.1k
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814
28.1k
    T value;
815
28.1k
    fuzz->nextEnum(&value, maxv);
816
28.1k
    return value;
817
28.1k
}
818
819
87.6k
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
820
87.6k
    if (!fuzz || !paint || depth <= 0) {
821
21.4k
        return;
822
21.4k
    }
823
824
66.1k
    paint->setAntiAlias(    make_fuzz_t<bool>(fuzz));
825
66.1k
    paint->setDither(       make_fuzz_t<bool>(fuzz));
826
66.1k
    paint->setColor(        make_fuzz_t<SkColor>(fuzz));
827
66.1k
    paint->setBlendMode(    make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
828
66.1k
    paint->setStyle(        make_fuzz_enum_range<SkPaint::Style>(fuzz,
829
66.1k
                                                 SkPaint::Style::kStrokeAndFill_Style));
830
66.1k
    paint->setShader(       make_fuzz_shader(fuzz, depth - 1));
831
66.1k
    paint->setPathEffect(   make_fuzz_patheffect(fuzz, depth - 1));
832
66.1k
    paint->setMaskFilter(   make_fuzz_maskfilter(fuzz));
833
66.1k
    paint->setImageFilter(  make_fuzz_imageFilter(fuzz, depth - 1));
834
66.1k
    paint->setColorFilter(  make_fuzz_colorfilter(fuzz, depth - 1));
835
836
66.1k
    if (paint->getStyle() != SkPaint::kFill_Style) {
837
40.4k
        paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
838
40.4k
        paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
839
40.4k
        paint->setStrokeCap(  make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
840
40.4k
        paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
841
40.4k
    }
842
66.1k
}
843
844
7.53k
static SkFont fuzz_font(Fuzz* fuzz) {
845
7.53k
    SkFont font;
846
7.53k
    font.setTypeface(           make_fuzz_typeface(fuzz));
847
7.53k
    font.setSize(               make_fuzz_t<SkScalar>(fuzz));
848
7.53k
    font.setScaleX(             make_fuzz_t<SkScalar>(fuzz));
849
7.53k
    font.setSkewX(              make_fuzz_t<SkScalar>(fuzz));
850
7.53k
    font.setLinearMetrics(      make_fuzz_t<bool>(fuzz));
851
7.53k
    font.setSubpixel(           make_fuzz_t<bool>(fuzz));
852
7.53k
    font.setEmbeddedBitmaps(    make_fuzz_t<bool>(fuzz));
853
7.53k
    font.setForceAutoHinting(   make_fuzz_t<bool>(fuzz));
854
7.53k
    font.setEmbolden(           make_fuzz_t<bool>(fuzz));
855
7.53k
    font.setHinting(            make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
856
7.53k
    font.setEdging(             make_fuzz_enum_range<SkFont::Edging>(fuzz,
857
7.53k
                                                     SkFont::Edging::kSubpixelAntiAlias));
858
7.53k
    return font;
859
7.53k
}
860
861
28.1k
static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
862
28.1k
    return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
863
28.1k
}
864
865
constexpr int kMaxGlyphCount = 30;
866
867
28.1k
static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
868
28.1k
    SkTDArray<uint8_t> array;
869
28.1k
    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
28.1k
    static const SkUnichar ranges[][2] = {
885
28.1k
        {0x0020, 0x007F},
886
28.1k
        {0x00A1, 0x0250},
887
28.1k
        {0x0400, 0x0500},
888
28.1k
    };
889
28.1k
    int32_t count = 0;
890
112k
    for (size_t i = 0; i < std::size(ranges); ++i) {
891
84.3k
        count += (ranges[i][1] - ranges[i][0]);
892
84.3k
    }
893
28.1k
    constexpr int kMaxLength = kMaxGlyphCount;
894
28.1k
    SkUnichar buffer[kMaxLength];
895
28.1k
    int length;
896
28.1k
    fuzz->nextRange(&length, 1, kMaxLength);
897
382k
    for (int j = 0; j < length; ++j) {
898
354k
        int32_t value;
899
354k
        fuzz->nextRange(&value, 0, count - 1);
900
751k
        for (size_t i = 0; i < std::size(ranges); ++i) {
901
751k
            if (value + ranges[i][0] < ranges[i][1]) {
902
354k
                buffer[j] = value + ranges[i][0];
903
354k
                break;
904
397k
            } else {
905
397k
                value -= (ranges[i][1] - ranges[i][0]);
906
397k
            }
907
751k
        }
908
354k
    }
909
28.1k
    switch (encoding) {
910
15.2k
        case SkTextEncoding::kUTF8: {
911
15.2k
            size_t utf8len = 0;
912
116k
            for (int j = 0; j < length; ++j) {
913
101k
                utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
914
101k
            }
915
15.2k
            char* ptr = (char*)array.append(utf8len);
916
116k
            for (int j = 0; j < length; ++j) {
917
101k
                ptr += SkUTF::ToUTF8(buffer[j], ptr);
918
101k
            }
919
15.2k
        } break;
920
183
        case SkTextEncoding::kUTF16: {
921
183
            size_t utf16len = 0;
922
2.95k
            for (int j = 0; j < length; ++j) {
923
2.77k
                utf16len += SkUTF::ToUTF16(buffer[j]);
924
2.77k
            }
925
183
            uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
926
2.95k
            for (int j = 0; j < length; ++j) {
927
2.77k
                ptr += SkUTF::ToUTF16(buffer[j], ptr);
928
2.77k
            }
929
183
        } break;
930
12.7k
        case SkTextEncoding::kUTF32:
931
12.7k
            memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
932
12.7k
            break;
933
0
        default:
934
0
            SkASSERT(false);
935
0
            break;
936
28.1k
    }
937
28.1k
    return array;
938
28.1k
}
939
940
2.54k
static std::string make_fuzz_string(Fuzz* fuzz) {
941
2.54k
    int len;
942
2.54k
    fuzz->nextRange(&len, 0, kMaxGlyphCount);
943
2.54k
    std::string str(len, 0);
944
68.1k
    for (int i = 0; i < len; i++) {
945
65.6k
        fuzz->next(&str[i]);
946
65.6k
    }
947
2.54k
    return str;
948
2.54k
}
949
950
3.73k
static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
951
3.73k
    SkTextBlobBuilder textBlobBuilder;
952
3.73k
    int8_t runCount;
953
3.73k
    fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
954
26.8k
    while (runCount-- > 0) {
955
23.1k
        SkFont font = ToolUtils::DefaultFont();
956
23.1k
        SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
957
23.1k
        font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
958
23.1k
        SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
959
23.1k
        int glyphCount = font.countText(text.begin(), SkToSizeT(text.size()), encoding);
960
23.1k
        SkASSERT(glyphCount <= kMaxGlyphCount);
961
23.1k
        SkScalar x, y;
962
23.1k
        const SkTextBlobBuilder::RunBuffer* buffer;
963
23.1k
        uint8_t runType;
964
23.1k
        fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
965
23.1k
        const void* textPtr = text.begin();
966
23.1k
        size_t textLen =  SkToSizeT(text.size());
967
23.1k
        switch (runType) {
968
12.5k
            case 0:
969
12.5k
                fuzz->next(&x, &y);
970
                // TODO: Test other variations of this.
971
12.5k
                buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
972
12.5k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
973
12.5k
                break;
974
1.83k
            case 1:
975
1.83k
                fuzz->next(&y);
976
                // TODO: Test other variations of this.
977
1.83k
                buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
978
1.83k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
979
1.83k
                fuzz->nextN(buffer->pos, glyphCount);
980
1.83k
                break;
981
8.70k
            case 2:
982
                // TODO: Test other variations of this.
983
8.70k
                buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
984
8.70k
                (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
985
8.70k
                fuzz->nextN(buffer->pos, glyphCount * 2);
986
8.70k
                break;
987
0
            default:
988
0
                SkASSERT(false);
989
0
                break;
990
23.1k
        }
991
23.1k
    }
992
3.73k
    return textBlobBuilder.make();
993
3.73k
}
994
995
63.4k
static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
996
63.4k
    if (!fuzz || !canvas || depth <= 0) {
997
2.92k
        return;
998
2.92k
    }
999
60.5k
    SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1000
60.5k
    unsigned N;
1001
60.5k
    fuzz->nextRange(&N, 0, 2000);
1002
357k
    for (unsigned loop = 0; loop < N; ++loop) {
1003
348k
        if (fuzz->exhausted()) {
1004
52.3k
            return;
1005
52.3k
        }
1006
296k
        SkPaint paint;
1007
296k
        SkFont font = ToolUtils::DefaultFont();
1008
296k
        unsigned drawCommand;
1009
296k
        fuzz->nextRange(&drawCommand, 0, 62);
1010
296k
        switch (drawCommand) {
1011
105k
            case 0:
1012
105k
#if defined(SK_GANESH)
1013
105k
                if (auto dContext = GrAsDirectContext(canvas->recordingContext())) {
1014
17.0k
                    dContext->flushAndSubmit();
1015
17.0k
                }
1016
105k
#endif
1017
105k
                break;
1018
3.28k
            case 1:
1019
3.28k
                canvas->save();
1020
3.28k
                break;
1021
821
            case 2: {
1022
821
                SkRect bounds;
1023
821
                fuzz->next(&bounds);
1024
821
                fuzz_paint(fuzz, &paint, depth - 1);
1025
821
                canvas->saveLayer(&bounds, &paint);
1026
821
                break;
1027
0
            }
1028
316
            case 3: {
1029
316
                SkRect bounds;
1030
316
                fuzz->next(&bounds);
1031
316
                canvas->saveLayer(&bounds, nullptr);
1032
316
                break;
1033
0
            }
1034
2.23k
            case 4:
1035
2.23k
                fuzz_paint(fuzz, &paint, depth - 1);
1036
2.23k
                canvas->saveLayer(nullptr, &paint);
1037
2.23k
                break;
1038
11.3k
            case 5:
1039
11.3k
                canvas->saveLayer(nullptr, nullptr);
1040
11.3k
                break;
1041
18.0k
            case 6: {
1042
18.0k
                uint8_t alpha;
1043
18.0k
                fuzz->next(&alpha);
1044
18.0k
                canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1045
18.0k
                break;
1046
0
            }
1047
888
            case 7: {
1048
888
                SkRect bounds;
1049
888
                uint8_t alpha;
1050
888
                fuzz->next(&bounds, &alpha);
1051
888
                canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1052
888
                break;
1053
0
            }
1054
7.87k
            case 8: {
1055
7.87k
                SkCanvas::SaveLayerRec saveLayerRec;
1056
7.87k
                SkRect bounds;
1057
7.87k
                if (make_fuzz_t<bool>(fuzz)) {
1058
834
                    fuzz->next(&bounds);
1059
834
                    saveLayerRec.fBounds = &bounds;
1060
834
                }
1061
7.87k
                if (make_fuzz_t<bool>(fuzz)) {
1062
273
                    fuzz_paint(fuzz, &paint, depth - 1);
1063
273
                    saveLayerRec.fPaint = &paint;
1064
273
                }
1065
7.87k
                sk_sp<SkImageFilter> imageFilter;
1066
7.87k
                if (make_fuzz_t<bool>(fuzz)) {
1067
2.83k
                    imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1068
2.83k
                    saveLayerRec.fBackdrop = imageFilter.get();
1069
2.83k
                }
1070
                // _DumpCanvas can't handle this.
1071
                // if (make_fuzz_t<bool>(fuzz)) {
1072
                //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1073
                // }
1074
1075
7.87k
                canvas->saveLayer(saveLayerRec);
1076
7.87k
                break;
1077
0
            }
1078
1.80k
            case 9:
1079
1.80k
                canvas->restore();
1080
1.80k
                break;
1081
2.00k
            case 10: {
1082
2.00k
                int saveCount;
1083
2.00k
                fuzz->next(&saveCount);
1084
2.00k
                canvas->restoreToCount(saveCount);
1085
2.00k
                break;
1086
0
            }
1087
1.02k
            case 11: {
1088
1.02k
                SkScalar x, y;
1089
1.02k
                fuzz->next(&x, &y);
1090
1.02k
                canvas->translate(x, y);
1091
1.02k
                break;
1092
0
            }
1093
1.74k
            case 12: {
1094
1.74k
                SkScalar x, y;
1095
1.74k
                fuzz->next(&x, &y);
1096
1.74k
                canvas->scale(x, y);
1097
1.74k
                break;
1098
0
            }
1099
1.61k
            case 13: {
1100
1.61k
                SkScalar v;
1101
1.61k
                fuzz->next(&v);
1102
1.61k
                canvas->rotate(v);
1103
1.61k
                break;
1104
0
            }
1105
387
            case 14: {
1106
387
                SkScalar x, y, v;
1107
387
                fuzz->next(&x, &y, &v);
1108
387
                canvas->rotate(v, x, y);
1109
387
                break;
1110
0
            }
1111
3.61k
            case 15: {
1112
3.61k
                SkScalar x, y;
1113
3.61k
                fuzz->next(&x, &y);
1114
3.61k
                canvas->skew(x, y);
1115
3.61k
                break;
1116
0
            }
1117
1.40k
            case 16: {
1118
1.40k
                SkMatrix mat;
1119
1.40k
                FuzzNiceMatrix(fuzz, &mat);
1120
1.40k
                canvas->concat(mat);
1121
1.40k
                break;
1122
0
            }
1123
1.14k
            case 17: {
1124
1.14k
                SkMatrix mat;
1125
1.14k
                FuzzNiceMatrix(fuzz, &mat);
1126
1.14k
                canvas->setMatrix(mat);
1127
1.14k
                break;
1128
0
            }
1129
1.26k
            case 18:
1130
1.26k
                canvas->resetMatrix();
1131
1.26k
                break;
1132
3.27k
            case 19: {
1133
3.27k
                SkRect r;
1134
3.27k
                int op;
1135
3.27k
                bool doAntiAlias;
1136
3.27k
                fuzz->next(&r, &doAntiAlias);
1137
3.27k
                fuzz->nextRange(&op, 0, 1);
1138
3.27k
                r.sort();
1139
3.27k
                canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1140
3.27k
                break;
1141
0
            }
1142
2.69k
            case 20: {
1143
2.69k
                SkRRect rr;
1144
2.69k
                int op;
1145
2.69k
                bool doAntiAlias;
1146
2.69k
                FuzzNiceRRect(fuzz, &rr);
1147
2.69k
                fuzz->next(&doAntiAlias);
1148
2.69k
                fuzz->nextRange(&op, 0, 1);
1149
2.69k
                canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1150
2.69k
                break;
1151
0
            }
1152
10.2k
            case 21: {
1153
10.2k
                SkPath path;
1154
10.2k
                FuzzNicePath(fuzz, &path, 30);
1155
10.2k
                int op;
1156
10.2k
                bool doAntiAlias;
1157
10.2k
                fuzz->next(&doAntiAlias);
1158
10.2k
                fuzz->nextRange(&op, 0, 1);
1159
10.2k
                canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1160
10.2k
                break;
1161
0
            }
1162
4.47k
            case 22: {
1163
4.47k
                SkRegion region;
1164
4.47k
                int op;
1165
4.47k
                fuzz->next(&region);
1166
4.47k
                fuzz->nextRange(&op, 0, 1);
1167
4.47k
                canvas->clipRegion(region, (SkClipOp)op);
1168
4.47k
                break;
1169
0
            }
1170
634
            case 23:
1171
634
                fuzz_paint(fuzz, &paint, depth - 1);
1172
634
                canvas->drawPaint(paint);
1173
634
                break;
1174
3.90k
            case 24: {
1175
3.90k
                fuzz_paint(fuzz, &paint, depth - 1);
1176
3.90k
                SkCanvas::PointMode pointMode;
1177
3.90k
                fuzz->nextRange(&pointMode,
1178
3.90k
                                SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
1179
3.90k
                size_t count;
1180
3.90k
                constexpr int kMaxCount = 30;
1181
3.90k
                fuzz->nextRange(&count, 0, kMaxCount);
1182
3.90k
                SkPoint pts[kMaxCount];
1183
3.90k
                fuzz->nextN(pts, count);
1184
3.90k
                canvas->drawPoints(pointMode, count, pts, paint);
1185
3.90k
                break;
1186
0
            }
1187
169
            case 25: {
1188
169
                fuzz_paint(fuzz, &paint, depth - 1);
1189
169
                SkRect r;
1190
169
                fuzz->next(&r);
1191
169
                if (!r.isFinite()) {
1192
49
                    break;
1193
49
                }
1194
120
                canvas->drawRect(r, paint);
1195
120
                break;
1196
169
            }
1197
363
            case 26: {
1198
363
                fuzz_paint(fuzz, &paint, depth - 1);
1199
363
                SkRegion region;
1200
363
                fuzz->next(&region);
1201
363
                canvas->drawRegion(region, paint);
1202
363
                break;
1203
169
            }
1204
578
            case 27: {
1205
578
                fuzz_paint(fuzz, &paint, depth - 1);
1206
578
                SkRect r;
1207
578
                fuzz->next(&r);
1208
578
                if (!r.isFinite()) {
1209
21
                    break;
1210
21
                }
1211
557
                canvas->drawOval(r, paint);
1212
557
                break;
1213
578
            }
1214
185
            case 28: break; // must have deleted this some time earlier
1215
407
            case 29: {
1216
407
                fuzz_paint(fuzz, &paint, depth - 1);
1217
407
                SkRRect rr;
1218
407
                FuzzNiceRRect(fuzz, &rr);
1219
407
                canvas->drawRRect(rr, paint);
1220
407
                break;
1221
578
            }
1222
620
            case 30: {
1223
620
                fuzz_paint(fuzz, &paint, depth - 1);
1224
620
                SkRRect orr, irr;
1225
620
                FuzzNiceRRect(fuzz, &orr);
1226
620
                FuzzNiceRRect(fuzz, &irr);
1227
620
                if (orr.getBounds().contains(irr.getBounds())) {
1228
290
                    canvas->drawDRRect(orr, irr, paint);
1229
290
                }
1230
620
                break;
1231
578
            }
1232
57
            case 31: {
1233
57
                fuzz_paint(fuzz, &paint, depth - 1);
1234
57
                SkRect r;
1235
57
                SkScalar start, sweep;
1236
57
                bool useCenter;
1237
57
                fuzz->next(&r, &start, &sweep, &useCenter);
1238
57
                canvas->drawArc(r, start, sweep, useCenter, paint);
1239
57
                break;
1240
578
            }
1241
5.59k
            case 32: {
1242
5.59k
                fuzz_paint(fuzz, &paint, depth - 1);
1243
5.59k
                SkPath path;
1244
5.59k
                FuzzNicePath(fuzz, &path, 60);
1245
5.59k
                canvas->drawPath(path, paint);
1246
5.59k
                break;
1247
578
            }
1248
4.96k
            case 33: {
1249
4.96k
                sk_sp<SkImage> img = make_fuzz_image(fuzz);
1250
4.96k
                SkScalar left, top;
1251
4.96k
                bool usePaint;
1252
4.96k
                fuzz->next(&left, &top, &usePaint);
1253
4.96k
                if (usePaint) {
1254
658
                    fuzz_paint(fuzz, &paint, depth - 1);
1255
658
                }
1256
4.96k
                canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
1257
4.96k
                                  usePaint ? &paint : nullptr);
1258
4.96k
                break;
1259
578
            }
1260
417
            case 35: {
1261
417
                auto img = make_fuzz_image(fuzz);
1262
417
                SkIRect src;
1263
417
                SkRect dst;
1264
417
                bool usePaint;
1265
417
                fuzz->next(&src, &dst, &usePaint);
1266
417
                if (usePaint) {
1267
89
                    fuzz_paint(fuzz, &paint, depth - 1);
1268
89
                }
1269
417
                SkCanvas::SrcRectConstraint constraint =
1270
417
                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1271
417
                                                : SkCanvas::kFast_SrcRectConstraint;
1272
417
                canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
1273
417
                                      usePaint ? &paint : nullptr, constraint);
1274
417
                break;
1275
578
            }
1276
1.23k
            case 37: {
1277
1.23k
                auto img = make_fuzz_image(fuzz);
1278
1.23k
                SkIRect center;
1279
1.23k
                SkRect dst;
1280
1.23k
                bool usePaint;
1281
1.23k
                fuzz->next(&usePaint);
1282
1.23k
                if (usePaint) {
1283
237
                    fuzz_paint(fuzz, &paint, depth - 1);
1284
237
                }
1285
1.23k
                if (make_fuzz_t<bool>(fuzz)) {
1286
295
                    fuzz->next(&center);
1287
938
                } else {  // Make valid center, see SkLatticeIter::Valid().
1288
938
                    fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1289
938
                    fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1290
938
                    fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1291
938
                    fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1292
938
                }
1293
1.23k
                fuzz->next(&dst);
1294
1.23k
                canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
1295
1.23k
                                      usePaint ? &paint : nullptr);
1296
1.23k
                break;
1297
578
            }
1298
630
            case 44: {
1299
630
                auto img = make_fuzz_image(fuzz);
1300
630
                bool usePaint;
1301
630
                SkRect dst;
1302
630
                fuzz->next(&usePaint, &dst);
1303
630
                if (usePaint) {
1304
208
                    fuzz_paint(fuzz, &paint, depth - 1);
1305
208
                }
1306
630
                constexpr int kMax = 6;
1307
630
                int xDivs[kMax], yDivs[kMax];
1308
630
                SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1309
630
                fuzz->nextRange(&lattice.fXCount, 2, kMax);
1310
630
                fuzz->nextRange(&lattice.fYCount, 2, kMax);
1311
630
                fuzz->nextN(xDivs, lattice.fXCount);
1312
630
                fuzz->nextN(yDivs, lattice.fYCount);
1313
630
                canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
1314
630
                                         usePaint ? &paint : nullptr);
1315
630
                break;
1316
578
            }
1317
4.98k
            case 45: {
1318
4.98k
                fuzz_paint(fuzz, &paint, depth - 1);
1319
4.98k
                font = fuzz_font(fuzz);
1320
4.98k
                SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
1321
4.98k
                SkScalar x, y;
1322
4.98k
                fuzz->next(&x, &y);
1323
4.98k
                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
1324
4.98k
                canvas->drawSimpleText(text.begin(), SkToSizeT(text.size()), encoding, x, y,
1325
4.98k
                                       font, paint);
1326
4.98k
                break;
1327
578
            }
1328
51
            case 46: {
1329
                // was drawPosText
1330
51
                break;
1331
578
            }
1332
162
            case 47: {
1333
                // was drawPosTextH
1334
162
                break;
1335
578
            }
1336
131
            case 48: {
1337
                // was drawtextonpath
1338
131
                break;
1339
578
            }
1340
83
            case 49: {
1341
                // was drawtextonpath
1342
83
                break;
1343
578
            }
1344
217
            case 50: {
1345
                // was drawTextRSXform
1346
217
                break;
1347
578
            }
1348
3.73k
            case 51: {
1349
3.73k
                sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
1350
3.73k
                fuzz_paint(fuzz, &paint, depth - 1);
1351
3.73k
                SkScalar x, y;
1352
3.73k
                fuzz->next(&x, &y);
1353
3.73k
                canvas->drawTextBlob(blob, x, y, paint);
1354
3.73k
                break;
1355
578
            }
1356
16.3k
            case 52: {
1357
16.3k
                SkMatrix matrix;
1358
16.3k
                bool usePaint, useMatrix;
1359
16.3k
                fuzz->next(&usePaint, &useMatrix);
1360
16.3k
                if (usePaint) {
1361
1.85k
                    fuzz_paint(fuzz, &paint, depth - 1);
1362
1.85k
                }
1363
16.3k
                if (useMatrix) {
1364
2.39k
                    FuzzNiceMatrix(fuzz, &matrix);
1365
2.39k
                }
1366
16.3k
                auto pic = make_fuzz_picture(fuzz, depth - 1);
1367
16.3k
                canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1368
16.3k
                                    usePaint ? &paint : nullptr);
1369
16.3k
                break;
1370
578
            }
1371
1.14k
            case 53: {
1372
1.14k
                fuzz_paint(fuzz, &paint, depth - 1);
1373
1.14k
                SkVertices::VertexMode vertexMode;
1374
1.14k
                SkBlendMode blendMode;
1375
1.14k
                fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1376
1.14k
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
1377
1.14k
                constexpr int kMaxCount = 100;
1378
1.14k
                int vertexCount;
1379
1.14k
                SkPoint vertices[kMaxCount];
1380
1.14k
                SkPoint texs[kMaxCount];
1381
1.14k
                SkColor colors[kMaxCount];
1382
1.14k
                fuzz->nextRange(&vertexCount, 3, kMaxCount);
1383
1.14k
                fuzz->nextN(vertices, vertexCount);
1384
1.14k
                bool useTexs, useColors;
1385
1.14k
                fuzz->next(&useTexs, &useColors);
1386
1.14k
                if (useTexs) {
1387
294
                    fuzz->nextN(texs, vertexCount);
1388
294
                }
1389
1.14k
                if (useColors) {
1390
256
                    fuzz->nextN(colors, vertexCount);
1391
256
                }
1392
1.14k
                int indexCount = 0;
1393
1.14k
                uint16_t indices[kMaxCount * 2];
1394
1.14k
                if (make_fuzz_t<bool>(fuzz)) {
1395
278
                    fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1396
11.3k
                    for (int index = 0; index < indexCount; ++index) {
1397
11.1k
                        fuzz->nextRange(&indices[index], 0, vertexCount - 1);
1398
11.1k
                    }
1399
278
                }
1400
1.14k
                canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1401
1.14k
                                                          useTexs ? texs : nullptr,
1402
1.14k
                                                          useColors ? colors : nullptr,
1403
1.14k
                                                          indexCount, indices),
1404
1.14k
                                     blendMode, paint);
1405
1.14k
                break;
1406
578
            }
1407
2.97k
            case 54: {
1408
2.97k
                SkColor color;
1409
2.97k
                SkBlendMode blendMode;
1410
2.97k
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1411
2.97k
                fuzz->next(&color);
1412
2.97k
                canvas->drawColor(color, blendMode);
1413
2.97k
                break;
1414
578
            }
1415
634
            case 55: {
1416
634
                SkColor4f color;
1417
634
                SkBlendMode blendMode;
1418
634
                float R, G, B, Alpha;
1419
634
                fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1420
634
                fuzz->nextRange(&R, -1, 2);
1421
634
                fuzz->nextRange(&G, -1, 2);
1422
634
                fuzz->nextRange(&B, -1, 2);
1423
634
                fuzz->nextRange(&Alpha, 0, 1);
1424
634
                color = {R, G, B, Alpha};
1425
634
                canvas->drawColor(color, blendMode);
1426
634
                break;
1427
578
            }
1428
1.10k
            case 56: {
1429
1.10k
                fuzz_paint(fuzz, &paint, depth - 1);
1430
1.10k
                SkPoint p0, p1;
1431
1.10k
                fuzz->next(&p0, &p1);
1432
1.10k
                canvas->drawLine(p0, p1, paint);
1433
1.10k
                break;
1434
578
            }
1435
163
            case 57: {
1436
163
                fuzz_paint(fuzz, &paint, depth - 1);
1437
163
                SkIRect r;
1438
163
                fuzz->next(&r);
1439
163
                canvas->drawIRect(r, paint);
1440
163
                break;
1441
578
            }
1442
715
            case 58: {
1443
715
                fuzz_paint(fuzz, &paint, depth - 1);
1444
715
                SkScalar radius;
1445
715
                SkPoint center;
1446
715
                fuzz->next(&radius, &center);
1447
715
                canvas->drawCircle(center, radius, paint);
1448
715
                break;
1449
578
            }
1450
425
            case 59: {
1451
425
                fuzz_paint(fuzz, &paint, depth - 1);
1452
425
                SkRect oval;
1453
425
                SkScalar startAngle, sweepAngle;
1454
425
                bool useCenter;
1455
425
                fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
1456
425
                canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1457
425
                break;
1458
578
            }
1459
866
            case 60: {
1460
866
                fuzz_paint(fuzz, &paint, depth - 1);
1461
866
                SkRect rect;
1462
866
                SkScalar rx, ry;
1463
866
                fuzz->next(&rect, &rx, &ry);
1464
866
                canvas->drawRoundRect(rect, rx, ry, paint);
1465
866
                break;
1466
578
            }
1467
2.54k
            case 61: {
1468
2.54k
                fuzz_paint(fuzz, &paint, depth - 1);
1469
2.54k
                font = fuzz_font(fuzz);
1470
2.54k
                std::string str = make_fuzz_string(fuzz);
1471
2.54k
                SkScalar x, y;
1472
2.54k
                fuzz->next(&x, &y);
1473
2.54k
                canvas->drawString(str.c_str(), x, y, font, paint);
1474
2.54k
                break;
1475
578
            }
1476
53.2k
            case 62: {
1477
53.2k
                fuzz_paint(fuzz, &paint, depth - 1);
1478
53.2k
                SkPoint cubics[12];
1479
53.2k
                SkColor colors[4];
1480
53.2k
                SkPoint texCoords[4];
1481
53.2k
                bool useTexCoords;
1482
53.2k
                fuzz->nextN(cubics, 12);
1483
53.2k
                fuzz->nextN(colors, 4);
1484
53.2k
                fuzz->next(&useTexCoords);
1485
53.2k
                if (useTexCoords) {
1486
9.26k
                    fuzz->nextN(texCoords, 4);
1487
9.26k
                }
1488
53.2k
                SkBlendMode mode;
1489
53.2k
                fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
1490
53.2k
                canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
1491
53.2k
                    , mode, paint);
1492
53.2k
                break;
1493
578
            }
1494
432
            default:
1495
432
                SkASSERT(false);
1496
432
                break;
1497
296k
        }
1498
296k
    }
1499
60.5k
}
1500
1501
24.5k
static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1502
24.5k
    SkScalar w, h;
1503
24.5k
    fuzz->next(&w, &h);
1504
24.5k
    SkPictureRecorder pictureRecorder;
1505
24.5k
    fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1506
24.5k
    return pictureRecorder.finishRecordingAsPicture();
1507
24.5k
}
1508
1509
9.79k
DEF_FUZZ(NullCanvas, fuzz) {
1510
9.79k
    fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1511
9.79k
}
1512
1513
constexpr SkISize kCanvasSize = {128, 160};
1514
1515
12.5k
DEF_FUZZ(RasterN32Canvas, fuzz) {
1516
12.5k
    auto surface = SkSurfaces::Raster(
1517
12.5k
            SkImageInfo::MakeN32Premul(kCanvasSize.width(), kCanvasSize.height()));
1518
12.5k
    if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
1519
12.5k
    fuzz_canvas(fuzz, surface->getCanvas());
1520
12.5k
}
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
4.32k
static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
1627
4.32k
    SkASSERT(context);
1628
4.32k
    auto surface = SkSurfaces::RenderTarget(
1629
4.32k
            context,
1630
4.32k
            skgpu::Budgeted::kNo,
1631
4.32k
            SkImageInfo::Make(kCanvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1632
4.32k
    SkASSERT(surface && surface->getCanvas());
1633
4.32k
    fuzz_canvas(fuzz, surface->getCanvas());
1634
4.32k
}
1635
1636
4.32k
DEF_FUZZ(MockGPUCanvas, fuzz) {
1637
4.32k
    sk_gpu_test::GrContextFactory f;
1638
4.32k
    fuzz_ganesh(fuzz, f.get(skgpu::ContextType::kMock));
1639
4.32k
}
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
12.2k
DEF_FUZZ(SVGCanvas, fuzz) {
1694
12.2k
    SkNullWStream stream;
1695
12.2k
    SkRect bounds = SkRect::MakeIWH(150, 150);
1696
12.2k
    std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
1697
12.2k
    fuzz_canvas(fuzz, canvas.get());
1698
12.2k
}