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.h"
9#include "FuzzCommon.h"
10
11// CORE
12#include "SkCanvas.h"
13#include "SkColorFilter.h"
14#include "SkDebugCanvas.h"
15#include "SkDocument.h"
16#include "SkFontMgr.h"
17#include "SkImageFilter.h"
18#include "SkMaskFilter.h"
19#include "SkNullCanvas.h"
20#include "SkPathEffect.h"
21#include "SkPictureRecorder.h"
22#include "SkPoint3.h"
23#include "SkRSXform.h"
24#include "SkRegion.h"
25#include "SkSurface.h"
26#include "SkTypeface.h"
27#include "SkOSFile.h"
28
29// EFFECTS
30#include "Sk1DPathEffect.h"
31#include "Sk2DPathEffect.h"
32#include "SkAlphaThresholdFilter.h"
33#include "SkArithmeticImageFilter.h"
34#include "SkBlurImageFilter.h"
35#include "SkBlurMaskFilter.h"
36#include "SkColorFilterImageFilter.h"
37#include "SkColorMatrixFilter.h"
38#include "SkComposeImageFilter.h"
39#include "SkCornerPathEffect.h"
40#include "SkDashPathEffect.h"
41#include "SkDiscretePathEffect.h"
42#include "SkDisplacementMapEffect.h"
43#include "SkDropShadowImageFilter.h"
44#include "SkGradientShader.h"
45#include "SkHighContrastFilter.h"
46#include "SkImageSource.h"
47#include "SkLightingImageFilter.h"
48#include "SkLumaColorFilter.h"
49#include "SkMagnifierImageFilter.h"
50#include "SkMatrixConvolutionImageFilter.h"
51#include "SkMergeImageFilter.h"
52#include "SkMorphologyImageFilter.h"
53#include "SkOffsetImageFilter.h"
54#include "SkPaintImageFilter.h"
55#include "SkPerlinNoiseShader.h"
56#include "SkPictureImageFilter.h"
57#include "SkReadBuffer.h"
58#include "SkRRectsGaussianEdgeMaskFilter.h"
59#include "SkTableColorFilter.h"
60#include "SkTextBlob.h"
61#include "SkTileImageFilter.h"
62#include "SkXfermodeImageFilter.h"
63
64// SRC
65#include "SkUtils.h"
66
67#if SK_SUPPORT_GPU
68#include "GrContextFactory.h"
69#endif
70
71// MISC
72
73#include <iostream>
74
75// TODO:
76//   SkTextBlob with Unicode
77//   SkImage: more types
78
79template <typename T, typename Min, typename Max>
80inline void fuzz_enum_range(Fuzz* fuzz, T* value, Min rmin, Max rmax) {
81    using U = skstd::underlying_type_t<T>;
82    fuzz->nextRange((U*)value, (U)rmin, (U)rmax);
83}
84
85// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
86// In fact, all make_fuzz_foo() functions have this potential problem.
87// Use sequence points!
88template <typename T>
89inline T make_fuzz_t(Fuzz* fuzz) {
90    T t;
91    fuzz->next(&t);
92    return t;
93}
94
95template <>
96inline void Fuzz::next(SkShader::TileMode* m) {
97    fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1);
98}
99
100template <>
101inline void Fuzz::next(SkFilterQuality* q) {
102    fuzz_enum_range(this, q, SkFilterQuality::kNone_SkFilterQuality,
103                    SkFilterQuality::kLast_SkFilterQuality);
104}
105
106template <>
107inline void Fuzz::next(SkMatrix* m) {
108    constexpr int kArrayLength = 9;
109    SkScalar buffer[kArrayLength];
110    int matrixType;
111    this->nextRange(&matrixType, 0, 4);
112    switch (matrixType) {
113        case 0:  // identity
114            *m = SkMatrix::I();
115            return;
116        case 1:  // translate
117            this->nextRange(&buffer[0], -4000.0f, 4000.0f);
118            this->nextRange(&buffer[1], -4000.0f, 4000.0f);
119            *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
120            return;
121        case 2:  // translate + scale
122            this->nextRange(&buffer[0], -400.0f, 400.0f);
123            this->nextRange(&buffer[1], -400.0f, 400.0f);
124            this->nextRange(&buffer[2], -4000.0f, 4000.0f);
125            this->nextRange(&buffer[3], -4000.0f, 4000.0f);
126            *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
127            m->postTranslate(buffer[2], buffer[3]);
128            return;
129        case 3:  // affine
130            this->nextN(buffer, 6);
131            m->setAffine(buffer);
132            return;
133        case 4:  // perspective
134            this->nextN(buffer, kArrayLength);
135            m->set9(buffer);
136            return;
137        default:
138            SkASSERT(false);
139            return;
140    }
141}
142
143template <>
144inline void Fuzz::next(SkRRect* rr) {
145    SkRect r;
146    SkVector radii[4];
147    this->next(&r);
148    r.sort();
149    for (SkVector& vec : radii) {
150        this->nextRange(&vec.fX, 0.0f, 1.0f);
151        vec.fX *= 0.5f * r.width();
152        this->nextRange(&vec.fY, 0.0f, 1.0f);
153        vec.fY *= 0.5f * r.height();
154    }
155    rr->setRectRadii(r, radii);
156}
157
158template <>
159inline void Fuzz::next(SkBlendMode* mode) {
160    fuzz_enum_range(this, mode, 0, SkBlendMode::kLastMode);
161}
162
163static sk_sp<SkImage> make_fuzz_image(Fuzz*);
164
165static SkBitmap make_fuzz_bitmap(Fuzz*);
166
167static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
168
169static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
170    if (depth <= 0) {
171        return nullptr;
172    }
173    int colorFilterType;
174    fuzz->nextRange(&colorFilterType, 0, 8);
175    switch (colorFilterType) {
176        case 0:
177            return nullptr;
178        case 1: {
179            SkColor color;
180            SkBlendMode mode;
181            fuzz->next(&color, &mode);
182            return SkColorFilter::MakeModeFilter(color, mode);
183        }
184        case 2: {
185            sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
186            if (!outer) {
187                return nullptr;
188            }
189            sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
190            // makeComposed should be able to handle nullptr.
191            return outer->makeComposed(std::move(inner));
192        }
193        case 3: {
194            SkScalar array[20];
195            fuzz->nextN(array, SK_ARRAY_COUNT(array));
196            return SkColorFilter::MakeMatrixFilterRowMajor255(array);
197        }
198        case 4: {
199            SkColor mul, add;
200            fuzz->next(&mul, &add);
201            return SkColorMatrixFilter::MakeLightingFilter(mul, add);
202        }
203        case 5: {
204            bool grayscale;
205            int invertStyle;
206            float contrast;
207            fuzz->next(&grayscale);
208            fuzz->nextRange(&invertStyle, 0, 2);
209            fuzz->nextRange(&contrast, -1.0f, 1.0f);
210            return SkHighContrastFilter::Make(SkHighContrastConfig(
211                    grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
212        }
213        case 6:
214            return SkLumaColorFilter::Make();
215        case 7: {
216            uint8_t table[256];
217            fuzz->nextN(table, SK_ARRAY_COUNT(table));
218            return SkTableColorFilter::Make(table);
219        }
220        case 8: {
221            uint8_t tableA[256];
222            uint8_t tableR[256];
223            uint8_t tableG[256];
224            uint8_t tableB[256];
225            fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
226            fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
227            fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
228            fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
229            return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
230        }
231        default:
232            SkASSERT(false);
233            break;
234    }
235    return nullptr;
236}
237
238static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
239    SkScalar totalPos = 0;
240    for (int i = 0; i < colorCount; ++i) {
241        fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
242        totalPos += pos[i];
243    }
244    totalPos = 1.0f / totalPos;
245    for (int i = 0; i < colorCount; ++i) {
246        pos[i] *= totalPos;
247    }
248    // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
249    pos[colorCount - 1] = 1.0f;
250}
251
252static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
253    sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
254    sk_sp<SkColorFilter> colorFilter(nullptr);
255    SkBitmap bitmap;
256    sk_sp<SkImage> img;
257    SkShader::TileMode tmX, tmY;
258    bool useMatrix;
259    SkColor color;
260    SkMatrix matrix;
261    SkBlendMode blendMode;
262    int shaderType;
263    if (depth <= 0) {
264        return nullptr;
265    }
266    fuzz->nextRange(&shaderType, 0, 14);
267    switch (shaderType) {
268        case 0:
269            return nullptr;
270        case 1:
271            return SkShader::MakeEmptyShader();
272        case 2:
273            fuzz->next(&color);
274            return SkShader::MakeColorShader(color);
275        case 3:
276            img = make_fuzz_image(fuzz);
277            fuzz->next(&tmX, &tmY, &useMatrix);
278            if (useMatrix) {
279                fuzz->next(&matrix);
280            }
281            return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
282        case 4:
283            bitmap = make_fuzz_bitmap(fuzz);
284            fuzz->next(&tmX, &tmY, &useMatrix);
285            if (useMatrix) {
286                fuzz->next(&matrix);
287            }
288            return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
289        case 5:
290            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
291            fuzz->next(&matrix);
292            return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
293        case 6:
294            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
295            colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
296            return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
297        case 7:
298            shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
299            shader2 = make_fuzz_shader(fuzz, depth - 1);
300            fuzz->next(&blendMode);
301            return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
302        case 8: {
303            auto pic = make_fuzz_picture(fuzz, depth - 1);
304            bool useTile;
305            SkRect tile;
306            fuzz->next(&tmX, &tmY, &useMatrix, &useTile);
307            if (useMatrix) {
308                fuzz->next(&matrix);
309            }
310            if (useTile) {
311                fuzz->next(&tile);
312            }
313            return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
314                                               useMatrix ? &matrix : nullptr,
315                                               useTile ? &tile : nullptr);
316        }
317        // EFFECTS:
318        case 9:
319            // Deprecated SkGaussianEdgeShader
320            return nullptr;
321        case 10: {
322            constexpr int kMaxColors = 12;
323            SkPoint pts[2];
324            SkColor colors[kMaxColors];
325            SkScalar pos[kMaxColors];
326            int colorCount;
327            bool usePos;
328            fuzz->nextN(pts, 2);
329            fuzz->nextRange(&colorCount, 2, kMaxColors);
330            fuzz->nextN(colors, colorCount);
331            fuzz->next(&tmX, &useMatrix, &usePos);
332            if (useMatrix) {
333                fuzz->next(&matrix);
334            }
335            if (usePos) {
336                fuzz_gradient_stops(fuzz, pos, colorCount);
337            }
338            return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
339                                                tmX, 0, useMatrix ? &matrix : nullptr);
340        }
341        case 11: {
342            constexpr int kMaxColors = 12;
343            SkPoint center;
344            SkScalar radius;
345            int colorCount;
346            bool usePos;
347            SkColor colors[kMaxColors];
348            SkScalar pos[kMaxColors];
349            fuzz->next(&tmX, &useMatrix, &usePos, &center, &radius);
350            fuzz->nextRange(&colorCount, 2, kMaxColors);
351            fuzz->nextN(colors, colorCount);
352            if (useMatrix) {
353                fuzz->next(&matrix);
354            }
355            if (usePos) {
356                fuzz_gradient_stops(fuzz, pos, colorCount);
357            }
358            return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
359                                                colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
360        }
361        case 12: {
362            constexpr int kMaxColors = 12;
363            SkPoint start, end;
364            SkScalar startRadius, endRadius;
365            int colorCount;
366            bool usePos;
367            SkColor colors[kMaxColors];
368            SkScalar pos[kMaxColors];
369            fuzz->next(&tmX, &useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
370            fuzz->nextRange(&colorCount, 2, kMaxColors);
371            fuzz->nextN(colors, colorCount);
372            if (useMatrix) {
373                fuzz->next(&matrix);
374            }
375            if (usePos) {
376                fuzz_gradient_stops(fuzz, pos, colorCount);
377            }
378            return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
379                                                         usePos ? pos : nullptr, colorCount, tmX, 0,
380                                                         useMatrix ? &matrix : nullptr);
381        }
382        case 13: {
383            constexpr int kMaxColors = 12;
384            SkScalar cx, cy;
385            int colorCount;
386            bool usePos;
387            SkColor colors[kMaxColors];
388            SkScalar pos[kMaxColors];
389            fuzz->next(&cx, &cy, &useMatrix, &usePos);
390            fuzz->nextRange(&colorCount, 2, kMaxColors);
391            fuzz->nextN(colors, colorCount);
392            if (useMatrix) {
393                fuzz->next(&matrix);
394            }
395            if (usePos) {
396                fuzz_gradient_stops(fuzz, pos, colorCount);
397            }
398            return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
399                                               0, useMatrix ? &matrix : nullptr);
400        }
401        case 14: {
402            SkScalar baseFrequencyX, baseFrequencyY, seed;
403            int numOctaves;
404            SkISize tileSize;
405            bool useTileSize, turbulence;
406            fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
407            if (useTileSize) {
408                fuzz->next(&tileSize);
409            }
410            fuzz->nextRange(&numOctaves, 2, 7);
411            if (turbulence) {
412                return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
413                                                           numOctaves, seed,
414                                                           useTileSize ? &tileSize : nullptr);
415            } else {
416                return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
417                                                             numOctaves, seed,
418                                                             useTileSize ? &tileSize : nullptr);
419            }
420        }
421        default:
422            SkASSERT(false);
423            break;
424    }
425    return nullptr;
426}
427
428static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
429    if (depth <= 0) {
430        return nullptr;
431    }
432    uint8_t pathEffectType;
433    fuzz->nextRange(&pathEffectType, 0, 8);
434    switch (pathEffectType) {
435        case 0: {
436            return nullptr;
437        }
438        case 1: {
439            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
440            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
441            return SkPathEffect::MakeSum(std::move(first), std::move(second));
442        }
443        case 2: {
444            sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
445            sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
446            return SkPathEffect::MakeCompose(std::move(first), std::move(second));
447        }
448        case 3: {
449            SkPath path;
450            fuzz_path(fuzz, &path, 20);
451            SkScalar advance, phase;
452            fuzz->next(&advance, &phase);
453            SkPath1DPathEffect::Style style;
454            fuzz_enum_range(fuzz, &style, 0, SkPath1DPathEffect::kLastEnum_Style);
455            return SkPath1DPathEffect::Make(path, advance, phase, style);
456        }
457        case 4: {
458            SkScalar width;
459            SkMatrix matrix;
460            fuzz->next(&width, &matrix);
461            return SkLine2DPathEffect::Make(width, matrix);
462        }
463        case 5: {
464            SkPath path;
465            fuzz_path(fuzz, &path, 20);
466            SkMatrix matrix;
467            fuzz->next(&matrix);
468            return SkPath2DPathEffect::Make(matrix, path);
469        }
470        case 6: {
471            SkScalar radius;
472            fuzz->next(&radius);
473            return SkCornerPathEffect::Make(radius);
474        }
475        case 7: {
476            SkScalar phase;
477            fuzz->next(&phase);
478            SkScalar intervals[20];
479            int count;
480            fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
481            fuzz->nextN(intervals, count);
482            return SkDashPathEffect::Make(intervals, count, phase);
483        }
484        case 8: {
485            SkScalar segLength, dev;
486            uint32_t seed;
487            fuzz->next(&segLength, &dev, &seed);
488            return SkDiscretePathEffect::Make(segLength, dev, seed);
489        }
490        default:
491            SkASSERT(false);
492            return nullptr;
493    }
494}
495
496static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
497    int maskfilterType;
498    fuzz->nextRange(&maskfilterType, 0, 2);
499    switch (maskfilterType) {
500        case 0:
501            return nullptr;
502        case 1: {
503            SkBlurStyle blurStyle;
504            fuzz_enum_range(fuzz, &blurStyle, 0, kLastEnum_SkBlurStyle);
505            SkScalar sigma;
506            fuzz->next(&sigma);
507            SkRect occluder{0.0f, 0.0f, 0.0f, 0.0f};
508            if (make_fuzz_t<bool>(fuzz)) {
509                fuzz->next(&occluder);
510            }
511            uint32_t flags;
512            fuzz->nextRange(&flags, 0, 3);
513            return SkBlurMaskFilter::Make(blurStyle, sigma, occluder, flags);
514        }
515        case 2: {
516            SkRRect first, second;
517            SkScalar radius;
518            fuzz->next(&first, &second, &radius);
519            return SkRRectsGaussianEdgeMaskFilter::Make(first, second, radius);
520        }
521        default:
522            SkASSERT(false);
523            return nullptr;
524    }
525}
526
527static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
528    if (make_fuzz_t<bool>(fuzz)) {
529        return nullptr;
530    }
531    auto fontMugger = SkFontMgr::RefDefault();
532    SkASSERT(fontMugger);
533    int familyCount = fontMugger->countFamilies();
534    int i, j;
535    fuzz->nextRange(&i, 0, familyCount - 1);
536    sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
537    int styleCount = family->count();
538    fuzz->nextRange(&j, 0, styleCount - 1);
539    return sk_sp<SkTypeface>(family->createTypeface(j));
540}
541
542template <>
543inline void Fuzz::next(SkImageFilter::CropRect* cropRect) {
544    SkRect rect;
545    uint8_t flags;
546    this->next(&rect);
547    this->nextRange(&flags, 0, 0xF);
548    *cropRect = SkImageFilter::CropRect(rect, flags);
549}
550
551static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
552
553static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
554    if (depth <= 0) {
555        return nullptr;
556    }
557    uint8_t imageFilterType;
558    fuzz->nextRange(&imageFilterType, 1, 6);
559    SkPoint3 p, q;
560    SkColor lightColor;
561    SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
562    sk_sp<SkImageFilter> input;
563    SkImageFilter::CropRect cropRect;
564    bool useCropRect;
565    fuzz->next(&useCropRect);
566    if (useCropRect) {
567        fuzz->next(&cropRect);
568    }
569    switch (imageFilterType) {
570        case 1:
571            fuzz->next(&p, &lightColor, &surfaceScale, &k);
572            input = make_fuzz_imageFilter(fuzz, depth - 1);
573            return SkLightingImageFilter::MakeDistantLitDiffuse(p, lightColor, surfaceScale, k,
574                                                                std::move(input),
575                                                                useCropRect ? &cropRect : nullptr);
576        case 2:
577            fuzz->next(&p, &lightColor, &surfaceScale, &k);
578            input = make_fuzz_imageFilter(fuzz, depth - 1);
579            return SkLightingImageFilter::MakePointLitDiffuse(p, lightColor, surfaceScale, k,
580                                                              std::move(input),
581                                                              useCropRect ? &cropRect : nullptr);
582        case 3:
583            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
584            input = make_fuzz_imageFilter(fuzz, depth - 1);
585            return SkLightingImageFilter::MakeSpotLitDiffuse(
586                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
587                    std::move(input), useCropRect ? &cropRect : nullptr);
588        case 4:
589            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
590            input = make_fuzz_imageFilter(fuzz, depth - 1);
591            return SkLightingImageFilter::MakeDistantLitSpecular(p, lightColor, surfaceScale, k,
592                                                                 shininess, std::move(input),
593                                                                 useCropRect ? &cropRect : nullptr);
594        case 5:
595            fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
596            input = make_fuzz_imageFilter(fuzz, depth - 1);
597            return SkLightingImageFilter::MakePointLitSpecular(p, lightColor, surfaceScale, k,
598                                                               shininess, std::move(input),
599                                                               useCropRect ? &cropRect : nullptr);
600        case 6:
601            fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
602                       &shininess);
603            input = make_fuzz_imageFilter(fuzz, depth - 1);
604            return SkLightingImageFilter::MakeSpotLitSpecular(
605                    p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
606                    std::move(input), useCropRect ? &cropRect : nullptr);
607        default:
608            SkASSERT(false);
609            return nullptr;
610    }
611}
612
613static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
614
615static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
616    if (depth <= 0) {
617        return nullptr;
618    }
619    uint8_t imageFilterType;
620    fuzz->nextRange(&imageFilterType, 0, 23);
621    switch (imageFilterType) {
622        case 0:
623            return nullptr;
624        case 1: {
625            SkScalar sigmaX, sigmaY;
626            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
627            bool useCropRect;
628            fuzz->next(&sigmaX, &sigmaY, &useCropRect);
629            SkImageFilter::CropRect cropRect;
630            if (useCropRect) {
631                fuzz->next(&cropRect);
632            }
633            return SkBlurImageFilter::Make(sigmaX, sigmaY, std::move(input),
634                                           useCropRect ? &cropRect : nullptr);
635        }
636        case 2: {
637            SkMatrix matrix;
638            SkFilterQuality quality;
639            fuzz->next(&matrix, &quality);
640            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
641            return SkImageFilter::MakeMatrixFilter(matrix, quality, std::move(input));
642        }
643        case 3: {
644            SkRegion region;
645            SkScalar innerMin, outerMax;
646            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
647            bool useCropRect;
648            fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
649            SkImageFilter::CropRect cropRect;
650            if (useCropRect) {
651                fuzz->next(&cropRect);
652            }
653            return SkAlphaThresholdFilter::Make(region, innerMin, outerMax, std::move(input),
654                                                useCropRect ? &cropRect : nullptr);
655        }
656        case 4: {
657            float k1, k2, k3, k4;
658            bool enforcePMColor;
659            bool useCropRect;
660            fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
661            sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
662            sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
663            SkImageFilter::CropRect cropRect;
664            if (useCropRect) {
665                fuzz->next(&cropRect);
666            }
667            return SkArithmeticImageFilter::Make(k1, k2, k3, k4, enforcePMColor,
668                                                 std::move(background), std::move(foreground),
669                                                 useCropRect ? &cropRect : nullptr);
670        }
671        case 5: {
672            sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
673            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
674            bool useCropRect;
675            SkImageFilter::CropRect cropRect;
676            fuzz->next(&useCropRect);
677            if (useCropRect) {
678                fuzz->next(&cropRect);
679            }
680            return SkColorFilterImageFilter::Make(std::move(cf), std::move(input),
681                                                  useCropRect ? &cropRect : nullptr);
682        }
683        case 6: {
684            sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
685            sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
686            return SkComposeImageFilter::Make(std::move(ifo), std::move(ifi));
687        }
688        case 7: {
689            SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, yChannelSelector;
690            fuzz_enum_range(fuzz, &xChannelSelector, 1, 4);
691            fuzz_enum_range(fuzz, &yChannelSelector, 1, 4);
692            SkScalar scale;
693            bool useCropRect;
694            fuzz->next(&scale, &useCropRect);
695            SkImageFilter::CropRect cropRect;
696            if (useCropRect) {
697                fuzz->next(&cropRect);
698            }
699            sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
700            sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
701            return SkDisplacementMapEffect::Make(xChannelSelector, yChannelSelector, scale,
702                                                 std::move(displacement), std::move(color),
703                                                 useCropRect ? &cropRect : nullptr);
704        }
705        case 8: {
706            SkScalar dx, dy, sigmaX, sigmaY;
707            SkColor color;
708            SkDropShadowImageFilter::ShadowMode shadowMode;
709            fuzz_enum_range(fuzz, &shadowMode, 0, 1);
710            bool useCropRect;
711            fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &useCropRect);
712            SkImageFilter::CropRect cropRect;
713            if (useCropRect) {
714                fuzz->next(&cropRect);
715            }
716            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
717            return SkDropShadowImageFilter::Make(dx, dy, sigmaX, sigmaY, color, shadowMode,
718                                                 std::move(input),
719                                                 useCropRect ? &cropRect : nullptr);
720        }
721        case 9:
722            return SkImageSource::Make(make_fuzz_image(fuzz));
723        case 10: {
724            sk_sp<SkImage> image = make_fuzz_image(fuzz);
725            SkRect srcRect, dstRect;
726            SkFilterQuality filterQuality;
727            fuzz->next(&srcRect, &dstRect, &filterQuality);
728            return SkImageSource::Make(std::move(image), srcRect, dstRect, filterQuality);
729        }
730        case 11:
731            return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
732        case 12: {
733            SkRect srcRect;
734            SkScalar inset;
735            bool useCropRect;
736            SkImageFilter::CropRect cropRect;
737            fuzz->next(&srcRect, &inset, &useCropRect);
738            if (useCropRect) {
739                fuzz->next(&cropRect);
740            }
741            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
742            return SkMagnifierImageFilter::Make(srcRect, inset, std::move(input),
743                                                useCropRect ? &cropRect : nullptr);
744        }
745        case 13: {
746            constexpr int kMaxKernelSize = 5;
747            int32_t n, m;
748            fuzz->nextRange(&n, 1, kMaxKernelSize);
749            fuzz->nextRange(&m, 1, kMaxKernelSize);
750            SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
751            fuzz->nextN(kernel, n * m);
752            int32_t offsetX, offsetY;
753            fuzz->nextRange(&offsetX, 0, n - 1);
754            fuzz->nextRange(&offsetY, 0, m - 1);
755            SkScalar gain, bias;
756            bool convolveAlpha, useCropRect;
757            fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
758            SkMatrixConvolutionImageFilter::TileMode tileMode;
759            fuzz_enum_range(fuzz, &tileMode, 0, 2);
760            SkImageFilter::CropRect cropRect;
761            if (useCropRect) {
762                fuzz->next(&cropRect);
763            }
764            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
765            return SkMatrixConvolutionImageFilter::Make(
766                    SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
767                    convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
768        }
769        case 14: {
770            sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
771            sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
772            bool useCropRect;
773            fuzz->next(&useCropRect);
774            SkImageFilter::CropRect cropRect;
775            if (useCropRect) {
776                fuzz->next(&cropRect);
777            }
778            return SkMergeImageFilter::Make(std::move(first), std::move(second),
779                                            useCropRect ? &cropRect : nullptr);
780        }
781        case 15: {
782            constexpr int kMaxCount = 4;
783            sk_sp<SkImageFilter> ifs[kMaxCount];
784            int count;
785            fuzz->nextRange(&count, 1, kMaxCount);
786            for (int i = 0; i < count; ++i) {
787                ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
788            }
789            bool useCropRect;
790            fuzz->next(&useCropRect);
791            SkImageFilter::CropRect cropRect;
792            if (useCropRect) {
793                fuzz->next(&cropRect);
794            }
795            return SkMergeImageFilter::Make(ifs, count, useCropRect ? &cropRect : nullptr);
796        }
797        case 16: {
798            int rx, ry;
799            fuzz->next(&rx, &ry);
800            bool useCropRect;
801            fuzz->next(&useCropRect);
802            SkImageFilter::CropRect cropRect;
803            if (useCropRect) {
804                fuzz->next(&cropRect);
805            }
806            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
807            return SkDilateImageFilter::Make(rx, ry, std::move(input),
808                                             useCropRect ? &cropRect : nullptr);
809        }
810        case 17: {
811            int rx, ry;
812            fuzz->next(&rx, &ry);
813            bool useCropRect;
814            fuzz->next(&useCropRect);
815            SkImageFilter::CropRect cropRect;
816            if (useCropRect) {
817                fuzz->next(&cropRect);
818            }
819            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
820            return SkErodeImageFilter::Make(rx, ry, std::move(input),
821                                            useCropRect ? &cropRect : nullptr);
822        }
823        case 18: {
824            SkScalar dx, dy;
825            fuzz->next(&dx, &dy);
826            bool useCropRect;
827            fuzz->next(&useCropRect);
828            SkImageFilter::CropRect cropRect;
829            if (useCropRect) {
830                fuzz->next(&cropRect);
831            }
832            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
833            return SkOffsetImageFilter::Make(dx, dy, std::move(input),
834                                             useCropRect ? &cropRect : nullptr);
835        }
836        case 19: {
837            SkPaint paint;
838            fuzz_paint(fuzz, &paint, depth - 1);
839            bool useCropRect;
840            fuzz->next(&useCropRect);
841            SkImageFilter::CropRect cropRect;
842            if (useCropRect) {
843                fuzz->next(&cropRect);
844            }
845            return SkPaintImageFilter::Make(paint, useCropRect ? &cropRect : nullptr);
846        }
847        case 20: {
848            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
849            return SkPictureImageFilter::Make(std::move(picture));
850        }
851        case 21: {
852            SkRect cropRect;
853            fuzz->next(&cropRect);
854            sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
855            return SkPictureImageFilter::Make(std::move(picture), cropRect);
856        }
857        case 22: {
858            SkRect src, dst;
859            fuzz->next(&src, &dst);
860            sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
861            return SkTileImageFilter::Make(src, dst, std::move(input));
862        }
863        case 23: {
864            SkBlendMode blendMode;
865            bool useCropRect;
866            fuzz->next(&useCropRect, &blendMode);
867            SkImageFilter::CropRect cropRect;
868            if (useCropRect) {
869                fuzz->next(&cropRect);
870            }
871            sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
872            sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
873            return SkXfermodeImageFilter::Make(blendMode, std::move(bg), std::move(fg),
874                                               useCropRect ? &cropRect : nullptr);
875        }
876        default:
877            SkASSERT(false);
878            return nullptr;
879    }
880}
881
882static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
883    int w, h;
884    fuzz->nextRange(&w, 1, 1024);
885    fuzz->nextRange(&h, 1, 1024);
886    SkAutoTMalloc<SkPMColor> data(w * h);
887    SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
888    int n = w * h;
889    for (int i = 0; i < n; ++i) {
890        SkColor c;
891        fuzz->next(&c);
892        data[i] = SkPreMultiplyColor(c);
893    }
894    (void)data.release();
895    return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
896                                   nullptr);
897}
898
899static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
900    SkBitmap bitmap;
901    int w, h;
902    fuzz->nextRange(&w, 1, 1024);
903    fuzz->nextRange(&h, 1, 1024);
904    if (!bitmap.tryAllocN32Pixels(w, h)) {
905        SkDEBUGF(("Could not allocate pixels %d x %d", w, h));
906        return bitmap;
907    }
908    for (int y = 0; y < h; ++y) {
909        for (int x = 0; x < w; ++x) {
910            SkColor c;
911            fuzz->next(&c);
912            *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
913        }
914    }
915    return bitmap;
916}
917
918template <typename T, typename Min, typename Max>
919inline T make_fuzz_t_range(Fuzz* fuzz, Min minv, Max maxv) {
920    T value;
921    fuzz_enum_range(fuzz, &value, minv, maxv);
922    return value;
923}
924
925static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
926    if (!fuzz || !paint || depth <= 0) {
927        return;
928    }
929
930    paint->setAntiAlias(    make_fuzz_t<bool>(fuzz));
931    paint->setDither(       make_fuzz_t<bool>(fuzz));
932    paint->setColor(        make_fuzz_t<SkColor>(fuzz));
933    paint->setBlendMode(    make_fuzz_t_range<SkBlendMode>(fuzz, 0, SkBlendMode::kLastMode));
934    paint->setFilterQuality(make_fuzz_t_range<SkFilterQuality>(fuzz, 0, kLast_SkFilterQuality));
935    paint->setStyle(        make_fuzz_t_range<SkPaint::Style>(fuzz, 0, 2));
936    paint->setShader(       make_fuzz_shader(fuzz, depth - 1));
937    paint->setPathEffect(   make_fuzz_patheffect(fuzz, depth - 1));
938    paint->setMaskFilter(   make_fuzz_maskfilter(fuzz));
939    paint->setImageFilter(  make_fuzz_imageFilter(fuzz, depth - 1));
940    paint->setColorFilter(  make_fuzz_colorfilter(fuzz, depth - 1));
941
942    if (paint->getStyle() != SkPaint::kFill_Style) {
943        paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
944        paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
945        paint->setStrokeCap(  make_fuzz_t_range<SkPaint::Cap>(fuzz, 0, SkPaint::kLast_Cap));
946        paint->setStrokeJoin( make_fuzz_t_range<SkPaint::Join>(fuzz, 0, SkPaint::kLast_Join));
947    }
948}
949
950static void fuzz_paint_text(Fuzz* fuzz, SkPaint* paint) {
951    paint->setTypeface(          make_fuzz_typeface(fuzz));
952    paint->setTextSize(          make_fuzz_t<SkScalar>(fuzz));
953    paint->setTextScaleX(        make_fuzz_t<SkScalar>(fuzz));
954    paint->setTextSkewX(         make_fuzz_t<SkScalar>(fuzz));
955    paint->setLinearText(        make_fuzz_t<bool>(fuzz));
956    paint->setSubpixelText(      make_fuzz_t<bool>(fuzz));
957    paint->setLCDRenderText(     make_fuzz_t<bool>(fuzz));
958    paint->setEmbeddedBitmapText(make_fuzz_t<bool>(fuzz));
959    paint->setAutohinted(        make_fuzz_t<bool>(fuzz));
960    paint->setVerticalText(      make_fuzz_t<bool>(fuzz));
961    paint->setFakeBoldText(      make_fuzz_t<bool>(fuzz));
962    paint->setDevKernText(       make_fuzz_t<bool>(fuzz));
963    paint->setHinting(           make_fuzz_t_range<SkPaint::Hinting>(fuzz, 0,
964                                                                     SkPaint::kFull_Hinting));
965    paint->setTextAlign(         make_fuzz_t_range<SkPaint::Align>(fuzz, 0, 2));
966}
967
968static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
969    paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
970}
971
972constexpr int kMaxGlyphCount = 30;
973
974static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
975    SkTDArray<uint8_t> array;
976    if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
977        int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
978                                             : SkTypeface::MakeDefault()->countGlyphs();
979        if (glyphRange == 0) {
980            // Some fuzzing environments have no fonts, so empty array is the best
981            // we can do.
982            return array;
983        }
984        int glyphCount;
985        fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
986        SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
987        for (int i = 0; i < glyphCount; ++i) {
988            fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
989        }
990        return array;
991    }
992    static const SkUnichar ranges[][2] = {
993        {0x0020, 0x007F},
994        {0x00A1, 0x0250},
995        {0x0400, 0x0500},
996    };
997    int32_t count = 0;
998    for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
999        count += (ranges[i][1] - ranges[i][0]);
1000    }
1001    constexpr int kMaxLength = kMaxGlyphCount;
1002    SkUnichar buffer[kMaxLength];
1003    int length;
1004    fuzz->nextRange(&length, 1, kMaxLength);
1005    for (int j = 0; j < length; ++j) {
1006        int32_t value;
1007        fuzz->nextRange(&value, 0, count - 1);
1008        for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
1009            if (value + ranges[i][0] < ranges[i][1]) {
1010                buffer[j] = value + ranges[i][0];
1011                break;
1012            } else {
1013                value -= (ranges[i][1] - ranges[i][0]);
1014            }
1015        }
1016    }
1017    switch (paint.getTextEncoding()) {
1018        case SkPaint::kUTF8_TextEncoding: {
1019            size_t utf8len = 0;
1020            for (int j = 0; j < length; ++j) {
1021                utf8len += SkUTF8_FromUnichar(buffer[j], nullptr);
1022            }
1023            char* ptr = (char*)array.append(utf8len);
1024            for (int j = 0; j < length; ++j) {
1025                ptr += SkUTF8_FromUnichar(buffer[j], ptr);
1026            }
1027        } break;
1028        case SkPaint::kUTF16_TextEncoding: {
1029            size_t utf16len = 0;
1030            for (int j = 0; j < length; ++j) {
1031                utf16len += SkUTF16_FromUnichar(buffer[j]);
1032            }
1033            uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
1034            for (int j = 0; j < length; ++j) {
1035                ptr += SkUTF16_FromUnichar(buffer[j], ptr);
1036            }
1037        } break;
1038        case SkPaint::kUTF32_TextEncoding:
1039            memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
1040            break;
1041        default:
1042            SkASSERT(false);
1043            break;
1044    }
1045    return array;
1046}
1047
1048static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
1049    SkTextBlobBuilder textBlobBuilder;
1050    int8_t runCount;
1051    fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
1052    while (runCount-- > 0) {
1053        SkPaint paint;
1054        fuzz_paint_text_encoding(fuzz, &paint);
1055        paint.setAntiAlias(make_fuzz_t<bool>(fuzz));
1056        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1057        SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1058        int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1059        SkASSERT(glyphCount <= kMaxGlyphCount);
1060        SkScalar x, y;
1061        const SkTextBlobBuilder::RunBuffer* buffer;
1062        uint8_t runType;
1063        fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
1064        switch (runType) {
1065            case 0:
1066                fuzz->next(&x, &y);
1067                // TODO: Test other variations of this.
1068                buffer = &textBlobBuilder.allocRun(paint, glyphCount, x, y);
1069                memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1070                break;
1071            case 1:
1072                fuzz->next(&y);
1073                // TODO: Test other variations of this.
1074                buffer = &textBlobBuilder.allocRunPosH(paint, glyphCount, y);
1075                memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1076                fuzz->nextN(buffer->pos, glyphCount);
1077                break;
1078            case 2:
1079                // TODO: Test other variations of this.
1080                buffer = &textBlobBuilder.allocRunPos(paint, glyphCount);
1081                memcpy(buffer->glyphs, text.begin(), SkToSizeT(text.count()));
1082                fuzz->nextN(buffer->pos, glyphCount * 2);
1083                break;
1084            default:
1085                SkASSERT(false);
1086                break;
1087        }
1088    }
1089    return textBlobBuilder.make();
1090}
1091
1092static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
1093    if (!fuzz || !canvas || depth <= 0) {
1094        return;
1095    }
1096    SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1097    unsigned N;
1098    fuzz->nextRange(&N, 0, 2000);
1099    for (unsigned i = 0; i < N; ++i) {
1100        if (fuzz->exhausted()) {
1101            return;
1102        }
1103        SkPaint paint;
1104        SkMatrix matrix;
1105        unsigned drawCommand;
1106        fuzz->nextRange(&drawCommand, 0, 53);
1107        switch (drawCommand) {
1108            case 0:
1109                canvas->flush();
1110                break;
1111            case 1:
1112                canvas->save();
1113                break;
1114            case 2: {
1115                SkRect bounds;
1116                fuzz->next(&bounds);
1117                fuzz_paint(fuzz, &paint, depth - 1);
1118                canvas->saveLayer(&bounds, &paint);
1119                break;
1120            }
1121            case 3: {
1122                SkRect bounds;
1123                fuzz->next(&bounds);
1124                canvas->saveLayer(&bounds, nullptr);
1125                break;
1126            }
1127            case 4:
1128                fuzz_paint(fuzz, &paint, depth - 1);
1129                canvas->saveLayer(nullptr, &paint);
1130                break;
1131            case 5:
1132                canvas->saveLayer(nullptr, nullptr);
1133                break;
1134            case 6: {
1135                uint8_t alpha;
1136                fuzz->next(&alpha);
1137                canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1138                break;
1139            }
1140            case 7: {
1141                SkRect bounds;
1142                uint8_t alpha;
1143                fuzz->next(&bounds, &alpha);
1144                canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1145                break;
1146            }
1147            case 8: {
1148                SkCanvas::SaveLayerRec saveLayerRec;
1149                SkRect bounds;
1150                if (make_fuzz_t<bool>(fuzz)) {
1151                    fuzz->next(&bounds);
1152                    saveLayerRec.fBounds = &bounds;
1153                }
1154                if (make_fuzz_t<bool>(fuzz)) {
1155                    fuzz_paint(fuzz, &paint, depth - 1);
1156                    saveLayerRec.fPaint = &paint;
1157                }
1158                sk_sp<SkImageFilter> imageFilter;
1159                if (make_fuzz_t<bool>(fuzz)) {
1160                    imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1161                    saveLayerRec.fBackdrop = imageFilter.get();
1162                }
1163                // _DumpCanvas can't handle this.
1164                // if (make_fuzz_t<bool>(fuzz)) {
1165                //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1166                // }
1167
1168                canvas->saveLayer(saveLayerRec);
1169                break;
1170            }
1171            case 9:
1172                canvas->restore();
1173                break;
1174            case 10: {
1175                int saveCount;
1176                fuzz->next(&saveCount);
1177                canvas->restoreToCount(saveCount);
1178                break;
1179            }
1180            case 11: {
1181                SkScalar x, y;
1182                fuzz->next(&x, &y);
1183                canvas->translate(x, y);
1184                break;
1185            }
1186            case 12: {
1187                SkScalar x, y;
1188                fuzz->next(&x, &y);
1189                canvas->scale(x, y);
1190                break;
1191            }
1192            case 13: {
1193                SkScalar v;
1194                fuzz->next(&v);
1195                canvas->rotate(v);
1196                break;
1197            }
1198            case 14: {
1199                SkScalar x, y, v;
1200                fuzz->next(&x, &y, &v);
1201                canvas->rotate(v, x, y);
1202                break;
1203            }
1204            case 15: {
1205                SkScalar x, y;
1206                fuzz->next(&x, &y);
1207                canvas->skew(x, y);
1208                break;
1209            }
1210            case 16: {
1211                SkMatrix mat;
1212                fuzz->next(&mat);
1213                canvas->concat(mat);
1214                break;
1215            }
1216            case 17: {
1217                SkMatrix mat;
1218                fuzz->next(&mat);
1219                canvas->setMatrix(mat);
1220                break;
1221            }
1222            case 18:
1223                canvas->resetMatrix();
1224                break;
1225            case 19: {
1226                SkRect r;
1227                int op;
1228                bool doAntiAlias;
1229                fuzz->next(&r, &doAntiAlias);
1230                fuzz->nextRange(&op, 0, 1);
1231                r.sort();
1232                canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1233                break;
1234            }
1235            case 20: {
1236                SkRRect rr;
1237                int op;
1238                bool doAntiAlias;
1239                fuzz->next(&rr);
1240                fuzz->next(&doAntiAlias);
1241                fuzz->nextRange(&op, 0, 1);
1242                canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1243                break;
1244            }
1245            case 21: {
1246                SkPath path;
1247                fuzz_path(fuzz, &path, 30);
1248                int op;
1249                bool doAntiAlias;
1250                fuzz->next(&doAntiAlias);
1251                fuzz->nextRange(&op, 0, 1);
1252                canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1253                break;
1254            }
1255            case 22: {
1256                SkRegion region;
1257                int op;
1258                fuzz->next(&region);
1259                fuzz->nextRange(&op, 0, 1);
1260                canvas->clipRegion(region, (SkClipOp)op);
1261                break;
1262            }
1263            case 23:
1264                fuzz_paint(fuzz, &paint, depth - 1);
1265                canvas->drawPaint(paint);
1266                break;
1267            case 24: {
1268                fuzz_paint(fuzz, &paint, depth - 1);
1269                SkCanvas::PointMode pointMode;
1270                fuzz_enum_range(fuzz, &pointMode,
1271                                SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
1272                size_t count;
1273                constexpr int kMaxCount = 30;
1274                fuzz->nextRange(&count, 0, kMaxCount);
1275                SkPoint pts[kMaxCount];
1276                fuzz->nextN(pts, count);
1277                canvas->drawPoints(pointMode, count, pts, paint);
1278                break;
1279            }
1280            case 25: {
1281                fuzz_paint(fuzz, &paint, depth - 1);
1282                SkRect r;
1283                fuzz->next(&r);
1284                canvas->drawRect(r, paint);
1285                break;
1286            }
1287            case 26: {
1288                fuzz_paint(fuzz, &paint, depth - 1);
1289                SkRegion region;
1290                fuzz->next(&region);
1291                canvas->drawRegion(region, paint);
1292                break;
1293            }
1294            case 27: {
1295                fuzz_paint(fuzz, &paint, depth - 1);
1296                SkRect r;
1297                fuzz->next(&r);
1298                canvas->drawOval(r, paint);
1299                break;
1300            }
1301            case 28: break; // must have deleted this some time earlier
1302            case 29: {
1303                fuzz_paint(fuzz, &paint, depth - 1);
1304                SkRRect rr;
1305                fuzz->next(&rr);
1306                canvas->drawRRect(rr, paint);
1307                break;
1308            }
1309            case 30: {
1310                fuzz_paint(fuzz, &paint, depth - 1);
1311                SkRRect orr, irr;
1312                fuzz->next(&orr);
1313                fuzz->next(&irr);
1314                if (orr.getBounds().contains(irr.getBounds())) {
1315                    canvas->drawDRRect(orr, irr, paint);
1316                }
1317                break;
1318            }
1319            case 31: {
1320                fuzz_paint(fuzz, &paint, depth - 1);
1321                SkRect r;
1322                SkScalar start, sweep;
1323                bool useCenter;
1324                fuzz->next(&r, &start, &sweep, &useCenter);
1325                canvas->drawArc(r, start, sweep, useCenter, paint);
1326                break;
1327            }
1328            case 32: {
1329                SkPath path;
1330                fuzz_path(fuzz, &path, 60);
1331                canvas->drawPath(path, paint);
1332                break;
1333            }
1334            case 33: {
1335                sk_sp<SkImage> img = make_fuzz_image(fuzz);
1336                SkScalar left, top;
1337                bool usePaint;
1338                fuzz->next(&left, &top, &usePaint);
1339                if (usePaint) {
1340                    fuzz_paint(fuzz, &paint, depth - 1);
1341                }
1342                canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
1343                break;
1344            }
1345            case 34: {
1346                auto img = make_fuzz_image(fuzz);
1347                SkRect src, dst;
1348                bool usePaint;
1349                fuzz->next(&src, &dst, &usePaint);
1350                if (usePaint) {
1351                    fuzz_paint(fuzz, &paint, depth - 1);
1352                }
1353                SkCanvas::SrcRectConstraint constraint =
1354                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1355                                                : SkCanvas::kFast_SrcRectConstraint;
1356                canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1357                break;
1358            }
1359            case 35: {
1360                auto img = make_fuzz_image(fuzz);
1361                SkIRect src;
1362                SkRect dst;
1363                bool usePaint;
1364                fuzz->next(&src, &dst, &usePaint);
1365                if (usePaint) {
1366                    fuzz_paint(fuzz, &paint, depth - 1);
1367                }
1368                SkCanvas::SrcRectConstraint constraint =
1369                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1370                                                : SkCanvas::kFast_SrcRectConstraint;
1371                canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1372                break;
1373            }
1374            case 36: {
1375                bool usePaint;
1376                auto img = make_fuzz_image(fuzz);
1377                SkRect dst;
1378                fuzz->next(&dst, &usePaint);
1379                if (usePaint) {
1380                    fuzz_paint(fuzz, &paint, depth - 1);
1381                }
1382                SkCanvas::SrcRectConstraint constraint =
1383                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1384                                                : SkCanvas::kFast_SrcRectConstraint;
1385                canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr, constraint);
1386                break;
1387            }
1388            case 37: {
1389                auto img = make_fuzz_image(fuzz);
1390                SkIRect center;
1391                SkRect dst;
1392                bool usePaint;
1393                fuzz->next(&usePaint);
1394                if (usePaint) {
1395                    fuzz_paint(fuzz, &paint, depth - 1);
1396                }
1397                if (make_fuzz_t<bool>(fuzz)) {
1398                    fuzz->next(&center);
1399                } else {  // Make valid center, see SkLatticeIter::Valid().
1400                    fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1401                    fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1402                    fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1403                    fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1404                }
1405                fuzz->next(&dst);
1406                canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
1407                break;
1408            }
1409            case 38: {
1410                SkBitmap bitmap = make_fuzz_bitmap(fuzz);
1411                SkScalar left, top;
1412                bool usePaint;
1413                fuzz->next(&left, &top, &usePaint);
1414                if (usePaint) {
1415                    fuzz_paint(fuzz, &paint, depth - 1);
1416                }
1417                canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
1418                break;
1419            }
1420            case 39: {
1421                SkBitmap bitmap = make_fuzz_bitmap(fuzz);
1422                SkRect src, dst;
1423                bool usePaint;
1424                fuzz->next(&src, &dst, &usePaint);
1425                if (usePaint) {
1426                    fuzz_paint(fuzz, &paint, depth - 1);
1427                }
1428                SkCanvas::SrcRectConstraint constraint =
1429                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1430                                                : SkCanvas::kFast_SrcRectConstraint;
1431                canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
1432                break;
1433            }
1434            case 40: {
1435                SkBitmap img = make_fuzz_bitmap(fuzz);
1436                SkIRect src;
1437                SkRect dst;
1438                bool usePaint;
1439                fuzz->next(&src, &dst, &usePaint);
1440                if (usePaint) {
1441                    fuzz_paint(fuzz, &paint, depth - 1);
1442                }
1443                SkCanvas::SrcRectConstraint constraint =
1444                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1445                                                : SkCanvas::kFast_SrcRectConstraint;
1446                canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1447                break;
1448            }
1449            case 41: {
1450                SkBitmap img = make_fuzz_bitmap(fuzz);
1451                SkRect dst;
1452                bool usePaint;
1453                fuzz->next(&dst, &usePaint);
1454                if (usePaint) {
1455                    fuzz_paint(fuzz, &paint, depth - 1);
1456                }
1457                SkCanvas::SrcRectConstraint constraint =
1458                        make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1459                                                : SkCanvas::kFast_SrcRectConstraint;
1460                canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1461                break;
1462            }
1463            case 42: {
1464                SkBitmap img = make_fuzz_bitmap(fuzz);
1465                SkIRect center;
1466                SkRect dst;
1467                bool usePaint;
1468                fuzz->next(&usePaint);
1469                if (usePaint) {
1470                    fuzz_paint(fuzz, &paint, depth - 1);
1471                }
1472                if (make_fuzz_t<bool>(fuzz)) {
1473                    fuzz->next(&center);
1474                } else {  // Make valid center, see SkLatticeIter::Valid().
1475                    if (img.width() == 0 || img.height() == 0) {
1476                        // bitmap may not have had its pixels initialized.
1477                        break;
1478                    }
1479                    fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
1480                    fuzz->nextRange(&center.fTop, 0, img.height() - 1);
1481                    fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
1482                    fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
1483                }
1484                fuzz->next(&dst);
1485                canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1486                break;
1487            }
1488            case 43: {
1489                SkBitmap img = make_fuzz_bitmap(fuzz);
1490                bool usePaint;
1491                SkRect dst;
1492                fuzz->next(&usePaint, &dst);
1493                if (usePaint) {
1494                    fuzz_paint(fuzz, &paint, depth - 1);
1495                }
1496                constexpr int kMax = 6;
1497                int xDivs[kMax], yDivs[kMax];
1498                SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1499                fuzz->nextRange(&lattice.fXCount, 2, kMax);
1500                fuzz->nextRange(&lattice.fYCount, 2, kMax);
1501                fuzz->nextN(xDivs, lattice.fXCount);
1502                fuzz->nextN(yDivs, lattice.fYCount);
1503                canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1504                break;
1505            }
1506            case 44: {
1507                auto img = make_fuzz_image(fuzz);
1508                bool usePaint;
1509                SkRect dst;
1510                fuzz->next(&usePaint, &dst);
1511                if (usePaint) {
1512                    fuzz_paint(fuzz, &paint, depth - 1);
1513                }
1514                constexpr int kMax = 6;
1515                int xDivs[kMax], yDivs[kMax];
1516                SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1517                fuzz->nextRange(&lattice.fXCount, 2, kMax);
1518                fuzz->nextRange(&lattice.fYCount, 2, kMax);
1519                fuzz->nextN(xDivs, lattice.fXCount);
1520                fuzz->nextN(yDivs, lattice.fYCount);
1521                canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1522                break;
1523            }
1524            case 45: {
1525                fuzz_paint(fuzz, &paint, depth - 1);
1526                fuzz_paint_text(fuzz, &paint);
1527                fuzz_paint_text_encoding(fuzz, &paint);
1528                SkScalar x, y;
1529                fuzz->next(&x, &y);
1530                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1531                canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
1532                break;
1533            }
1534            case 46: {
1535                fuzz_paint(fuzz, &paint, depth - 1);
1536                fuzz_paint_text(fuzz, &paint);
1537                fuzz_paint_text_encoding(fuzz, &paint);
1538                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1539                int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1540                if (glyphCount < 1) {
1541                    break;
1542                }
1543                SkAutoTMalloc<SkPoint> pos(glyphCount);
1544                SkAutoTMalloc<SkScalar> widths(glyphCount);
1545                paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
1546                pos[0] = {0, 0};
1547                for (int i = 1; i < glyphCount; ++i) {
1548                    float y;
1549                    fuzz->nextRange(&y, -0.5f * paint.getTextSize(), 0.5f * paint.getTextSize());
1550                    pos[i] = {pos[i - 1].x() + widths[i - 1], y};
1551                }
1552                canvas->drawPosText(text.begin(), SkToSizeT(text.count()), pos.get(), paint);
1553                break;
1554            }
1555            case 47: {
1556                fuzz_paint(fuzz, &paint, depth - 1);
1557                fuzz_paint_text(fuzz, &paint);
1558                fuzz_paint_text_encoding(fuzz, &paint);
1559                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1560                int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1561                SkAutoTMalloc<SkScalar> widths(glyphCount);
1562                if (glyphCount < 1) {
1563                    break;
1564                }
1565                paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
1566                SkScalar x = widths[0];
1567                for (int i = 0; i < glyphCount; ++i) {
1568                    SkTSwap(x, widths[i]);
1569                    x += widths[i];
1570                    SkScalar offset;
1571                    fuzz->nextRange(&offset, -0.125f * paint.getTextSize(),
1572                                    0.125f * paint.getTextSize());
1573                    widths[i] += offset;
1574                }
1575                SkScalar y;
1576                fuzz->next(&y);
1577                canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
1578                break;
1579            }
1580            case 48: {
1581                fuzz_paint(fuzz, &paint, depth - 1);
1582                fuzz_paint_text(fuzz, &paint);
1583                fuzz_paint_text_encoding(fuzz, &paint);
1584                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1585                SkPath path;
1586                fuzz_path(fuzz, &path, 20);
1587                SkScalar hOffset, vOffset;
1588                fuzz->next(&hOffset, &vOffset);
1589                canvas->drawTextOnPathHV(text.begin(), SkToSizeT(text.count()), path, hOffset,
1590                                         vOffset, paint);
1591                break;
1592            }
1593            case 49: {
1594                SkMatrix matrix;
1595                bool useMatrix = make_fuzz_t<bool>(fuzz);
1596                if (useMatrix) {
1597                    fuzz->next(&matrix);
1598                }
1599                fuzz_paint(fuzz, &paint, depth - 1);
1600                fuzz_paint_text(fuzz, &paint);
1601                fuzz_paint_text_encoding(fuzz, &paint);
1602                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1603                SkPath path;
1604                fuzz_path(fuzz, &path, 20);
1605                canvas->drawTextOnPath(text.begin(), SkToSizeT(text.count()), path,
1606                                       useMatrix ? &matrix : nullptr, paint);
1607                break;
1608            }
1609            case 50: {
1610                fuzz_paint(fuzz, &paint, depth - 1);
1611                fuzz_paint_text(fuzz, &paint);
1612                fuzz_paint_text_encoding(fuzz, &paint);
1613                SkTDArray<uint8_t> text = make_fuzz_text(fuzz, paint);
1614                SkRSXform rSXform[kMaxGlyphCount];
1615                int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
1616                SkASSERT(glyphCount <= kMaxGlyphCount);
1617                fuzz->nextN(rSXform, glyphCount);
1618                SkRect cullRect;
1619                bool useCullRect;
1620                fuzz->next(&useCullRect);
1621                if (useCullRect) {
1622                    fuzz->next(&cullRect);
1623                }
1624                canvas->drawTextRSXform(text.begin(), SkToSizeT(text.count()), rSXform,
1625                                        useCullRect ? &cullRect : nullptr, paint);
1626                break;
1627            }
1628            case 51: {
1629                sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
1630                fuzz_paint(fuzz, &paint, depth - 1);
1631                SkScalar x, y;
1632                fuzz->next(&x, &y);
1633                canvas->drawTextBlob(blob, x, y, paint);
1634                break;
1635            }
1636            case 52: {
1637                bool usePaint, useMatrix;
1638                fuzz->next(&usePaint, &useMatrix);
1639                if (usePaint) {
1640                    fuzz_paint(fuzz, &paint, depth - 1);
1641                }
1642                if (useMatrix) {
1643                    fuzz->next(&matrix);
1644                }
1645                auto pic = make_fuzz_picture(fuzz, depth - 1);
1646                canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1647                                    usePaint ? &paint : nullptr);
1648                break;
1649            }
1650            case 53: {
1651                fuzz_paint(fuzz, &paint, depth - 1);
1652                SkVertices::VertexMode vertexMode;
1653                SkBlendMode blendMode;
1654                fuzz_enum_range(fuzz, &vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1655                fuzz->next(&blendMode);
1656                constexpr int kMaxCount = 100;
1657                int vertexCount;
1658                SkPoint vertices[kMaxCount];
1659                SkPoint texs[kMaxCount];
1660                SkColor colors[kMaxCount];
1661                fuzz->nextRange(&vertexCount, 3, kMaxCount);
1662                fuzz->nextN(vertices, vertexCount);
1663                bool useTexs, useColors;
1664                fuzz->next(&useTexs, &useColors);
1665                if (useTexs) {
1666                    fuzz->nextN(texs, vertexCount);
1667                }
1668                if (useColors) {
1669                    fuzz->nextN(colors, vertexCount);
1670                }
1671                int indexCount = 0;
1672                uint16_t indices[kMaxCount * 2];
1673                if (make_fuzz_t<bool>(fuzz)) {
1674                    fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1675                    for (int i = 0; i < indexCount; ++i) {
1676                        fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1677                    }
1678                }
1679                canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1680                                                          useTexs ? texs : nullptr,
1681                                                          useColors ? colors : nullptr,
1682                                                          indexCount, indices),
1683                                     blendMode, paint);
1684                break;
1685            }
1686            default:
1687                SkASSERT(false);
1688                break;
1689        }
1690    }
1691}
1692
1693static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1694    SkScalar w, h;
1695    fuzz->next(&w, &h);
1696    SkPictureRecorder pictureRecorder;
1697    fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1698    return pictureRecorder.finishRecordingAsPicture();
1699}
1700
1701DEF_FUZZ(NullCanvas, fuzz) {
1702    fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1703}
1704
1705// 8.5x11 letter paper at 72ppi.
1706constexpr SkISize kCanvasSize = {612, 792};
1707
1708DEF_FUZZ(RasterN32Canvas, fuzz) {
1709    auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1710    SkASSERT(surface && surface->getCanvas());
1711    fuzz_canvas(fuzz, surface->getCanvas());
1712}
1713
1714DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1715    SkPictureRecorder recorder;
1716    fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1717                                              SkIntToScalar(kCanvasSize.height())));
1718    sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1719    if (!pic) { fuzz->signalBug(); }
1720    sk_sp<SkData> data = pic->serialize();
1721    if (!data) { fuzz->signalBug(); }
1722    SkReadBuffer rb(data->data(), data->size());
1723    auto deserialized = SkPicture::MakeFromBuffer(rb);
1724    if (!deserialized) { fuzz->signalBug(); }
1725    auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1726    SkASSERT(surface && surface->getCanvas());
1727    surface->getCanvas()->drawPicture(deserialized);
1728}
1729
1730DEF_FUZZ(ImageFilter, fuzz) {
1731    auto fil = make_fuzz_imageFilter(fuzz, 20);
1732
1733    SkPaint paint;
1734    paint.setImageFilter(fil);
1735    SkBitmap bitmap;
1736    SkCanvas canvas(bitmap);
1737    canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1738}
1739
1740
1741//SkRandom _rand;
1742#define SK_ADD_RANDOM_BIT_FLIPS
1743
1744DEF_FUZZ(SerializedImageFilter, fuzz) {
1745    auto filter = make_fuzz_imageFilter(fuzz, 20);
1746    auto data = filter->serialize();
1747    const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1748    size_t len = data->size();
1749#ifdef SK_ADD_RANDOM_BIT_FLIPS
1750    unsigned char* p = const_cast<unsigned char*>(ptr);
1751    for (size_t i = 0; i < len; ++i, ++p) {
1752        uint8_t j;
1753        fuzz->nextRange(&j, 1, 250);
1754        if (j == 1) { // 0.4% of the time, flip a bit or byte
1755            uint8_t k;
1756            fuzz->nextRange(&k, 1, 10);
1757            if (k == 1) { // Then 10% of the time, change a whole byte
1758                uint8_t s;
1759                fuzz->nextRange(&s, 0, 2);
1760                switch(s) {
1761                case 0:
1762                    *p ^= 0xFF; // Flip entire byte
1763                    break;
1764                case 1:
1765                    *p = 0xFF; // Set all bits to 1
1766                    break;
1767                case 2:
1768                    *p = 0x00; // Set all bits to 0
1769                    break;
1770                }
1771            } else {
1772                uint8_t s;
1773                fuzz->nextRange(&s, 0, 7);
1774                *p ^= (1 << 7);
1775            }
1776        }
1777    }
1778#endif // SK_ADD_RANDOM_BIT_FLIPS
1779    auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1780
1781    // uncomment below to write out a serialized image filter (to make corpus
1782    // for -t filter_fuzz)
1783    // SkString s("./serialized_filters/sf");
1784    // s.appendU32(_rand.nextU());
1785    // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1786    // sk_fwrite(data->bytes(), data->size(), file);
1787    // sk_fclose(file);
1788
1789    SkPaint paint;
1790    paint.setImageFilter(deserializedFil);
1791    SkBitmap bitmap;
1792    SkCanvas canvas(bitmap);
1793    canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1794}
1795
1796#if SK_SUPPORT_GPU
1797static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
1798    SkASSERT(context);
1799    auto surface = SkSurface::MakeRenderTarget(
1800            context,
1801            SkBudgeted::kNo,
1802            SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1803    SkASSERT(surface && surface->getCanvas());
1804    fuzz_canvas(fuzz, surface->getCanvas());
1805}
1806
1807DEF_FUZZ(NativeGLCanvas, fuzz) {
1808    sk_gpu_test::GrContextFactory f;
1809    GrContext* context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
1810    if (!context) {
1811        context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
1812    }
1813    fuzz_ganesh(fuzz, context);
1814}
1815
1816DEF_FUZZ(NullGLCanvas, fuzz) {
1817    sk_gpu_test::GrContextFactory f;
1818    fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kNullGL_ContextType));
1819}
1820
1821DEF_FUZZ(DebugGLCanvas, fuzz) {
1822    sk_gpu_test::GrContextFactory f;
1823    fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kDebugGL_ContextType));
1824}
1825#endif
1826
1827DEF_FUZZ(PDFCanvas, fuzz) {
1828    SkNullWStream stream;
1829    auto doc = SkDocument::MakePDF(&stream);
1830    fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1831                                     SkIntToScalar(kCanvasSize.height())));
1832}
1833
1834// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1835DEF_FUZZ(_DumpCanvas, fuzz) {
1836    SkDebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
1837    fuzz_canvas(fuzz, &debugCanvas);
1838    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1839    UrlDataManager dataManager(SkString("data"));
1840    Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
1841    Json::StyledStreamWriter("  ").write(std::cout, json);
1842}
1843