• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
fuzz_enum_range(Fuzz * fuzz,T * value,Min rmin,Max rmax)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>
make_fuzz_t(Fuzz * fuzz)89 inline T make_fuzz_t(Fuzz* fuzz) {
90     T t;
91     fuzz->next(&t);
92     return t;
93 }
94 
95 template <>
next(SkShader::TileMode * m)96 inline void Fuzz::next(SkShader::TileMode* m) {
97     fuzz_enum_range(this, m, 0, SkShader::kTileModeCount - 1);
98 }
99 
100 template <>
next(SkFilterQuality * q)101 inline void Fuzz::next(SkFilterQuality* q) {
102     fuzz_enum_range(this, q, SkFilterQuality::kNone_SkFilterQuality,
103                     SkFilterQuality::kLast_SkFilterQuality);
104 }
105 
106 template <>
next(SkMatrix * m)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 <>
next(SkRRect * rr)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 <>
next(SkBlendMode * mode)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 
make_fuzz_colorfilter(Fuzz * fuzz,int depth)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 
fuzz_gradient_stops(Fuzz * fuzz,SkScalar * pos,int colorCount)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 
make_fuzz_shader(Fuzz * fuzz,int depth)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 
make_fuzz_patheffect(Fuzz * fuzz,int depth)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 
make_fuzz_maskfilter(Fuzz * fuzz)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 
make_fuzz_typeface(Fuzz * fuzz)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 <>
next(SkImageFilter::CropRect * cropRect)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 
make_fuzz_lighting_imagefilter(Fuzz * fuzz,int depth)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 
make_fuzz_imageFilter(Fuzz * fuzz,int depth)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 
make_fuzz_image(Fuzz * fuzz)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 
make_fuzz_bitmap(Fuzz * fuzz)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>
make_fuzz_t_range(Fuzz * fuzz,Min minv,Max maxv)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 
fuzz_paint(Fuzz * fuzz,SkPaint * paint,int depth)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 
fuzz_paint_text(Fuzz * fuzz,SkPaint * paint)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 
fuzz_paint_text_encoding(Fuzz * fuzz,SkPaint * paint)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 
make_fuzz_text(Fuzz * fuzz,const SkPaint & paint)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 
make_fuzz_textblob(Fuzz * fuzz)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 
fuzz_canvas(Fuzz * fuzz,SkCanvas * canvas,int depth=9)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 
make_fuzz_picture(Fuzz * fuzz,int depth)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 
DEF_FUZZ(NullCanvas,fuzz)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 
DEF_FUZZ(RasterN32Canvas,fuzz)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 
DEF_FUZZ(RasterN32CanvasViaSerialization,fuzz)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 
DEF_FUZZ(ImageFilter,fuzz)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 
DEF_FUZZ(SerializedImageFilter,fuzz)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
fuzz_ganesh(Fuzz * fuzz,GrContext * context)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 
DEF_FUZZ(NativeGLCanvas,fuzz)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 
DEF_FUZZ(NullGLCanvas,fuzz)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 
DEF_FUZZ(DebugGLCanvas,fuzz)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 
DEF_FUZZ(PDFCanvas,fuzz)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.
DEF_FUZZ(_DumpCanvas,fuzz)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