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