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