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