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