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