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