Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / fuzz / FuzzCanvas.cpp
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/Fuzz.h"
9 #include "fuzz/FuzzCommon.h"
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColorFilter.h"
13 #include "include/core/SkFontMgr.h"
14 #include "include/core/SkImageFilter.h"
15 #include "include/core/SkMaskFilter.h"
16 #include "include/core/SkPathEffect.h"
17 #include "include/core/SkPictureRecorder.h"
18 #include "include/core/SkPoint3.h"
19 #include "include/core/SkRSXform.h"
20 #include "include/core/SkRegion.h"
21 #include "include/core/SkSurface.h"
22 #include "include/core/SkTextBlob.h"
23 #include "include/core/SkTypeface.h"
24 #include "include/core/SkVertices.h"
25 #include "include/docs/SkPDFDocument.h"
26 #include "include/effects/Sk1DPathEffect.h"
27 #include "include/effects/Sk2DPathEffect.h"
28 #include "include/effects/SkColorMatrixFilter.h"
29 #include "include/effects/SkCornerPathEffect.h"
30 #include "include/effects/SkDashPathEffect.h"
31 #include "include/effects/SkDiscretePathEffect.h"
32 #include "include/effects/SkGradientShader.h"
33 #include "include/effects/SkHighContrastFilter.h"
34 #include "include/effects/SkImageFilters.h"
35 #include "include/effects/SkLumaColorFilter.h"
36 #include "include/effects/SkPerlinNoiseShader.h"
37 #include "include/effects/SkTableColorFilter.h"
38 #include "include/private/SkTo.h"
39 #include "include/svg/SkSVGCanvas.h"
40 #include "include/utils/SkNullCanvas.h"
41 #include "src/core/SkOSFile.h"
42 #include "src/core/SkPaintPriv.h"
43 #include "src/core/SkPicturePriv.h"
44 #include "src/core/SkReadBuffer.h"
45 #include "src/utils/SkJSONWriter.h"
46 #include "src/utils/SkUTF.h"
47 #include "tools/UrlDataManager.h"
48 #include "tools/debugger/DebugCanvas.h"
49 #include "tools/flags/CommandLineFlags.h"
50
51 #if SK_SUPPORT_GPU
52 #include "include/gpu/GrDirectContext.h"
53 #include "src/gpu/ganesh/GrDirectContextPriv.h"
54 #include "tools/gpu/GrContextFactory.h"
55 #endif
56
57 #ifdef SK_GL
58 #include "include/gpu/gl/GrGLFunctions.h"
59 #include "src/gpu/ganesh/gl/GrGLGpu.h"
60 #include "src/gpu/ganesh/gl/GrGLUtil.h"
61 #endif
62
63 #include <iostream>
64 #include <utility>
65
66 static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
67
68 // TODO:
69 //   SkTextBlob with Unicode
70 //   SkImage: more types
71
72 // be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
73 // In fact, all make_fuzz_foo() functions have this potential problem.
74 // Use sequence points!
75 template <typename T>
76 inline T make_fuzz_t(Fuzz* fuzz) {
77     T t;
78     fuzz->next(&t);
79     return t;
80 }
81
82 static sk_sp<SkImage> make_fuzz_image(Fuzz*);
83
84 static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
85
86 static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
87     if (depth <= 0) {
88         return nullptr;
89     }
90     int colorFilterType;
91     fuzz->nextRange(&colorFilterType, 0, 8);
92     switch (colorFilterType) {
93         case 0:
94             return nullptr;
95         case 1: {
96             SkColor color;
97             SkBlendMode mode;
98             fuzz->next(&color);
99             fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
100             return SkColorFilters::Blend(color, mode);
101         }
102         case 2: {
103             sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
104             if (!outer) {
105                 return nullptr;
106             }
107             sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
108             // makeComposed should be able to handle nullptr.
109             return outer->makeComposed(std::move(inner));
110         }
111         case 3: {
112             float array[20];
113             fuzz->nextN(array, SK_ARRAY_COUNT(array));
114             return SkColorFilters::Matrix(array);
115         }
116         case 4: {
117             SkColor mul, add;
118             fuzz->next(&mul, &add);
119             return SkColorMatrixFilter::MakeLightingFilter(mul, add);
120         }
121         case 5: {
122             bool grayscale;
123             int invertStyle;
124             float contrast;
125             fuzz->next(&grayscale);
126             fuzz->nextRange(&invertStyle, 0, 2);
127             fuzz->nextRange(&contrast, -1.0f, 1.0f);
128             return SkHighContrastFilter::Make(SkHighContrastConfig(
129                     grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
130         }
131         case 6:
132             return SkLumaColorFilter::Make();
133         case 7: {
134             uint8_t table[256];
135             fuzz->nextN(table, SK_ARRAY_COUNT(table));
136             return SkTableColorFilter::Make(table);
137         }
138         case 8: {
139             uint8_t tableA[256];
140             uint8_t tableR[256];
141             uint8_t tableG[256];
142             uint8_t tableB[256];
143             fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
144             fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
145             fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
146             fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
147             return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
148         }
149         default:
150             SkASSERT(false);
151             break;
152     }
153     return nullptr;
154 }
155
156 static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
157     SkScalar totalPos = 0;
158     for (int i = 0; i < colorCount; ++i) {
159         fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
160         totalPos += pos[i];
161     }
162     totalPos = 1.0f / totalPos;
163     for (int i = 0; i < colorCount; ++i) {
164         pos[i] *= totalPos;
165     }
166     // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
167     pos[colorCount - 1] = 1.0f;
168 }
169
170 static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
171     sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
172     sk_sp<SkColorFilter> colorFilter(nullptr);
173     SkBitmap bitmap;
174     sk_sp<SkImage> img;
175     SkTileMode tmX, tmY;
176     bool useMatrix;
177     SkColor color;
178     SkMatrix matrix;
179     SkBlendMode blendMode;
180     int shaderType;
181     if (depth <= 0) {
182         return nullptr;
183     }
184     fuzz->nextRange(&shaderType, 0, 14);
185     switch (shaderType) {
186         case 0:
187             return nullptr;
188         case 1:
189             return SkShaders::Empty();
190         case 2:
191             fuzz->next(&color);
192             return SkShaders::Color(color);
193         case 3:
194             img = make_fuzz_image(fuzz);
195             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
196             fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
197             fuzz->next(&useMatrix);
198             if (useMatrix) {
199                 FuzzNiceMatrix(fuzz, &matrix);
200             }
201             return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
202         case 5:
203             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
204             FuzzNiceMatrix(fuzz, &matrix);
205             return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
206         case 6:
207             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
208             colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
209             return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
210         case 7:
211             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
212             shader2 = make_fuzz_shader(fuzz, depth - 1);
213             fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
214             return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
215         case 8: {
216             auto pic = make_fuzz_picture(fuzz, depth - 1);
217             bool useTile;
218             SkRect tile;
219             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
220             fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
221             fuzz->next(&useMatrix, &useTile);
222             if (useMatrix) {
223                 FuzzNiceMatrix(fuzz, &matrix);
224             }
225             if (useTile) {
226                 fuzz->next(&tile);
227             }
228             return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
229                                    useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
230         }
231         // EFFECTS:
232         case 9:
233             // Deprecated SkGaussianEdgeShader
234             return nullptr;
235         case 10: {
236             constexpr int kMaxColors = 12;
237             SkPoint pts[2];
238             SkColor colors[kMaxColors];
239             SkScalar pos[kMaxColors];
240             int colorCount;
241             bool usePos;
242             fuzz->nextN(pts, 2);
243             fuzz->nextRange(&colorCount, 2, kMaxColors);
244             fuzz->nextN(colors, colorCount);
245             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
246             fuzz->next(&useMatrix, &usePos);
247             if (useMatrix) {
248                 FuzzNiceMatrix(fuzz, &matrix);
249             }
250             if (usePos) {
251                 fuzz_gradient_stops(fuzz, pos, colorCount);
252             }
253             return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
254                                                 tmX, 0, useMatrix ? &matrix : nullptr);
255         }
256         case 11: {
257             constexpr int kMaxColors = 12;
258             SkPoint center;
259             SkScalar radius;
260             int colorCount;
261             bool usePos;
262             SkColor colors[kMaxColors];
263             SkScalar pos[kMaxColors];
264             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
265             fuzz->next(&useMatrix, &usePos, &center, &radius);
266             fuzz->nextRange(&colorCount, 2, kMaxColors);
267             fuzz->nextN(colors, colorCount);
268             if (useMatrix) {
269                 FuzzNiceMatrix(fuzz, &matrix);
270             }
271             if (usePos) {
272                 fuzz_gradient_stops(fuzz, pos, colorCount);
273             }
274             return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
275                                                 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
276         }
277         case 12: {
278             constexpr int kMaxColors = 12;
279             SkPoint start, end;
280             SkScalar startRadius, endRadius;
281             int colorCount;
282             bool usePos;
283             SkColor colors[kMaxColors];
284             SkScalar pos[kMaxColors];
285             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
286             fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
287             fuzz->nextRange(&colorCount, 2, kMaxColors);
288             fuzz->nextN(colors, colorCount);
289             if (useMatrix) {
290                 FuzzNiceMatrix(fuzz, &matrix);
291             }
292             if (usePos) {
293                 fuzz_gradient_stops(fuzz, pos, colorCount);
294             }
295             return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
296                                                          usePos ? pos : nullptr, colorCount, tmX, 0,
297                                                          useMatrix ? &matrix : nullptr);
298         }
299         case 13: {
300             constexpr int kMaxColors = 12;
301             SkScalar cx, cy;
302             int colorCount;
303             bool usePos;
304             SkColor colors[kMaxColors];
305             SkScalar pos[kMaxColors];
306             fuzz->next(&cx, &cy, &useMatrix, &usePos);
307             fuzz->nextRange(&colorCount, 2, kMaxColors);
308             fuzz->nextN(colors, colorCount);
309             if (useMatrix) {
310                 FuzzNiceMatrix(fuzz, &matrix);
311             }
312             if (usePos) {
313                 fuzz_gradient_stops(fuzz, pos, colorCount);
314             }
315             return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
316                                                0, useMatrix ? &matrix : nullptr);
317         }
318         case 14: {
319             SkScalar baseFrequencyX, baseFrequencyY, seed;
320             int numOctaves;
321             SkISize tileSize;
322             bool useTileSize, turbulence;
323             fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
324             if (useTileSize) {
325                 fuzz->next(&tileSize);
326             }
327             fuzz->nextRange(&numOctaves, 2, 7);
328             if (turbulence) {
329                 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
330                                                            numOctaves, seed,
331                                                            useTileSize ? &tileSize : nullptr);
332             } else {
333                 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
334                                                              numOctaves, seed,
335                                                              useTileSize ? &tileSize : nullptr);
336             }
337         }
338         default:
339             SkASSERT(false);
340             break;
341     }
342     return nullptr;
343 }
344
345 static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
346     if (depth <= 0) {
347         return nullptr;
348     }
349     uint8_t pathEffectType;
350     fuzz->nextRange(&pathEffectType, 0, 8);
351     switch (pathEffectType) {
352         case 0: {
353             return nullptr;
354         }
355         case 1: {
356             sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
357             sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
358             return SkPathEffect::MakeSum(std::move(first), std::move(second));
359         }
360         case 2: {
361             sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
362             sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
363             return SkPathEffect::MakeCompose(std::move(first), std::move(second));
364         }
365         case 3: {
366             SkPath path;
367             FuzzNicePath(fuzz, &path, 20);
368             SkScalar advance, phase;
369             fuzz->next(&advance, &phase);
370             SkPath1DPathEffect::Style style;
371             fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
372             return SkPath1DPathEffect::Make(path, advance, phase, style);
373         }
374         case 4: {
375             SkScalar width;
376             SkMatrix matrix;
377             fuzz->next(&width);
378             FuzzNiceMatrix(fuzz, &matrix);
379             return SkLine2DPathEffect::Make(width, matrix);
380         }
381         case 5: {
382             SkPath path;
383             FuzzNicePath(fuzz, &path, 20);
384             SkMatrix matrix;
385             FuzzNiceMatrix(fuzz, &matrix);
386             return SkPath2DPathEffect::Make(matrix, path);
387         }
388         case 6: {
389             SkScalar radius;
390             fuzz->next(&radius);
391             return SkCornerPathEffect::Make(radius);
392         }
393         case 7: {
394             SkScalar phase;
395             fuzz->next(&phase);
396             SkScalar intervals[20];
397             int count;
398             fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
399             fuzz->nextN(intervals, count);
400             return SkDashPathEffect::Make(intervals, count, phase);
401         }
402         case 8: {
403             SkScalar segLength, dev;
404             uint32_t seed;
405             fuzz->next(&segLength, &dev, &seed);
406             return SkDiscretePathEffect::Make(segLength, dev, seed);
407         }
408         default:
409             SkASSERT(false);
410             return nullptr;
411     }
412 }
413
414 static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
415     int maskfilterType;
416     fuzz->nextRange(&maskfilterType, 0, 1);
417     switch (maskfilterType) {
418         case 0:
419             return nullptr;
420         case 1: {
421             SkBlurStyle blurStyle;
422             fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
423             SkScalar sigma;
424             fuzz->next(&sigma);
425             bool respectCTM;
426             fuzz->next(&respectCTM);
427             return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
428         }
429         default:
430             SkASSERT(false);
431             return nullptr;
432     }
433 }
434
435 static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
436     if (make_fuzz_t<bool>(fuzz)) {
437         return nullptr;
438     }
439     auto fontMugger = SkFontMgr::RefDefault();
440     SkASSERT(fontMugger);
441     int familyCount = fontMugger->countFamilies();
442     int i, j;
443     fuzz->nextRange(&i, 0, familyCount - 1);
444     sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
445     int styleCount = family->count();
446     fuzz->nextRange(&j, 0, styleCount - 1);
447     return sk_sp<SkTypeface>(family->createTypeface(j));
448 }
449
450 static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
451
452 static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
453     if (depth <= 0) {
454         return nullptr;
455     }
456     uint8_t imageFilterType;
457     fuzz->nextRange(&imageFilterType, 1, 6);
458     SkPoint3 p, q;
459     SkColor lightColor;
460     SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
461     sk_sp<SkImageFilter> input;
462     SkIRect cropRect;
463     bool useCropRect;
464     fuzz->next(&useCropRect);
465     if (useCropRect) {
466         fuzz->next(&cropRect);
467     }
468     switch (imageFilterType) {
469         case 1:
470             fuzz->next(&p, &lightColor, &surfaceScale, &k);
471             input = make_fuzz_imageFilter(fuzz, depth - 1);
472             return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
473                                                      std::move(input),
474                                                      useCropRect ? &cropRect : nullptr);
475         case 2:
476             fuzz->next(&p, &lightColor, &surfaceScale, &k);
477             input = make_fuzz_imageFilter(fuzz, depth - 1);
478             return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
479                                                    std::move(input),
480                                                    useCropRect ? &cropRect : nullptr);
481         case 3:
482             fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
483             input = make_fuzz_imageFilter(fuzz, depth - 1);
484             return SkImageFilters::SpotLitDiffuse(
485                     p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
486                     std::move(input), useCropRect ? &cropRect : nullptr);
487         case 4:
488             fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
489             input = make_fuzz_imageFilter(fuzz, depth - 1);
490             return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
491                                                       shininess, std::move(input),
492                                                       useCropRect ? &cropRect : nullptr);
493         case 5:
494             fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
495             input = make_fuzz_imageFilter(fuzz, depth - 1);
496             return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
497                                                     shininess, std::move(input),
498                                                     useCropRect ? &cropRect : nullptr);
499         case 6:
500             fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
501                        &shininess);
502             input = make_fuzz_imageFilter(fuzz, depth - 1);
503             return SkImageFilters::SpotLitSpecular(
504                     p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
505                     std::move(input), useCropRect ? &cropRect : nullptr);
506         default:
507             SkASSERT(false);
508             return nullptr;
509     }
510 }
511
512 static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
513
514 static SkSamplingOptions next_sampling(Fuzz* fuzz) {
515     if (fuzz->nextBool()) {
516         float B, C;
517         fuzz->next(&B, &C);
518         return SkSamplingOptions({B, C});
519     } else {
520         SkFilterMode fm;
521         SkMipmapMode mm;
522         fuzz->nextEnum(&fm, SkFilterMode::kLast);
523         fuzz->nextEnum(&mm, SkMipmapMode::kLast);
524         return SkSamplingOptions(fm, mm);
525     }
526 }
527
528 static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
529     if (depth <= 0) {
530         return nullptr;
531     }
532     uint8_t imageFilterType;
533     fuzz->nextRange(&imageFilterType, 0, 24);
534     switch (imageFilterType) {
535         case 0:
536             return nullptr;
537         case 1: {
538             SkScalar sigmaX, sigmaY;
539             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
540             bool useCropRect;
541             fuzz->next(&sigmaX, &sigmaY, &useCropRect);
542             SkIRect cropRect;
543             if (useCropRect) {
544                 fuzz->next(&cropRect);
545             }
546             return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
547                                         useCropRect ? &cropRect : nullptr);
548         }
549         case 2: {
550             SkMatrix matrix;
551             FuzzNiceMatrix(fuzz, &matrix);
552             const auto sampling = next_sampling(fuzz);
553             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
554             return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
555         }
556         case 3: {
557             SkRegion region;
558             SkScalar innerMin, outerMax;
559             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
560             bool useCropRect;
561             fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
562             SkIRect cropRect;
563             if (useCropRect) {
564                 fuzz->next(&cropRect);
565             }
566             return SkImageFilters::AlphaThreshold(region, innerMin, outerMax, std::move(input),
567                                                   useCropRect ? &cropRect : nullptr);
568         }
569         case 4: {
570             float k1, k2, k3, k4;
571             bool enforcePMColor;
572             bool useCropRect;
573             fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
574             sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
575             sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
576             SkIRect cropRect;
577             if (useCropRect) {
578                 fuzz->next(&cropRect);
579             }
580             return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
581                                               std::move(background), std::move(foreground),
582                                               useCropRect ? &cropRect : nullptr);
583         }
584         case 5: {
585             sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
586             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
587             bool useCropRect;
588             SkIRect cropRect;
589             fuzz->next(&useCropRect);
590             if (useCropRect) {
591                 fuzz->next(&cropRect);
592             }
593             return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
594                                                useCropRect ? &cropRect : nullptr);
595         }
596         case 6: {
597             sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
598             sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
599             return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
600         }
601         case 7: {
602             SkColorChannel xChannelSelector, yChannelSelector;
603             fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
604             fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
605             SkScalar scale;
606             bool useCropRect;
607             fuzz->next(&scale, &useCropRect);
608             SkIRect cropRect;
609             if (useCropRect) {
610                 fuzz->next(&cropRect);
611             }
612             sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
613             sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
614             return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
615                                                    std::move(displacement), std::move(color),
616                                                    useCropRect ? &cropRect : nullptr);
617         }
618         case 8: {
619             SkScalar dx, dy, sigmaX, sigmaY;
620             SkColor color;
621             bool shadowOnly, useCropRect;
622             fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
623             SkIRect cropRect;
624             if (useCropRect) {
625                 fuzz->next(&cropRect);
626             }
627             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
628             if (shadowOnly) {
629                 return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
630                                                       std::move(input),
631                                                       useCropRect ? &cropRect : nullptr);
632             } else {
633                 return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
634                                                   useCropRect ? &cropRect : nullptr);
635             }
636         }
637         case 9:
638             return SkImageFilters::Image(make_fuzz_image(fuzz));
639         case 10: {
640             sk_sp<SkImage> image = make_fuzz_image(fuzz);
641             SkRect srcRect, dstRect;
642             fuzz->next(&srcRect, &dstRect);
643             return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
644         }
645         case 11:
646             return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
647         case 12: {
648             SkRect srcRect;
649             SkScalar inset;
650             bool useCropRect;
651             SkIRect cropRect;
652             fuzz->next(&srcRect, &inset, &useCropRect);
653             if (useCropRect) {
654                 fuzz->next(&cropRect);
655             }
656             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
657             return SkImageFilters::Magnifier(srcRect, inset, std::move(input),
658                                              useCropRect ? &cropRect : nullptr);
659         }
660         case 13: {
661             constexpr int kMaxKernelSize = 5;
662             int32_t n, m;
663             fuzz->nextRange(&n, 1, kMaxKernelSize);
664             fuzz->nextRange(&m, 1, kMaxKernelSize);
665             SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
666             fuzz->nextN(kernel, n * m);
667             int32_t offsetX, offsetY;
668             fuzz->nextRange(&offsetX, 0, n - 1);
669             fuzz->nextRange(&offsetY, 0, m - 1);
670             SkScalar gain, bias;
671             bool convolveAlpha, useCropRect;
672             fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
673             SkTileMode tileMode;
674             fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
675             SkIRect cropRect;
676             if (useCropRect) {
677                 fuzz->next(&cropRect);
678             }
679             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
680             return SkImageFilters::MatrixConvolution(
681                     SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
682                     convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
683         }
684         case 14: {
685             sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
686             sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
687             bool useCropRect;
688             fuzz->next(&useCropRect);
689             SkIRect cropRect;
690             if (useCropRect) {
691                 fuzz->next(&cropRect);
692             }
693             return SkImageFilters::Merge(std::move(first), std::move(second),
694                                          useCropRect ? &cropRect : nullptr);
695         }
696         case 15: {
697             constexpr int kMaxCount = 4;
698             sk_sp<SkImageFilter> ifs[kMaxCount];
699             int count;
700             fuzz->nextRange(&count, 1, kMaxCount);
701             for (int i = 0; i < count; ++i) {
702                 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
703             }
704             bool useCropRect;
705             fuzz->next(&useCropRect);
706             SkIRect cropRect;
707             if (useCropRect) {
708                 fuzz->next(&cropRect);
709             }
710             return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
711         }
712         case 16: {
713             int rx, ry;
714             fuzz->next(&rx, &ry);
715             bool useCropRect;
716             fuzz->next(&useCropRect);
717             SkIRect cropRect;
718             if (useCropRect) {
719                 fuzz->next(&cropRect);
720             }
721             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
722             return SkImageFilters::Dilate(rx, ry, std::move(input),
723                                           useCropRect ? &cropRect : nullptr);
724         }
725         case 17: {
726             int rx, ry;
727             fuzz->next(&rx, &ry);
728             bool useCropRect;
729             fuzz->next(&useCropRect);
730             SkIRect cropRect;
731             if (useCropRect) {
732                 fuzz->next(&cropRect);
733             }
734             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
735             return SkImageFilters::Erode(rx, ry, std::move(input),
736                                          useCropRect ? &cropRect : nullptr);
737         }
738         case 18: {
739             SkScalar dx, dy;
740             fuzz->next(&dx, &dy);
741             bool useCropRect;
742             fuzz->next(&useCropRect);
743             SkIRect cropRect;
744             if (useCropRect) {
745                 fuzz->next(&cropRect);
746             }
747             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
748             return SkImageFilters::Offset(dx, dy, std::move(input),
749                                           useCropRect ? &cropRect : nullptr);
750         }
751         case 19: {
752             SkPaint paint;
753             fuzz_paint(fuzz, &paint, depth - 1);
754             bool useCropRect;
755             fuzz->next(&useCropRect);
756             SkIRect cropRect;
757             if (useCropRect) {
758                 fuzz->next(&cropRect);
759             }
760             return SkImageFilters::Paint(paint, useCropRect ? &cropRect : nullptr);
761         }
762         case 20: {
763             sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
764             return SkImageFilters::Picture(std::move(picture));
765         }
766         case 21: {
767             SkRect cropRect;
768             fuzz->next(&cropRect);
769             sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
770             return SkImageFilters::Picture(std::move(picture), cropRect);
771         }
772         case 22: {
773             SkRect src, dst;
774             fuzz->next(&src, &dst);
775             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
776             return SkImageFilters::Tile(src, dst, std::move(input));
777         }
778         case 23: {
779             SkBlendMode blendMode;
780             bool useCropRect;
781             fuzz->next(&useCropRect);
782             fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
783             SkIRect cropRect;
784             if (useCropRect) {
785                 fuzz->next(&cropRect);
786             }
787             sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
788             sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
789             return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
790                                          useCropRect ? &cropRect : nullptr);
791         }
792         case 24: {
793             sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
794             bool useCropRect;
795             fuzz->next(&useCropRect);
796             SkIRect cropRect;
797             if (useCropRect) {
798                 fuzz->next(&cropRect);
799             }
800             return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
801         }
802         default:
803             SkASSERT(false);
804             return nullptr;
805     }
806 }
807
808 static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
809     int w, h;
810     fuzz->nextRange(&w, 1, 1024);
811     fuzz->nextRange(&h, 1, 1024);
812     SkAutoTMalloc<SkPMColor> data(w * h);
813     SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
814     int n = w * h;
815     for (int i = 0; i < n; ++i) {
816         SkColor c;
817         fuzz->next(&c);
818         data[i] = SkPreMultiplyColor(c);
819     }
820     (void)data.release();
821     return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
822                                    nullptr);
823 }
824
825 template <typename T>
826 static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
827     T value;
828     fuzz->nextEnum(&value, maxv);
829     return value;
830 }
831
832 static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
833     if (!fuzz || !paint || depth <= 0) {
834         return;
835     }
836
837     paint->setAntiAlias(    make_fuzz_t<bool>(fuzz));
838     paint->setDither(       make_fuzz_t<bool>(fuzz));
839     paint->setColor(        make_fuzz_t<SkColor>(fuzz));
840     paint->setBlendMode(    make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
841     paint->setStyle(        make_fuzz_enum_range<SkPaint::Style>(fuzz,
842                                                  SkPaint::Style::kStrokeAndFill_Style));
843     paint->setShader(       make_fuzz_shader(fuzz, depth - 1));
844     paint->setPathEffect(   make_fuzz_patheffect(fuzz, depth - 1));
845     paint->setMaskFilter(   make_fuzz_maskfilter(fuzz));
846     paint->setImageFilter(  make_fuzz_imageFilter(fuzz, depth - 1));
847     paint->setColorFilter(  make_fuzz_colorfilter(fuzz, depth - 1));
848
849     if (paint->getStyle() != SkPaint::kFill_Style) {
850         paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
851         paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
852         paint->setStrokeCap(  make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
853         paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
854     }
855 }
856
857 static SkFont fuzz_font(Fuzz* fuzz) {
858     SkFont font;
859     font.setTypeface(           make_fuzz_typeface(fuzz));
860     font.setSize(               make_fuzz_t<SkScalar>(fuzz));
861     font.setScaleX(             make_fuzz_t<SkScalar>(fuzz));
862     font.setSkewX(              make_fuzz_t<SkScalar>(fuzz));
863     font.setLinearMetrics(      make_fuzz_t<bool>(fuzz));
864     font.setSubpixel(           make_fuzz_t<bool>(fuzz));
865     font.setEmbeddedBitmaps(    make_fuzz_t<bool>(fuzz));
866     font.setForceAutoHinting(   make_fuzz_t<bool>(fuzz));
867     font.setEmbolden(           make_fuzz_t<bool>(fuzz));
868     font.setHinting(            make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
869     font.setEdging(             make_fuzz_enum_range<SkFont::Edging>(fuzz,
870                                                      SkFont::Edging::kSubpixelAntiAlias));
871     return font;
872 }
873
874 static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
875     return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
876 }
877
878 constexpr int kMaxGlyphCount = 30;
879
880 static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
881     SkTDArray<uint8_t> array;
882     if (SkTextEncoding::kGlyphID == encoding) {
883         int glyphRange = font.getTypefaceOrDefault()->countGlyphs();
884         if (glyphRange == 0) {
885             // Some fuzzing environments have no fonts, so empty array is the best
886             // we can do.
887             return array;
888         }
889         int glyphCount;
890         fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
891         SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
892         for (int i = 0; i < glyphCount; ++i) {
893             fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
894         }
895         return array;
896     }
897     static const SkUnichar ranges[][2] = {
898         {0x0020, 0x007F},
899         {0x00A1, 0x0250},
900         {0x0400, 0x0500},
901     };
902     int32_t count = 0;
903     for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
904         count += (ranges[i][1] - ranges[i][0]);
905     }
906     constexpr int kMaxLength = kMaxGlyphCount;
907     SkUnichar buffer[kMaxLength];
908     int length;
909     fuzz->nextRange(&length, 1, kMaxLength);
910     for (int j = 0; j < length; ++j) {
911         int32_t value;
912         fuzz->nextRange(&value, 0, count - 1);
913         for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
914             if (value + ranges[i][0] < ranges[i][1]) {
915                 buffer[j] = value + ranges[i][0];
916                 break;
917             } else {
918                 value -= (ranges[i][1] - ranges[i][0]);
919             }
920         }
921     }
922     switch (encoding) {
923         case SkTextEncoding::kUTF8: {
924             size_t utf8len = 0;
925             for (int j = 0; j < length; ++j) {
926                 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
927             }
928             char* ptr = (char*)array.append(utf8len);
929             for (int j = 0; j < length; ++j) {
930                 ptr += SkUTF::ToUTF8(buffer[j], ptr);
931             }
932         } break;
933         case SkTextEncoding::kUTF16: {
934             size_t utf16len = 0;
935             for (int j = 0; j < length; ++j) {
936                 utf16len += SkUTF::ToUTF16(buffer[j]);
937             }
938             uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
939             for (int j = 0; j < length; ++j) {
940                 ptr += SkUTF::ToUTF16(buffer[j], ptr);
941             }
942         } break;
943         case SkTextEncoding::kUTF32:
944             memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
945             break;
946         default:
947             SkASSERT(false);
948             break;
949     }
950     return array;
951 }
952
953 static std::string make_fuzz_string(Fuzz* fuzz) {
954     int len;
955     fuzz->nextRange(&len, 0, kMaxGlyphCount);
956     std::string str(len, 0);
957     for (int i = 0; i < len; i++) {
958         fuzz->next(&str[i]);
959     }
960     return str;
961 }
962
963 static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
964     SkTextBlobBuilder textBlobBuilder;
965     int8_t runCount;
966     fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
967     while (runCount-- > 0) {
968         SkFont font;
969         SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
970         font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
971         SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
972         int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
973         SkASSERT(glyphCount <= kMaxGlyphCount);
974         SkScalar x, y;
975         const SkTextBlobBuilder::RunBuffer* buffer;
976         uint8_t runType;
977         fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
978         const void* textPtr = text.begin();
979         size_t textLen =  SkToSizeT(text.count());
980         switch (runType) {
981             case 0:
982                 fuzz->next(&x, &y);
983                 // TODO: Test other variations of this.
984                 buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
985                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
986                 break;
987             case 1:
988                 fuzz->next(&y);
989                 // TODO: Test other variations of this.
990                 buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
991                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
992                 fuzz->nextN(buffer->pos, glyphCount);
993                 break;
994             case 2:
995                 // TODO: Test other variations of this.
996                 buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
997                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
998                 fuzz->nextN(buffer->pos, glyphCount * 2);
999                 break;
1000             default:
1001                 SkASSERT(false);
1002                 break;
1003         }
1004     }
1005     return textBlobBuilder.make();
1006 }
1007
1008 static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
1009     if (!fuzz || !canvas || depth <= 0) {
1010         return;
1011     }
1012     SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1013     unsigned N;
1014     fuzz->nextRange(&N, 0, 2000);
1015     for (unsigned loop = 0; loop < N; ++loop) {
1016         if (fuzz->exhausted()) {
1017             return;
1018         }
1019         SkPaint paint;
1020         SkFont font;
1021         unsigned drawCommand;
1022         fuzz->nextRange(&drawCommand, 0, 62);
1023         switch (drawCommand) {
1024             case 0:
1025                 canvas->flush();
1026                 break;
1027             case 1:
1028                 canvas->save();
1029                 break;
1030             case 2: {
1031                 SkRect bounds;
1032                 fuzz->next(&bounds);
1033                 fuzz_paint(fuzz, &paint, depth - 1);
1034                 canvas->saveLayer(&bounds, &paint);
1035                 break;
1036             }
1037             case 3: {
1038                 SkRect bounds;
1039                 fuzz->next(&bounds);
1040                 canvas->saveLayer(&bounds, nullptr);
1041                 break;
1042             }
1043             case 4:
1044                 fuzz_paint(fuzz, &paint, depth - 1);
1045                 canvas->saveLayer(nullptr, &paint);
1046                 break;
1047             case 5:
1048                 canvas->saveLayer(nullptr, nullptr);
1049                 break;
1050             case 6: {
1051                 uint8_t alpha;
1052                 fuzz->next(&alpha);
1053                 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1054                 break;
1055             }
1056             case 7: {
1057                 SkRect bounds;
1058                 uint8_t alpha;
1059                 fuzz->next(&bounds, &alpha);
1060                 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1061                 break;
1062             }
1063             case 8: {
1064                 SkCanvas::SaveLayerRec saveLayerRec;
1065                 SkRect bounds;
1066                 if (make_fuzz_t<bool>(fuzz)) {
1067                     fuzz->next(&bounds);
1068                     saveLayerRec.fBounds = &bounds;
1069                 }
1070                 if (make_fuzz_t<bool>(fuzz)) {
1071                     fuzz_paint(fuzz, &paint, depth - 1);
1072                     saveLayerRec.fPaint = &paint;
1073                 }
1074                 sk_sp<SkImageFilter> imageFilter;
1075                 if (make_fuzz_t<bool>(fuzz)) {
1076                     imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1077                     saveLayerRec.fBackdrop = imageFilter.get();
1078                 }
1079                 // _DumpCanvas can't handle this.
1080                 // if (make_fuzz_t<bool>(fuzz)) {
1081                 //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1082                 // }
1083
1084                 canvas->saveLayer(saveLayerRec);
1085                 break;
1086             }
1087             case 9:
1088                 canvas->restore();
1089                 break;
1090             case 10: {
1091                 int saveCount;
1092                 fuzz->next(&saveCount);
1093                 canvas->restoreToCount(saveCount);
1094                 break;
1095             }
1096             case 11: {
1097                 SkScalar x, y;
1098                 fuzz->next(&x, &y);
1099                 canvas->translate(x, y);
1100                 break;
1101             }
1102             case 12: {
1103                 SkScalar x, y;
1104                 fuzz->next(&x, &y);
1105                 canvas->scale(x, y);
1106                 break;
1107             }
1108             case 13: {
1109                 SkScalar v;
1110                 fuzz->next(&v);
1111                 canvas->rotate(v);
1112                 break;
1113             }
1114             case 14: {
1115                 SkScalar x, y, v;
1116                 fuzz->next(&x, &y, &v);
1117                 canvas->rotate(v, x, y);
1118                 break;
1119             }
1120             case 15: {
1121                 SkScalar x, y;
1122                 fuzz->next(&x, &y);
1123                 canvas->skew(x, y);
1124                 break;
1125             }
1126             case 16: {
1127                 SkMatrix mat;
1128                 FuzzNiceMatrix(fuzz, &mat);
1129                 canvas->concat(mat);
1130                 break;
1131             }
1132             case 17: {
1133                 SkMatrix mat;
1134                 FuzzNiceMatrix(fuzz, &mat);
1135                 canvas->setMatrix(mat);
1136                 break;
1137             }
1138             case 18:
1139                 canvas->resetMatrix();
1140                 break;
1141             case 19: {
1142                 SkRect r;
1143                 int op;
1144                 bool doAntiAlias;
1145                 fuzz->next(&r, &doAntiAlias);
1146                 fuzz->nextRange(&op, 0, 1);
1147                 r.sort();
1148                 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1149                 break;
1150             }
1151             case 20: {
1152                 SkRRect rr;
1153                 int op;
1154                 bool doAntiAlias;
1155                 FuzzNiceRRect(fuzz, &rr);
1156                 fuzz->next(&doAntiAlias);
1157                 fuzz->nextRange(&op, 0, 1);
1158                 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1159                 break;
1160             }
1161             case 21: {
1162                 SkPath path;
1163                 FuzzNicePath(fuzz, &path, 30);
1164                 int op;
1165                 bool doAntiAlias;
1166                 fuzz->next(&doAntiAlias);
1167                 fuzz->nextRange(&op, 0, 1);
1168                 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1169                 break;
1170             }
1171             case 22: {
1172                 SkRegion region;
1173                 int op;
1174                 fuzz->next(&region);
1175                 fuzz->nextRange(&op, 0, 1);
1176                 canvas->clipRegion(region, (SkClipOp)op);
1177                 break;
1178             }
1179             case 23:
1180                 fuzz_paint(fuzz, &paint, depth - 1);
1181                 canvas->drawPaint(paint);
1182                 break;
1183             case 24: {
1184                 fuzz_paint(fuzz, &paint, depth - 1);
1185                 SkCanvas::PointMode pointMode;
1186                 fuzz->nextRange(&pointMode,
1187                                 SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
1188                 size_t count;
1189                 constexpr int kMaxCount = 30;
1190                 fuzz->nextRange(&count, 0, kMaxCount);
1191                 SkPoint pts[kMaxCount];
1192                 fuzz->nextN(pts, count);
1193                 canvas->drawPoints(pointMode, count, pts, paint);
1194                 break;
1195             }
1196             case 25: {
1197                 fuzz_paint(fuzz, &paint, depth - 1);
1198                 SkRect r;
1199                 fuzz->next(&r);
1200                 if (!r.isFinite()) {
1201                     break;
1202                 }
1203                 canvas->drawRect(r, paint);
1204                 break;
1205             }
1206             case 26: {
1207                 fuzz_paint(fuzz, &paint, depth - 1);
1208                 SkRegion region;
1209                 fuzz->next(&region);
1210                 canvas->drawRegion(region, paint);
1211                 break;
1212             }
1213             case 27: {
1214                 fuzz_paint(fuzz, &paint, depth - 1);
1215                 SkRect r;
1216                 fuzz->next(&r);
1217                 if (!r.isFinite()) {
1218                     break;
1219                 }
1220                 canvas->drawOval(r, paint);
1221                 break;
1222             }
1223             case 28: break; // must have deleted this some time earlier
1224             case 29: {
1225                 fuzz_paint(fuzz, &paint, depth - 1);
1226                 SkRRect rr;
1227                 FuzzNiceRRect(fuzz, &rr);
1228                 canvas->drawRRect(rr, paint);
1229                 break;
1230             }
1231             case 30: {
1232                 fuzz_paint(fuzz, &paint, depth - 1);
1233                 SkRRect orr, irr;
1234                 FuzzNiceRRect(fuzz, &orr);
1235                 FuzzNiceRRect(fuzz, &irr);
1236                 if (orr.getBounds().contains(irr.getBounds())) {
1237                     canvas->drawDRRect(orr, irr, paint);
1238                 }
1239                 break;
1240             }
1241             case 31: {
1242                 fuzz_paint(fuzz, &paint, depth - 1);
1243                 SkRect r;
1244                 SkScalar start, sweep;
1245                 bool useCenter;
1246                 fuzz->next(&r, &start, &sweep, &useCenter);
1247                 canvas->drawArc(r, start, sweep, useCenter, paint);
1248                 break;
1249             }
1250             case 32: {
1251                 fuzz_paint(fuzz, &paint, depth - 1);
1252                 SkPath path;
1253                 FuzzNicePath(fuzz, &path, 60);
1254                 canvas->drawPath(path, paint);
1255                 break;
1256             }
1257             case 33: {
1258                 sk_sp<SkImage> img = make_fuzz_image(fuzz);
1259                 SkScalar left, top;
1260                 bool usePaint;
1261                 fuzz->next(&left, &top, &usePaint);
1262                 if (usePaint) {
1263                     fuzz_paint(fuzz, &paint, depth - 1);
1264                 }
1265                 canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
1266                                   usePaint ? &paint : nullptr);
1267                 break;
1268             }
1269             case 35: {
1270                 auto img = make_fuzz_image(fuzz);
1271                 SkIRect src;
1272                 SkRect dst;
1273                 bool usePaint;
1274                 fuzz->next(&src, &dst, &usePaint);
1275                 if (usePaint) {
1276                     fuzz_paint(fuzz, &paint, depth - 1);
1277                 }
1278                 SkCanvas::SrcRectConstraint constraint =
1279                         make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1280                                                 : SkCanvas::kFast_SrcRectConstraint;
1281                 canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
1282                                       usePaint ? &paint : nullptr, constraint);
1283                 break;
1284             }
1285             case 37: {
1286                 auto img = make_fuzz_image(fuzz);
1287                 SkIRect center;
1288                 SkRect dst;
1289                 bool usePaint;
1290                 fuzz->next(&usePaint);
1291                 if (usePaint) {
1292                     fuzz_paint(fuzz, &paint, depth - 1);
1293                 }
1294                 if (make_fuzz_t<bool>(fuzz)) {
1295                     fuzz->next(&center);
1296                 } else {  // Make valid center, see SkLatticeIter::Valid().
1297                     fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1298                     fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1299                     fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1300                     fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1301                 }
1302                 fuzz->next(&dst);
1303                 canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
1304                                       usePaint ? &paint : nullptr);
1305                 break;
1306             }
1307             case 44: {
1308                 auto img = make_fuzz_image(fuzz);
1309                 bool usePaint;
1310                 SkRect dst;
1311                 fuzz->next(&usePaint, &dst);
1312                 if (usePaint) {
1313                     fuzz_paint(fuzz, &paint, depth - 1);
1314                 }
1315                 constexpr int kMax = 6;
1316                 int xDivs[kMax], yDivs[kMax];
1317                 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1318                 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1319                 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1320                 fuzz->nextN(xDivs, lattice.fXCount);
1321                 fuzz->nextN(yDivs, lattice.fYCount);
1322                 canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
1323                                          usePaint ? &paint : nullptr);
1324                 break;
1325             }
1326             case 45: {
1327                 fuzz_paint(fuzz, &paint, depth - 1);
1328                 font = fuzz_font(fuzz);
1329                 SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
1330                 SkScalar x, y;
1331                 fuzz->next(&x, &y);
1332                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
1333                 canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
1334                                        font, paint);
1335                 break;
1336             }
1337             case 46: {
1338                 // was drawPosText
1339                 break;
1340             }
1341             case 47: {
1342                 // was drawPosTextH
1343                 break;
1344             }
1345             case 48: {
1346                 // was drawtextonpath
1347                 break;
1348             }
1349             case 49: {
1350                 // was drawtextonpath
1351                 break;
1352             }
1353             case 50: {
1354                 // was drawTextRSXform
1355                 break;
1356             }
1357             case 51: {
1358                 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
1359                 fuzz_paint(fuzz, &paint, depth - 1);
1360                 SkScalar x, y;
1361                 fuzz->next(&x, &y);
1362                 canvas->drawTextBlob(blob, x, y, paint);
1363                 break;
1364             }
1365             case 52: {
1366                 SkMatrix matrix;
1367                 bool usePaint, useMatrix;
1368                 fuzz->next(&usePaint, &useMatrix);
1369                 if (usePaint) {
1370                     fuzz_paint(fuzz, &paint, depth - 1);
1371                 }
1372                 if (useMatrix) {
1373                     FuzzNiceMatrix(fuzz, &matrix);
1374                 }
1375                 auto pic = make_fuzz_picture(fuzz, depth - 1);
1376                 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1377                                     usePaint ? &paint : nullptr);
1378                 break;
1379             }
1380             case 53: {
1381                 fuzz_paint(fuzz, &paint, depth - 1);
1382                 SkVertices::VertexMode vertexMode;
1383                 SkBlendMode blendMode;
1384                 fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1385                 fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
1386                 constexpr int kMaxCount = 100;
1387                 int vertexCount;
1388                 SkPoint vertices[kMaxCount];
1389                 SkPoint texs[kMaxCount];
1390                 SkColor colors[kMaxCount];
1391                 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1392                 fuzz->nextN(vertices, vertexCount);
1393                 bool useTexs, useColors;
1394                 fuzz->next(&useTexs, &useColors);
1395                 if (useTexs) {
1396                     fuzz->nextN(texs, vertexCount);
1397                 }
1398                 if (useColors) {
1399                     fuzz->nextN(colors, vertexCount);
1400                 }
1401                 int indexCount = 0;
1402                 uint16_t indices[kMaxCount * 2];
1403                 if (make_fuzz_t<bool>(fuzz)) {
1404                     fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1405                     for (int index = 0; index < indexCount; ++index) {
1406                         fuzz->nextRange(&indices[index], 0, vertexCount - 1);
1407                     }
1408                 }
1409                 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1410                                                           useTexs ? texs : nullptr,
1411                                                           useColors ? colors : nullptr,
1412                                                           indexCount, indices),
1413                                      blendMode, paint);
1414                 break;
1415             }
1416             case 54: {
1417                 SkColor color;
1418                 SkBlendMode blendMode;
1419                 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1420                 fuzz->next(&color);
1421                 canvas->drawColor(color, blendMode);
1422                 break;
1423             }
1424             case 55: {
1425                 SkColor4f color;
1426                 SkBlendMode blendMode;
1427                 float R, G, B, Alpha;
1428                 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1429                 fuzz->nextRange(&R, -1, 2);
1430                 fuzz->nextRange(&G, -1, 2);
1431                 fuzz->nextRange(&B, -1, 2);
1432                 fuzz->nextRange(&Alpha, 0, 1);
1433                 color = {R, G, B, Alpha};
1434                 canvas->drawColor(color, blendMode);
1435                 break;
1436             }
1437             case 56: {
1438                 fuzz_paint(fuzz, &paint, depth - 1);
1439                 SkPoint p0, p1;
1440                 fuzz->next(&p0, &p1);
1441                 canvas->drawLine(p0, p1, paint);
1442                 break;
1443             }
1444             case 57: {
1445                 fuzz_paint(fuzz, &paint, depth - 1);
1446                 SkIRect r;
1447                 fuzz->next(&r);
1448                 canvas->drawIRect(r, paint);
1449                 break;
1450             }
1451             case 58: {
1452                 fuzz_paint(fuzz, &paint, depth - 1);
1453                 SkScalar radius;
1454                 SkPoint center;
1455                 fuzz->next(&radius, &center);
1456                 canvas->drawCircle(center, radius, paint);
1457                 break;
1458             }
1459             case 59: {
1460                 fuzz_paint(fuzz, &paint, depth - 1);
1461                 SkRect oval;
1462                 SkScalar startAngle, sweepAngle;
1463                 bool useCenter;
1464                 fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
1465                 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1466                 break;
1467             }
1468             case 60: {
1469                 fuzz_paint(fuzz, &paint, depth - 1);
1470                 SkRect rect;
1471                 SkScalar rx, ry;
1472                 fuzz->next(&rect, &rx, &ry);
1473                 canvas->drawRoundRect(rect, rx, ry, paint);
1474                 break;
1475             }
1476             case 61: {
1477                 fuzz_paint(fuzz, &paint, depth - 1);
1478                 font = fuzz_font(fuzz);
1479                 std::string str = make_fuzz_string(fuzz);
1480                 SkScalar x, y;
1481                 fuzz->next(&x, &y);
1482                 canvas->drawString(str.c_str(), x, y, font, paint);
1483                 break;
1484             }
1485             case 62: {
1486                 fuzz_paint(fuzz, &paint, depth - 1);
1487                 SkPoint cubics[12];
1488                 SkColor colors[4];
1489                 SkPoint texCoords[4];
1490                 bool useTexCoords;
1491                 fuzz->nextN(cubics, 12);
1492                 fuzz->nextN(colors, 4);
1493                 fuzz->next(&useTexCoords);
1494                 if (useTexCoords) {
1495                     fuzz->nextN(texCoords, 4);
1496                 }
1497                 SkBlendMode mode;
1498                 fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
1499                 canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
1500                     , mode, paint);
1501                 break;
1502             }
1503             default:
1504                 SkASSERT(false);
1505                 break;
1506         }
1507     }
1508 }
1509
1510 static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1511     SkScalar w, h;
1512     fuzz->next(&w, &h);
1513     SkPictureRecorder pictureRecorder;
1514     fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1515     return pictureRecorder.finishRecordingAsPicture();
1516 }
1517
1518 DEF_FUZZ(NullCanvas, fuzz) {
1519     fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1520 }
1521
1522 constexpr SkISize kCanvasSize = {128, 160};
1523
1524 DEF_FUZZ(RasterN32Canvas, fuzz) {
1525     auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1526     if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
1527     fuzz_canvas(fuzz, surface->getCanvas());
1528 }
1529
1530 DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1531     SkPictureRecorder recorder;
1532     fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1533                                               SkIntToScalar(kCanvasSize.height())));
1534     sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1535     if (!pic) { fuzz->signalBug(); }
1536     sk_sp<SkData> data = pic->serialize();
1537     if (!data) { fuzz->signalBug(); }
1538     SkReadBuffer rb(data->data(), data->size());
1539     auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
1540     if (!deserialized) { fuzz->signalBug(); }
1541     auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1542     SkASSERT(surface && surface->getCanvas());
1543     surface->getCanvas()->drawPicture(deserialized);
1544 }
1545
1546 DEF_FUZZ(ImageFilter, fuzz) {
1547     auto fil = make_fuzz_imageFilter(fuzz, 20);
1548
1549     SkPaint paint;
1550     paint.setImageFilter(fil);
1551     SkBitmap bitmap;
1552     SkCanvas canvas(bitmap);
1553     canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1554 }
1555
1556
1557 //SkRandom _rand;
1558 #define SK_ADD_RANDOM_BIT_FLIPS
1559
1560 DEF_FUZZ(SerializedImageFilter, fuzz) {
1561     SkBitmap bitmap;
1562     if (!bitmap.tryAllocN32Pixels(256, 256)) {
1563         SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
1564         return;
1565     }
1566
1567     auto filter = make_fuzz_imageFilter(fuzz, 20);
1568     if (!filter) {
1569         return;
1570     }
1571     auto data = filter->serialize();
1572     const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1573     size_t len = data->size();
1574 #ifdef SK_ADD_RANDOM_BIT_FLIPS
1575     unsigned char* p = const_cast<unsigned char*>(ptr);
1576     for (size_t i = 0; i < len; ++i, ++p) {
1577         uint8_t j;
1578         fuzz->nextRange(&j, 1, 250);
1579         if (j == 1) { // 0.4% of the time, flip a bit or byte
1580             uint8_t k;
1581             fuzz->nextRange(&k, 1, 10);
1582             if (k == 1) { // Then 10% of the time, change a whole byte
1583                 uint8_t s;
1584                 fuzz->nextRange(&s, 0, 2);
1585                 switch(s) {
1586                 case 0:
1587                     *p ^= 0xFF; // Flip entire byte
1588                     break;
1589                 case 1:
1590                     *p = 0xFF; // Set all bits to 1
1591                     break;
1592                 case 2:
1593                     *p = 0x00; // Set all bits to 0
1594                     break;
1595                 }
1596             } else {
1597                 uint8_t s;
1598                 fuzz->nextRange(&s, 0, 7);
1599                 *p ^= (1 << 7);
1600             }
1601         }
1602     }
1603 #endif // SK_ADD_RANDOM_BIT_FLIPS
1604     auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1605
1606     // uncomment below to write out a serialized image filter (to make corpus
1607     // for -t filter_fuzz)
1608     // SkString s("./serialized_filters/sf");
1609     // s.appendU32(_rand.nextU());
1610     // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1611     // sk_fwrite(data->bytes(), data->size(), file);
1612     // sk_fclose(file);
1613
1614     SkPaint paint;
1615     paint.setImageFilter(deserializedFil);
1616
1617     SkCanvas canvas(bitmap);
1618     canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
1619     canvas.restore();
1620 }
1621
1622 #if SK_SUPPORT_GPU
1623 static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
1624     SkASSERT(context);
1625     auto surface = SkSurface::MakeRenderTarget(
1626             context,
1627             SkBudgeted::kNo,
1628             SkImageInfo::Make(kCanvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1629     SkASSERT(surface && surface->getCanvas());
1630     fuzz_canvas(fuzz, surface->getCanvas());
1631 }
1632
1633 DEF_FUZZ(MockGPUCanvas, fuzz) {
1634     sk_gpu_test::GrContextFactory f;
1635     fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
1636 }
1637 #endif
1638
1639 #ifdef SK_GL
1640 static void dump_GPU_info(GrDirectContext* context) {
1641     const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
1642                                     ->glInterface();
1643     const GrGLubyte* output;
1644     GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1645     SkDebugf("GL_RENDERER %s\n", (const char*) output);
1646
1647     GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1648     SkDebugf("GL_VENDOR %s\n", (const char*) output);
1649
1650     GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1651     SkDebugf("GL_VERSION %s\n", (const char*) output);
1652 }
1653
1654 DEF_FUZZ(NativeGLCanvas, fuzz) {
1655     sk_gpu_test::GrContextFactory f;
1656     auto context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
1657     if (!context) {
1658         context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
1659     }
1660     if (FLAGS_gpuInfo) {
1661         dump_GPU_info(context);
1662     }
1663     fuzz_ganesh(fuzz, context);
1664 }
1665 #endif
1666
1667 DEF_FUZZ(PDFCanvas, fuzz) {
1668     SkNullWStream stream;
1669     auto doc = SkPDF::MakeDocument(&stream);
1670     fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1671                                      SkIntToScalar(kCanvasSize.height())));
1672 }
1673
1674 // not a "real" thing to fuzz, used to debug errors found while fuzzing.
1675 DEF_FUZZ(_DumpCanvas, fuzz) {
1676     DebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
1677     fuzz_canvas(fuzz, &debugCanvas);
1678     std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1679     UrlDataManager dataManager(SkString("data"));
1680     SkDynamicMemoryWStream stream;
1681     SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1682     writer.beginObject(); // root
1683     debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
1684     writer.endObject(); // root
1685     writer.flush();
1686     sk_sp<SkData> json = stream.detachAsData();
1687     fwrite(json->data(), json->size(), 1, stdout);
1688 }
1689
1690 DEF_FUZZ(SVGCanvas, fuzz) {
1691     SkNullWStream stream;
1692     SkRect bounds = SkRect::MakeIWH(150, 150);
1693     std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
1694     fuzz_canvas(fuzz, canvas.get());
1695 }