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 "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 
     79 template <typename T, typename Min, typename Max>
     80 inline 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!
     88 template <typename T>
     89 inline T make_fuzz_t(Fuzz* fuzz) {
     90     T t;
     91     fuzz->next(&t);
     92     return t;
     93 }
     94 
     95 template <>
     96 inline void Fuzz::next(SkShader::TileMode* m) {
     97     fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1);
     98 }
     99 
    100 template <>
    101 inline void Fuzz::next(SkFilterQuality* q) {
    102     fuzz_enum_range(this, q, SkFilterQuality::kNone_SkFilterQuality,
    103                     SkFilterQuality::kLast_SkFilterQuality);
    104 }
    105 
    106 template <>
    107 inline 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 
    143 template <>
    144 inline 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 
    158 template <>
    159 inline void Fuzz::next(SkBlendMode* mode) {
    160     fuzz_enum_range(this, mode, 0, SkBlendMode::kLastMode);
    161 }
    162 
    163 static sk_sp<SkImage> make_fuzz_image(Fuzz*);
    164 
    165 static SkBitmap make_fuzz_bitmap(Fuzz*);
    166 
    167 static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
    168 
    169 static 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 
    238 static 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 
    252 static 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 
    428 static 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 
    496 static 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 
    527 static 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 
    542 template <>
    543 inline 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 
    551 static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
    552 
    553 static 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 
    613 static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
    614 
    615 static 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 
    882 static 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 
    899 static 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 
    918 template <typename T, typename Min, typename Max>
    919 inline 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 
    925 static 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 
    950 static 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 
    968 static void fuzz_paint_text_encoding(Fuzz* fuzz, SkPaint* paint) {
    969     paint->setTextEncoding(make_fuzz_t_range<SkPaint::TextEncoding>(fuzz, 0, 3));
    970 }
    971 
    972 constexpr int kMaxGlyphCount = 30;
    973 
    974 static 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 
   1048 static 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 
   1092 static 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 
   1693 static 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 
   1701 DEF_FUZZ(NullCanvas, fuzz) {
   1702     fuzz_canvas(fuzz, SkMakeNullCanvas().get());
   1703 }
   1704 
   1705 // 8.5x11 letter paper at 72ppi.
   1706 constexpr SkISize kCanvasSize = {612, 792};
   1707 
   1708 DEF_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 
   1714 DEF_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 
   1730 DEF_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 
   1744 DEF_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
   1797 static 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 
   1807 DEF_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 
   1816 DEF_FUZZ(NullGLCanvas, fuzz) {
   1817     sk_gpu_test::GrContextFactory f;
   1818     fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kNullGL_ContextType));
   1819 }
   1820 
   1821 DEF_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 
   1827 DEF_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.
   1835 DEF_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