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