• 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/utils/SkNullCanvas.h"
27 #include "src/core/SkOSFile.h"
28 #include "src/core/SkPicturePriv.h"
29 #include "tools/debugger/DebugCanvas.h"
30 
31 // EFFECTS
32 #include "include/core/SkTextBlob.h"
33 #include "include/effects/Sk1DPathEffect.h"
34 #include "include/effects/Sk2DPathEffect.h"
35 #include "include/effects/SkBlurMaskFilter.h"
36 #include "include/effects/SkColorMatrixFilter.h"
37 #include "include/effects/SkCornerPathEffect.h"
38 #include "include/effects/SkDashPathEffect.h"
39 #include "include/effects/SkDiscretePathEffect.h"
40 #include "include/effects/SkGradientShader.h"
41 #include "include/effects/SkHighContrastFilter.h"
42 #include "include/effects/SkImageFilters.h"
43 #include "include/effects/SkLumaColorFilter.h"
44 #include "include/effects/SkPerlinNoiseShader.h"
45 #include "include/effects/SkTableColorFilter.h"
46 #include "src/core/SkReadBuffer.h"
47 
48 // SRC
49 #include "src/utils/SkUTF.h"
50 #include "tools/flags/CommandLineFlags.h"
51 
52 #if SK_SUPPORT_GPU
53 #include "include/gpu/gl/GrGLFunctions.h"
54 #include "src/gpu/GrContextPriv.h"
55 #include "src/gpu/gl/GrGLGpu.h"
56 #include "src/gpu/gl/GrGLUtil.h"
57 #include "tools/gpu/GrContextFactory.h"
58 #endif
59 
60 // MISC
61 
62 #include <iostream>
63 #include <utility>
64 
65 static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
66 
67 // TODO:
68 //   SkTextBlob with Unicode
69 //   SkImage: more types
70 
71 // be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
72 // In fact, all make_fuzz_foo() functions have this potential problem.
73 // Use sequence points!
74 template <typename T>
make_fuzz_t(Fuzz * fuzz)75 inline T make_fuzz_t(Fuzz* fuzz) {
76     T t;
77     fuzz->next(&t);
78     return t;
79 }
80 
81 static sk_sp<SkImage> make_fuzz_image(Fuzz*);
82 
83 static SkBitmap make_fuzz_bitmap(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, useMatrix ? &matrix : nullptr);
203         case 4:
204             bitmap = make_fuzz_bitmap(fuzz);
205             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
206             fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
207             fuzz->next(&useMatrix);
208             if (useMatrix) {
209                 FuzzNiceMatrix(fuzz, &matrix);
210             }
211             return bitmap.makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
212         case 5:
213             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
214             FuzzNiceMatrix(fuzz, &matrix);
215             return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
216         case 6:
217             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
218             colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
219             return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
220         case 7:
221             shader1 = make_fuzz_shader(fuzz, depth - 1);  // limit recursion.
222             shader2 = make_fuzz_shader(fuzz, depth - 1);
223             fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
224             return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
225         case 8: {
226             auto pic = make_fuzz_picture(fuzz, depth - 1);
227             bool useTile;
228             SkRect tile;
229             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
230             fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
231             fuzz->next(&useMatrix, &useTile);
232             if (useMatrix) {
233                 FuzzNiceMatrix(fuzz, &matrix);
234             }
235             if (useTile) {
236                 fuzz->next(&tile);
237             }
238             return pic->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
239         }
240         // EFFECTS:
241         case 9:
242             // Deprecated SkGaussianEdgeShader
243             return nullptr;
244         case 10: {
245             constexpr int kMaxColors = 12;
246             SkPoint pts[2];
247             SkColor colors[kMaxColors];
248             SkScalar pos[kMaxColors];
249             int colorCount;
250             bool usePos;
251             fuzz->nextN(pts, 2);
252             fuzz->nextRange(&colorCount, 2, kMaxColors);
253             fuzz->nextN(colors, colorCount);
254             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
255             fuzz->next(&useMatrix, &usePos);
256             if (useMatrix) {
257                 FuzzNiceMatrix(fuzz, &matrix);
258             }
259             if (usePos) {
260                 fuzz_gradient_stops(fuzz, pos, colorCount);
261             }
262             return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
263                                                 tmX, 0, useMatrix ? &matrix : nullptr);
264         }
265         case 11: {
266             constexpr int kMaxColors = 12;
267             SkPoint center;
268             SkScalar radius;
269             int colorCount;
270             bool usePos;
271             SkColor colors[kMaxColors];
272             SkScalar pos[kMaxColors];
273             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
274             fuzz->next(&useMatrix, &usePos, &center, &radius);
275             fuzz->nextRange(&colorCount, 2, kMaxColors);
276             fuzz->nextN(colors, colorCount);
277             if (useMatrix) {
278                 FuzzNiceMatrix(fuzz, &matrix);
279             }
280             if (usePos) {
281                 fuzz_gradient_stops(fuzz, pos, colorCount);
282             }
283             return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
284                                                 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
285         }
286         case 12: {
287             constexpr int kMaxColors = 12;
288             SkPoint start, end;
289             SkScalar startRadius, endRadius;
290             int colorCount;
291             bool usePos;
292             SkColor colors[kMaxColors];
293             SkScalar pos[kMaxColors];
294             fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
295             fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
296             fuzz->nextRange(&colorCount, 2, kMaxColors);
297             fuzz->nextN(colors, colorCount);
298             if (useMatrix) {
299                 FuzzNiceMatrix(fuzz, &matrix);
300             }
301             if (usePos) {
302                 fuzz_gradient_stops(fuzz, pos, colorCount);
303             }
304             return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
305                                                          usePos ? pos : nullptr, colorCount, tmX, 0,
306                                                          useMatrix ? &matrix : nullptr);
307         }
308         case 13: {
309             constexpr int kMaxColors = 12;
310             SkScalar cx, cy;
311             int colorCount;
312             bool usePos;
313             SkColor colors[kMaxColors];
314             SkScalar pos[kMaxColors];
315             fuzz->next(&cx, &cy, &useMatrix, &usePos);
316             fuzz->nextRange(&colorCount, 2, kMaxColors);
317             fuzz->nextN(colors, colorCount);
318             if (useMatrix) {
319                 FuzzNiceMatrix(fuzz, &matrix);
320             }
321             if (usePos) {
322                 fuzz_gradient_stops(fuzz, pos, colorCount);
323             }
324             return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
325                                                0, useMatrix ? &matrix : nullptr);
326         }
327         case 14: {
328             SkScalar baseFrequencyX, baseFrequencyY, seed;
329             int numOctaves;
330             SkISize tileSize;
331             bool useTileSize, turbulence;
332             fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
333             if (useTileSize) {
334                 fuzz->next(&tileSize);
335             }
336             fuzz->nextRange(&numOctaves, 2, 7);
337             if (turbulence) {
338                 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
339                                                            numOctaves, seed,
340                                                            useTileSize ? &tileSize : nullptr);
341             } else {
342                 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
343                                                              numOctaves, seed,
344                                                              useTileSize ? &tileSize : nullptr);
345             }
346         }
347         default:
348             SkASSERT(false);
349             break;
350     }
351     return nullptr;
352 }
353 
make_fuzz_patheffect(Fuzz * fuzz,int depth)354 static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
355     if (depth <= 0) {
356         return nullptr;
357     }
358     uint8_t pathEffectType;
359     fuzz->nextRange(&pathEffectType, 0, 8);
360     switch (pathEffectType) {
361         case 0: {
362             return nullptr;
363         }
364         case 1: {
365             sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
366             sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
367             return SkPathEffect::MakeSum(std::move(first), std::move(second));
368         }
369         case 2: {
370             sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
371             sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
372             return SkPathEffect::MakeCompose(std::move(first), std::move(second));
373         }
374         case 3: {
375             SkPath path;
376             FuzzNicePath(fuzz, &path, 20);
377             SkScalar advance, phase;
378             fuzz->next(&advance, &phase);
379             SkPath1DPathEffect::Style style;
380             fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
381             return SkPath1DPathEffect::Make(path, advance, phase, style);
382         }
383         case 4: {
384             SkScalar width;
385             SkMatrix matrix;
386             fuzz->next(&width);
387             FuzzNiceMatrix(fuzz, &matrix);
388             return SkLine2DPathEffect::Make(width, matrix);
389         }
390         case 5: {
391             SkPath path;
392             FuzzNicePath(fuzz, &path, 20);
393             SkMatrix matrix;
394             FuzzNiceMatrix(fuzz, &matrix);
395             return SkPath2DPathEffect::Make(matrix, path);
396         }
397         case 6: {
398             SkScalar radius;
399             fuzz->next(&radius);
400             return SkCornerPathEffect::Make(radius);
401         }
402         case 7: {
403             SkScalar phase;
404             fuzz->next(&phase);
405             SkScalar intervals[20];
406             int count;
407             fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
408             fuzz->nextN(intervals, count);
409             return SkDashPathEffect::Make(intervals, count, phase);
410         }
411         case 8: {
412             SkScalar segLength, dev;
413             uint32_t seed;
414             fuzz->next(&segLength, &dev, &seed);
415             return SkDiscretePathEffect::Make(segLength, dev, seed);
416         }
417         default:
418             SkASSERT(false);
419             return nullptr;
420     }
421 }
422 
make_fuzz_maskfilter(Fuzz * fuzz)423 static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
424     int maskfilterType;
425     fuzz->nextRange(&maskfilterType, 0, 1);
426     switch (maskfilterType) {
427         case 0:
428             return nullptr;
429         case 1: {
430             SkBlurStyle blurStyle;
431             fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
432             SkScalar sigma;
433             fuzz->next(&sigma);
434             bool respectCTM;
435             fuzz->next(&respectCTM);
436             return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
437         }
438         default:
439             SkASSERT(false);
440             return nullptr;
441     }
442 }
443 
make_fuzz_typeface(Fuzz * fuzz)444 static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
445     if (make_fuzz_t<bool>(fuzz)) {
446         return nullptr;
447     }
448     auto fontMugger = SkFontMgr::RefDefault();
449     SkASSERT(fontMugger);
450     int familyCount = fontMugger->countFamilies();
451     int i, j;
452     fuzz->nextRange(&i, 0, familyCount - 1);
453     sk_sp<SkFontStyleSet> family(fontMugger->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 
make_fuzz_imageFilter(Fuzz * fuzz,int depth)523 static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
524     if (depth <= 0) {
525         return nullptr;
526     }
527     uint8_t imageFilterType;
528     fuzz->nextRange(&imageFilterType, 0, 23);
529     switch (imageFilterType) {
530         case 0:
531             return nullptr;
532         case 1: {
533             SkScalar sigmaX, sigmaY;
534             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
535             bool useCropRect;
536             fuzz->next(&sigmaX, &sigmaY, &useCropRect);
537             SkIRect cropRect;
538             if (useCropRect) {
539                 fuzz->next(&cropRect);
540             }
541             return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
542                                         useCropRect ? &cropRect : nullptr);
543         }
544         case 2: {
545             SkMatrix matrix;
546             FuzzNiceMatrix(fuzz, &matrix);
547             SkFilterQuality quality;
548             fuzz->nextEnum(&quality, SkFilterQuality::kLast_SkFilterQuality);
549             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
550             return SkImageFilters::MatrixTransform(matrix, quality, std::move(input));
551         }
552         case 3: {
553             SkRegion region;
554             SkScalar innerMin, outerMax;
555             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
556             bool useCropRect;
557             fuzz->next(&region, &innerMin, &outerMax, &useCropRect);
558             SkIRect cropRect;
559             if (useCropRect) {
560                 fuzz->next(&cropRect);
561             }
562             return SkImageFilters::AlphaThreshold(region, innerMin, outerMax, std::move(input),
563                                                   useCropRect ? &cropRect : nullptr);
564         }
565         case 4: {
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 5: {
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 6: {
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 7: {
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 8: {
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 9:
634             return SkImageFilters::Image(make_fuzz_image(fuzz));
635         case 10: {
636             sk_sp<SkImage> image = make_fuzz_image(fuzz);
637             SkRect srcRect, dstRect;
638             SkFilterQuality filterQuality;
639             fuzz->next(&srcRect, &dstRect);
640             fuzz->nextEnum(&filterQuality, SkFilterQuality::kLast_SkFilterQuality);
641             return SkImageFilters::Image(std::move(image), srcRect, dstRect, filterQuality);
642         }
643         case 11:
644             return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
645         case 12: {
646             SkRect srcRect;
647             SkScalar inset;
648             bool useCropRect;
649             SkIRect cropRect;
650             fuzz->next(&srcRect, &inset, &useCropRect);
651             if (useCropRect) {
652                 fuzz->next(&cropRect);
653             }
654             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
655             return SkImageFilters::Magnifier(srcRect, inset, std::move(input),
656                                              useCropRect ? &cropRect : nullptr);
657         }
658         case 13: {
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 14: {
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 15: {
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 16: {
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 17: {
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 18: {
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 19: {
750             SkPaint paint;
751             fuzz_paint(fuzz, &paint, depth - 1);
752             bool useCropRect;
753             fuzz->next(&useCropRect);
754             SkIRect cropRect;
755             if (useCropRect) {
756                 fuzz->next(&cropRect);
757             }
758             return SkImageFilters::Paint(paint, useCropRect ? &cropRect : nullptr);
759         }
760         case 20: {
761             sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
762             return SkImageFilters::Picture(std::move(picture));
763         }
764         case 21: {
765             SkRect cropRect;
766             fuzz->next(&cropRect);
767             sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
768             return SkImageFilters::Picture(std::move(picture), cropRect);
769         }
770         case 22: {
771             SkRect src, dst;
772             fuzz->next(&src, &dst);
773             sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
774             return SkImageFilters::Tile(src, dst, std::move(input));
775         }
776         case 23: {
777             SkBlendMode blendMode;
778             bool useCropRect;
779             fuzz->next(&useCropRect);
780             fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
781             SkIRect cropRect;
782             if (useCropRect) {
783                 fuzz->next(&cropRect);
784             }
785             sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
786             sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
787             return SkImageFilters::Xfermode(blendMode, std::move(bg), std::move(fg),
788                                             useCropRect ? &cropRect : nullptr);
789         }
790         default:
791             SkASSERT(false);
792             return nullptr;
793     }
794 }
795 
make_fuzz_image(Fuzz * fuzz)796 static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
797     int w, h;
798     fuzz->nextRange(&w, 1, 1024);
799     fuzz->nextRange(&h, 1, 1024);
800     SkAutoTMalloc<SkPMColor> data(w * h);
801     SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
802     int n = w * h;
803     for (int i = 0; i < n; ++i) {
804         SkColor c;
805         fuzz->next(&c);
806         data[i] = SkPreMultiplyColor(c);
807     }
808     (void)data.release();
809     return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
810                                    nullptr);
811 }
812 
make_fuzz_bitmap(Fuzz * fuzz)813 static SkBitmap make_fuzz_bitmap(Fuzz* fuzz) {
814     SkBitmap bitmap;
815     int w, h;
816     fuzz->nextRange(&w, 1, 1024);
817     fuzz->nextRange(&h, 1, 1024);
818     if (!bitmap.tryAllocN32Pixels(w, h)) {
819         SkDEBUGF("Could not allocate pixels %d x %d", w, h);
820         return bitmap;
821     }
822     for (int y = 0; y < h; ++y) {
823         for (int x = 0; x < w; ++x) {
824             SkColor c;
825             fuzz->next(&c);
826             *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
827         }
828     }
829     return bitmap;
830 }
831 
832 template <typename T>
make_fuzz_enum_range(Fuzz * fuzz,T maxv)833 static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
834     T value;
835     fuzz->nextEnum(&value, maxv);
836     return value;
837 }
838 
fuzz_paint(Fuzz * fuzz,SkPaint * paint,int depth)839 static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
840     if (!fuzz || !paint || depth <= 0) {
841         return;
842     }
843 
844     paint->setAntiAlias(    make_fuzz_t<bool>(fuzz));
845     paint->setDither(       make_fuzz_t<bool>(fuzz));
846     paint->setColor(        make_fuzz_t<SkColor>(fuzz));
847     paint->setBlendMode(    make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
848     paint->setFilterQuality(make_fuzz_enum_range<SkFilterQuality>(fuzz, kLast_SkFilterQuality));
849     paint->setStyle(        make_fuzz_enum_range<SkPaint::Style>(fuzz,
850                                                  SkPaint::Style::kStrokeAndFill_Style));
851     paint->setShader(       make_fuzz_shader(fuzz, depth - 1));
852     paint->setPathEffect(   make_fuzz_patheffect(fuzz, depth - 1));
853     paint->setMaskFilter(   make_fuzz_maskfilter(fuzz));
854     paint->setImageFilter(  make_fuzz_imageFilter(fuzz, depth - 1));
855     paint->setColorFilter(  make_fuzz_colorfilter(fuzz, depth - 1));
856 
857     if (paint->getStyle() != SkPaint::kFill_Style) {
858         paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
859         paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
860         paint->setStrokeCap(  make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
861         paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
862     }
863 }
864 
fuzz_font(Fuzz * fuzz)865 static SkFont fuzz_font(Fuzz* fuzz) {
866     SkFont font;
867     font.setTypeface(           make_fuzz_typeface(fuzz));
868     font.setSize(               make_fuzz_t<SkScalar>(fuzz));
869     font.setScaleX(             make_fuzz_t<SkScalar>(fuzz));
870     font.setSkewX(              make_fuzz_t<SkScalar>(fuzz));
871     font.setLinearMetrics(      make_fuzz_t<bool>(fuzz));
872     font.setSubpixel(           make_fuzz_t<bool>(fuzz));
873     font.setEmbeddedBitmaps(    make_fuzz_t<bool>(fuzz));
874     font.setForceAutoHinting(   make_fuzz_t<bool>(fuzz));
875     font.setEmbolden(           make_fuzz_t<bool>(fuzz));
876     font.setHinting(            make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
877     font.setEdging(             make_fuzz_enum_range<SkFont::Edging>(fuzz,
878                                                      SkFont::Edging::kSubpixelAntiAlias));
879     return font;
880 }
881 
fuzz_paint_text_encoding(Fuzz * fuzz)882 static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
883     return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
884 }
885 
886 constexpr int kMaxGlyphCount = 30;
887 
make_fuzz_text(Fuzz * fuzz,const SkFont & font,SkTextEncoding encoding)888 static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
889     SkTDArray<uint8_t> array;
890     if (SkTextEncoding::kGlyphID == encoding) {
891         int glyphRange = font.getTypefaceOrDefault()->countGlyphs();
892         if (glyphRange == 0) {
893             // Some fuzzing environments have no fonts, so empty array is the best
894             // we can do.
895             return array;
896         }
897         int glyphCount;
898         fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
899         SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
900         for (int i = 0; i < glyphCount; ++i) {
901             fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
902         }
903         return array;
904     }
905     static const SkUnichar ranges[][2] = {
906         {0x0020, 0x007F},
907         {0x00A1, 0x0250},
908         {0x0400, 0x0500},
909     };
910     int32_t count = 0;
911     for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
912         count += (ranges[i][1] - ranges[i][0]);
913     }
914     constexpr int kMaxLength = kMaxGlyphCount;
915     SkUnichar buffer[kMaxLength];
916     int length;
917     fuzz->nextRange(&length, 1, kMaxLength);
918     for (int j = 0; j < length; ++j) {
919         int32_t value;
920         fuzz->nextRange(&value, 0, count - 1);
921         for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
922             if (value + ranges[i][0] < ranges[i][1]) {
923                 buffer[j] = value + ranges[i][0];
924                 break;
925             } else {
926                 value -= (ranges[i][1] - ranges[i][0]);
927             }
928         }
929     }
930     switch (encoding) {
931         case SkTextEncoding::kUTF8: {
932             size_t utf8len = 0;
933             for (int j = 0; j < length; ++j) {
934                 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
935             }
936             char* ptr = (char*)array.append(utf8len);
937             for (int j = 0; j < length; ++j) {
938                 ptr += SkUTF::ToUTF8(buffer[j], ptr);
939             }
940         } break;
941         case SkTextEncoding::kUTF16: {
942             size_t utf16len = 0;
943             for (int j = 0; j < length; ++j) {
944                 utf16len += SkUTF::ToUTF16(buffer[j]);
945             }
946             uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
947             for (int j = 0; j < length; ++j) {
948                 ptr += SkUTF::ToUTF16(buffer[j], ptr);
949             }
950         } break;
951         case SkTextEncoding::kUTF32:
952             memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
953             break;
954         default:
955             SkASSERT(false);
956             break;
957     }
958     return array;
959 }
960 
make_fuzz_textblob(Fuzz * fuzz)961 static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
962     SkTextBlobBuilder textBlobBuilder;
963     int8_t runCount;
964     fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
965     while (runCount-- > 0) {
966         SkFont font;
967         SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
968         font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
969         SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
970         int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
971         SkASSERT(glyphCount <= kMaxGlyphCount);
972         SkScalar x, y;
973         const SkTextBlobBuilder::RunBuffer* buffer;
974         uint8_t runType;
975         fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
976         const void* textPtr = text.begin();
977         size_t textLen =  SkToSizeT(text.count());
978         switch (runType) {
979             case 0:
980                 fuzz->next(&x, &y);
981                 // TODO: Test other variations of this.
982                 buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
983                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
984                 break;
985             case 1:
986                 fuzz->next(&y);
987                 // TODO: Test other variations of this.
988                 buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
989                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
990                 fuzz->nextN(buffer->pos, glyphCount);
991                 break;
992             case 2:
993                 // TODO: Test other variations of this.
994                 buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
995                 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
996                 fuzz->nextN(buffer->pos, glyphCount * 2);
997                 break;
998             default:
999                 SkASSERT(false);
1000                 break;
1001         }
1002     }
1003     return textBlobBuilder.make();
1004 }
1005 
fuzz_canvas(Fuzz * fuzz,SkCanvas * canvas,int depth=9)1006 static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
1007     if (!fuzz || !canvas || depth <= 0) {
1008         return;
1009     }
1010     SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1011     unsigned N;
1012     fuzz->nextRange(&N, 0, 2000);
1013     for (unsigned i = 0; i < N; ++i) {
1014         if (fuzz->exhausted()) {
1015             return;
1016         }
1017         SkPaint paint;
1018         SkFont font;
1019         unsigned drawCommand;
1020         fuzz->nextRange(&drawCommand, 0, 53);
1021         switch (drawCommand) {
1022             case 0:
1023                 canvas->flush();
1024                 break;
1025             case 1:
1026                 canvas->save();
1027                 break;
1028             case 2: {
1029                 SkRect bounds;
1030                 fuzz->next(&bounds);
1031                 fuzz_paint(fuzz, &paint, depth - 1);
1032                 canvas->saveLayer(&bounds, &paint);
1033                 break;
1034             }
1035             case 3: {
1036                 SkRect bounds;
1037                 fuzz->next(&bounds);
1038                 canvas->saveLayer(&bounds, nullptr);
1039                 break;
1040             }
1041             case 4:
1042                 fuzz_paint(fuzz, &paint, depth - 1);
1043                 canvas->saveLayer(nullptr, &paint);
1044                 break;
1045             case 5:
1046                 canvas->saveLayer(nullptr, nullptr);
1047                 break;
1048             case 6: {
1049                 uint8_t alpha;
1050                 fuzz->next(&alpha);
1051                 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1052                 break;
1053             }
1054             case 7: {
1055                 SkRect bounds;
1056                 uint8_t alpha;
1057                 fuzz->next(&bounds, &alpha);
1058                 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1059                 break;
1060             }
1061             case 8: {
1062                 SkCanvas::SaveLayerRec saveLayerRec;
1063                 SkRect bounds;
1064                 if (make_fuzz_t<bool>(fuzz)) {
1065                     fuzz->next(&bounds);
1066                     saveLayerRec.fBounds = &bounds;
1067                 }
1068                 if (make_fuzz_t<bool>(fuzz)) {
1069                     fuzz_paint(fuzz, &paint, depth - 1);
1070                     saveLayerRec.fPaint = &paint;
1071                 }
1072                 sk_sp<SkImageFilter> imageFilter;
1073                 if (make_fuzz_t<bool>(fuzz)) {
1074                     imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1075                     saveLayerRec.fBackdrop = imageFilter.get();
1076                 }
1077                 // _DumpCanvas can't handle this.
1078                 // if (make_fuzz_t<bool>(fuzz)) {
1079                 //     saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1080                 // }
1081 
1082                 canvas->saveLayer(saveLayerRec);
1083                 break;
1084             }
1085             case 9:
1086                 canvas->restore();
1087                 break;
1088             case 10: {
1089                 int saveCount;
1090                 fuzz->next(&saveCount);
1091                 canvas->restoreToCount(saveCount);
1092                 break;
1093             }
1094             case 11: {
1095                 SkScalar x, y;
1096                 fuzz->next(&x, &y);
1097                 canvas->translate(x, y);
1098                 break;
1099             }
1100             case 12: {
1101                 SkScalar x, y;
1102                 fuzz->next(&x, &y);
1103                 canvas->scale(x, y);
1104                 break;
1105             }
1106             case 13: {
1107                 SkScalar v;
1108                 fuzz->next(&v);
1109                 canvas->rotate(v);
1110                 break;
1111             }
1112             case 14: {
1113                 SkScalar x, y, v;
1114                 fuzz->next(&x, &y, &v);
1115                 canvas->rotate(v, x, y);
1116                 break;
1117             }
1118             case 15: {
1119                 SkScalar x, y;
1120                 fuzz->next(&x, &y);
1121                 canvas->skew(x, y);
1122                 break;
1123             }
1124             case 16: {
1125                 SkMatrix mat;
1126                 FuzzNiceMatrix(fuzz, &mat);
1127                 canvas->concat(mat);
1128                 break;
1129             }
1130             case 17: {
1131                 SkMatrix mat;
1132                 FuzzNiceMatrix(fuzz, &mat);
1133                 canvas->setMatrix(mat);
1134                 break;
1135             }
1136             case 18:
1137                 canvas->resetMatrix();
1138                 break;
1139             case 19: {
1140                 SkRect r;
1141                 int op;
1142                 bool doAntiAlias;
1143                 fuzz->next(&r, &doAntiAlias);
1144                 fuzz->nextRange(&op, 0, 1);
1145                 r.sort();
1146                 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1147                 break;
1148             }
1149             case 20: {
1150                 SkRRect rr;
1151                 int op;
1152                 bool doAntiAlias;
1153                 FuzzNiceRRect(fuzz, &rr);
1154                 fuzz->next(&doAntiAlias);
1155                 fuzz->nextRange(&op, 0, 1);
1156                 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1157                 break;
1158             }
1159             case 21: {
1160                 SkPath path;
1161                 FuzzNicePath(fuzz, &path, 30);
1162                 int op;
1163                 bool doAntiAlias;
1164                 fuzz->next(&doAntiAlias);
1165                 fuzz->nextRange(&op, 0, 1);
1166                 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1167                 break;
1168             }
1169             case 22: {
1170                 SkRegion region;
1171                 int op;
1172                 fuzz->next(&region);
1173                 fuzz->nextRange(&op, 0, 1);
1174                 canvas->clipRegion(region, (SkClipOp)op);
1175                 break;
1176             }
1177             case 23:
1178                 fuzz_paint(fuzz, &paint, depth - 1);
1179                 canvas->drawPaint(paint);
1180                 break;
1181             case 24: {
1182                 fuzz_paint(fuzz, &paint, depth - 1);
1183                 SkCanvas::PointMode pointMode;
1184                 fuzz->nextRange(&pointMode,
1185                                 SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
1186                 size_t count;
1187                 constexpr int kMaxCount = 30;
1188                 fuzz->nextRange(&count, 0, kMaxCount);
1189                 SkPoint pts[kMaxCount];
1190                 fuzz->nextN(pts, count);
1191                 canvas->drawPoints(pointMode, count, pts, paint);
1192                 break;
1193             }
1194             case 25: {
1195                 fuzz_paint(fuzz, &paint, depth - 1);
1196                 SkRect r;
1197                 fuzz->next(&r);
1198                 if (!r.isFinite()) {
1199                     break;
1200                 }
1201                 canvas->drawRect(r, paint);
1202                 break;
1203             }
1204             case 26: {
1205                 fuzz_paint(fuzz, &paint, depth - 1);
1206                 SkRegion region;
1207                 fuzz->next(&region);
1208                 canvas->drawRegion(region, paint);
1209                 break;
1210             }
1211             case 27: {
1212                 fuzz_paint(fuzz, &paint, depth - 1);
1213                 SkRect r;
1214                 fuzz->next(&r);
1215                 if (!r.isFinite()) {
1216                     break;
1217                 }
1218                 canvas->drawOval(r, paint);
1219                 break;
1220             }
1221             case 28: break; // must have deleted this some time earlier
1222             case 29: {
1223                 fuzz_paint(fuzz, &paint, depth - 1);
1224                 SkRRect rr;
1225                 FuzzNiceRRect(fuzz, &rr);
1226                 canvas->drawRRect(rr, paint);
1227                 break;
1228             }
1229             case 30: {
1230                 fuzz_paint(fuzz, &paint, depth - 1);
1231                 SkRRect orr, irr;
1232                 FuzzNiceRRect(fuzz, &orr);
1233                 FuzzNiceRRect(fuzz, &irr);
1234                 if (orr.getBounds().contains(irr.getBounds())) {
1235                     canvas->drawDRRect(orr, irr, paint);
1236                 }
1237                 break;
1238             }
1239             case 31: {
1240                 fuzz_paint(fuzz, &paint, depth - 1);
1241                 SkRect r;
1242                 SkScalar start, sweep;
1243                 bool useCenter;
1244                 fuzz->next(&r, &start, &sweep, &useCenter);
1245                 canvas->drawArc(r, start, sweep, useCenter, paint);
1246                 break;
1247             }
1248             case 32: {
1249                 fuzz_paint(fuzz, &paint, depth - 1);
1250                 SkPath path;
1251                 FuzzNicePath(fuzz, &path, 60);
1252                 canvas->drawPath(path, paint);
1253                 break;
1254             }
1255             case 33: {
1256                 sk_sp<SkImage> img = make_fuzz_image(fuzz);
1257                 SkScalar left, top;
1258                 bool usePaint;
1259                 fuzz->next(&left, &top, &usePaint);
1260                 if (usePaint) {
1261                     fuzz_paint(fuzz, &paint, depth - 1);
1262                 }
1263                 canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
1264                 break;
1265             }
1266             case 34: {
1267                 auto img = make_fuzz_image(fuzz);
1268                 SkRect src, dst;
1269                 bool usePaint;
1270                 fuzz->next(&src, &dst, &usePaint);
1271                 if (usePaint) {
1272                     fuzz_paint(fuzz, &paint, depth - 1);
1273                 }
1274                 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr);
1275                 break;
1276             }
1277             case 35: {
1278                 auto img = make_fuzz_image(fuzz);
1279                 SkIRect src;
1280                 SkRect dst;
1281                 bool usePaint;
1282                 fuzz->next(&src, &dst, &usePaint);
1283                 if (usePaint) {
1284                     fuzz_paint(fuzz, &paint, depth - 1);
1285                 }
1286                 SkCanvas::SrcRectConstraint constraint =
1287                         make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1288                                                 : SkCanvas::kFast_SrcRectConstraint;
1289                 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1290                 break;
1291             }
1292             case 36: {
1293                 bool usePaint;
1294                 auto img = make_fuzz_image(fuzz);
1295                 SkRect dst;
1296                 fuzz->next(&dst, &usePaint);
1297                 if (usePaint) {
1298                     fuzz_paint(fuzz, &paint, depth - 1);
1299                 }
1300                 canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr);
1301                 break;
1302             }
1303             case 37: {
1304                 auto img = make_fuzz_image(fuzz);
1305                 SkIRect center;
1306                 SkRect dst;
1307                 bool usePaint;
1308                 fuzz->next(&usePaint);
1309                 if (usePaint) {
1310                     fuzz_paint(fuzz, &paint, depth - 1);
1311                 }
1312                 if (make_fuzz_t<bool>(fuzz)) {
1313                     fuzz->next(&center);
1314                 } else {  // Make valid center, see SkLatticeIter::Valid().
1315                     fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1316                     fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1317                     fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1318                     fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1319                 }
1320                 fuzz->next(&dst);
1321                 canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
1322                 break;
1323             }
1324             case 38: {
1325                 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
1326                 SkScalar left, top;
1327                 bool usePaint;
1328                 fuzz->next(&left, &top, &usePaint);
1329                 if (usePaint) {
1330                     fuzz_paint(fuzz, &paint, depth - 1);
1331                 }
1332                 canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
1333                 break;
1334             }
1335             case 39: {
1336                 SkBitmap bitmap = make_fuzz_bitmap(fuzz);
1337                 SkRect src, dst;
1338                 bool usePaint;
1339                 fuzz->next(&src, &dst, &usePaint);
1340                 if (usePaint) {
1341                     fuzz_paint(fuzz, &paint, depth - 1);
1342                 }
1343                 SkCanvas::SrcRectConstraint constraint =
1344                         make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1345                                                 : SkCanvas::kFast_SrcRectConstraint;
1346                 canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
1347                 break;
1348             }
1349             case 40: {
1350                 SkBitmap img = make_fuzz_bitmap(fuzz);
1351                 SkIRect src;
1352                 SkRect dst;
1353                 bool usePaint;
1354                 fuzz->next(&src, &dst, &usePaint);
1355                 if (usePaint) {
1356                     fuzz_paint(fuzz, &paint, depth - 1);
1357                 }
1358                 SkCanvas::SrcRectConstraint constraint =
1359                         make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1360                                                 : SkCanvas::kFast_SrcRectConstraint;
1361                 canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
1362                 break;
1363             }
1364             case 41: {
1365                 SkBitmap img = make_fuzz_bitmap(fuzz);
1366                 SkRect dst;
1367                 bool usePaint;
1368                 fuzz->next(&dst, &usePaint);
1369                 if (usePaint) {
1370                     fuzz_paint(fuzz, &paint, depth - 1);
1371                 }
1372                 SkCanvas::SrcRectConstraint constraint =
1373                         make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1374                                                 : SkCanvas::kFast_SrcRectConstraint;
1375                 canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1376                 break;
1377             }
1378             case 42: {
1379                 SkBitmap img = make_fuzz_bitmap(fuzz);
1380                 SkIRect center;
1381                 SkRect dst;
1382                 bool usePaint;
1383                 fuzz->next(&usePaint);
1384                 if (usePaint) {
1385                     fuzz_paint(fuzz, &paint, depth - 1);
1386                 }
1387                 if (make_fuzz_t<bool>(fuzz)) {
1388                     fuzz->next(&center);
1389                 } else {  // Make valid center, see SkLatticeIter::Valid().
1390                     if (img.width() == 0 || img.height() == 0) {
1391                         // bitmap may not have had its pixels initialized.
1392                         break;
1393                     }
1394                     fuzz->nextRange(&center.fLeft, 0, img.width() - 1);
1395                     fuzz->nextRange(&center.fTop, 0, img.height() - 1);
1396                     fuzz->nextRange(&center.fRight, center.fLeft + 1, img.width());
1397                     fuzz->nextRange(&center.fBottom, center.fTop + 1, img.height());
1398                 }
1399                 fuzz->next(&dst);
1400                 canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1401                 break;
1402             }
1403             case 43: {
1404                 SkBitmap img = make_fuzz_bitmap(fuzz);
1405                 bool usePaint;
1406                 SkRect dst;
1407                 fuzz->next(&usePaint, &dst);
1408                 if (usePaint) {
1409                     fuzz_paint(fuzz, &paint, depth - 1);
1410                 }
1411                 constexpr int kMax = 6;
1412                 int xDivs[kMax], yDivs[kMax];
1413                 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1414                 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1415                 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1416                 fuzz->nextN(xDivs, lattice.fXCount);
1417                 fuzz->nextN(yDivs, lattice.fYCount);
1418                 canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1419                 break;
1420             }
1421             case 44: {
1422                 auto img = make_fuzz_image(fuzz);
1423                 bool usePaint;
1424                 SkRect dst;
1425                 fuzz->next(&usePaint, &dst);
1426                 if (usePaint) {
1427                     fuzz_paint(fuzz, &paint, depth - 1);
1428                 }
1429                 constexpr int kMax = 6;
1430                 int xDivs[kMax], yDivs[kMax];
1431                 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1432                 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1433                 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1434                 fuzz->nextN(xDivs, lattice.fXCount);
1435                 fuzz->nextN(yDivs, lattice.fYCount);
1436                 canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1437                 break;
1438             }
1439             case 45: {
1440                 fuzz_paint(fuzz, &paint, depth - 1);
1441                 font = fuzz_font(fuzz);
1442                 SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
1443                 SkScalar x, y;
1444                 fuzz->next(&x, &y);
1445                 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
1446                 canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
1447                                        font, paint);
1448                 break;
1449             }
1450             case 46: {
1451                 // was drawPosText
1452                 break;
1453             }
1454             case 47: {
1455                 // was drawPosTextH
1456                 break;
1457             }
1458             case 48: {
1459                 // was drawtextonpath
1460                 break;
1461             }
1462             case 49: {
1463                 // was drawtextonpath
1464                 break;
1465             }
1466             case 50: {
1467                 // was drawTextRSXform
1468                 break;
1469             }
1470             case 51: {
1471                 sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
1472                 fuzz_paint(fuzz, &paint, depth - 1);
1473                 SkScalar x, y;
1474                 fuzz->next(&x, &y);
1475                 canvas->drawTextBlob(blob, x, y, paint);
1476                 break;
1477             }
1478             case 52: {
1479                 SkMatrix matrix;
1480                 bool usePaint, useMatrix;
1481                 fuzz->next(&usePaint, &useMatrix);
1482                 if (usePaint) {
1483                     fuzz_paint(fuzz, &paint, depth - 1);
1484                 }
1485                 if (useMatrix) {
1486                     FuzzNiceMatrix(fuzz, &matrix);
1487                 }
1488                 auto pic = make_fuzz_picture(fuzz, depth - 1);
1489                 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1490                                     usePaint ? &paint : nullptr);
1491                 break;
1492             }
1493             case 53: {
1494                 fuzz_paint(fuzz, &paint, depth - 1);
1495                 SkVertices::VertexMode vertexMode;
1496                 SkBlendMode blendMode;
1497                 fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1498                 fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
1499                 constexpr int kMaxCount = 100;
1500                 int vertexCount;
1501                 SkPoint vertices[kMaxCount];
1502                 SkPoint texs[kMaxCount];
1503                 SkColor colors[kMaxCount];
1504                 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1505                 fuzz->nextN(vertices, vertexCount);
1506                 bool useTexs, useColors;
1507                 fuzz->next(&useTexs, &useColors);
1508                 if (useTexs) {
1509                     fuzz->nextN(texs, vertexCount);
1510                 }
1511                 if (useColors) {
1512                     fuzz->nextN(colors, vertexCount);
1513                 }
1514                 int indexCount = 0;
1515                 uint16_t indices[kMaxCount * 2];
1516                 if (make_fuzz_t<bool>(fuzz)) {
1517                     fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1518                     for (int i = 0; i < indexCount; ++i) {
1519                         fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1520                     }
1521                 }
1522                 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1523                                                           useTexs ? texs : nullptr,
1524                                                           useColors ? colors : nullptr,
1525                                                           indexCount, indices),
1526                                      blendMode, paint);
1527                 break;
1528             }
1529             default:
1530                 SkASSERT(false);
1531                 break;
1532         }
1533     }
1534 }
1535 
make_fuzz_picture(Fuzz * fuzz,int depth)1536 static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1537     SkScalar w, h;
1538     fuzz->next(&w, &h);
1539     SkPictureRecorder pictureRecorder;
1540     fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1541     return pictureRecorder.finishRecordingAsPicture();
1542 }
1543 
DEF_FUZZ(NullCanvas,fuzz)1544 DEF_FUZZ(NullCanvas, fuzz) {
1545     fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1546 }
1547 
1548 constexpr SkISize kCanvasSize = {128, 160};
1549 
DEF_FUZZ(RasterN32Canvas,fuzz)1550 DEF_FUZZ(RasterN32Canvas, fuzz) {
1551     auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1552     if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
1553     fuzz_canvas(fuzz, surface->getCanvas());
1554 }
1555 
DEF_FUZZ(RasterN32CanvasViaSerialization,fuzz)1556 DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1557     SkPictureRecorder recorder;
1558     fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
1559                                               SkIntToScalar(kCanvasSize.height())));
1560     sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
1561     if (!pic) { fuzz->signalBug(); }
1562     sk_sp<SkData> data = pic->serialize();
1563     if (!data) { fuzz->signalBug(); }
1564     SkReadBuffer rb(data->data(), data->size());
1565     auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
1566     if (!deserialized) { fuzz->signalBug(); }
1567     auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
1568     SkASSERT(surface && surface->getCanvas());
1569     surface->getCanvas()->drawPicture(deserialized);
1570 }
1571 
DEF_FUZZ(ImageFilter,fuzz)1572 DEF_FUZZ(ImageFilter, fuzz) {
1573     auto fil = make_fuzz_imageFilter(fuzz, 20);
1574 
1575     SkPaint paint;
1576     paint.setImageFilter(fil);
1577     SkBitmap bitmap;
1578     SkCanvas canvas(bitmap);
1579     canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1580 }
1581 
1582 
1583 //SkRandom _rand;
1584 #define SK_ADD_RANDOM_BIT_FLIPS
1585 
DEF_FUZZ(SerializedImageFilter,fuzz)1586 DEF_FUZZ(SerializedImageFilter, fuzz) {
1587     SkBitmap bitmap;
1588     if (!bitmap.tryAllocN32Pixels(256, 256)) {
1589         SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
1590         return;
1591     }
1592 
1593     auto filter = make_fuzz_imageFilter(fuzz, 20);
1594     if (!filter) {
1595         return;
1596     }
1597     auto data = filter->serialize();
1598     const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1599     size_t len = data->size();
1600 #ifdef SK_ADD_RANDOM_BIT_FLIPS
1601     unsigned char* p = const_cast<unsigned char*>(ptr);
1602     for (size_t i = 0; i < len; ++i, ++p) {
1603         uint8_t j;
1604         fuzz->nextRange(&j, 1, 250);
1605         if (j == 1) { // 0.4% of the time, flip a bit or byte
1606             uint8_t k;
1607             fuzz->nextRange(&k, 1, 10);
1608             if (k == 1) { // Then 10% of the time, change a whole byte
1609                 uint8_t s;
1610                 fuzz->nextRange(&s, 0, 2);
1611                 switch(s) {
1612                 case 0:
1613                     *p ^= 0xFF; // Flip entire byte
1614                     break;
1615                 case 1:
1616                     *p = 0xFF; // Set all bits to 1
1617                     break;
1618                 case 2:
1619                     *p = 0x00; // Set all bits to 0
1620                     break;
1621                 }
1622             } else {
1623                 uint8_t s;
1624                 fuzz->nextRange(&s, 0, 7);
1625                 *p ^= (1 << 7);
1626             }
1627         }
1628     }
1629 #endif // SK_ADD_RANDOM_BIT_FLIPS
1630     auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1631 
1632     // uncomment below to write out a serialized image filter (to make corpus
1633     // for -t filter_fuzz)
1634     // SkString s("./serialized_filters/sf");
1635     // s.appendU32(_rand.nextU());
1636     // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1637     // sk_fwrite(data->bytes(), data->size(), file);
1638     // sk_fclose(file);
1639 
1640     SkPaint paint;
1641     paint.setImageFilter(deserializedFil);
1642 
1643     SkCanvas canvas(bitmap);
1644     canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
1645     canvas.restore();
1646 }
1647 
1648 #if SK_SUPPORT_GPU
1649 
dump_GPU_info(GrContext * context)1650 static void dump_GPU_info(GrContext* context) {
1651     const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
1652                                     ->glInterface();
1653     const GrGLubyte* output;
1654     GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1655     SkDebugf("GL_RENDERER %s\n", (const char*) output);
1656 
1657     GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1658     SkDebugf("GL_VENDOR %s\n", (const char*) output);
1659 
1660     GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1661     SkDebugf("GL_VERSION %s\n", (const char*) output);
1662 }
1663 
fuzz_ganesh(Fuzz * fuzz,GrContext * context)1664 static void fuzz_ganesh(Fuzz* fuzz, GrContext* context) {
1665     SkASSERT(context);
1666     auto surface = SkSurface::MakeRenderTarget(
1667             context,
1668             SkBudgeted::kNo,
1669             SkImageInfo::Make(kCanvasSize.width(), kCanvasSize.height(), kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1670     SkASSERT(surface && surface->getCanvas());
1671     fuzz_canvas(fuzz, surface->getCanvas());
1672 }
1673 
DEF_FUZZ(NativeGLCanvas,fuzz)1674 DEF_FUZZ(NativeGLCanvas, fuzz) {
1675     sk_gpu_test::GrContextFactory f;
1676     GrContext* context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
1677     if (!context) {
1678         context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
1679     }
1680     if (FLAGS_gpuInfo) {
1681         dump_GPU_info(context);
1682     }
1683     fuzz_ganesh(fuzz, context);
1684 }
1685 
DEF_FUZZ(MockGPUCanvas,fuzz)1686 DEF_FUZZ(MockGPUCanvas, fuzz) {
1687     sk_gpu_test::GrContextFactory f;
1688     fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
1689 }
1690 #endif
1691 
DEF_FUZZ(PDFCanvas,fuzz)1692 DEF_FUZZ(PDFCanvas, fuzz) {
1693     SkNullWStream stream;
1694     auto doc = SkPDF::MakeDocument(&stream);
1695     fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1696                                      SkIntToScalar(kCanvasSize.height())));
1697 }
1698 
1699 // not a "real" thing to fuzz, used to debug errors found while fuzzing.
DEF_FUZZ(_DumpCanvas,fuzz)1700 DEF_FUZZ(_DumpCanvas, fuzz) {
1701     DebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
1702     fuzz_canvas(fuzz, &debugCanvas);
1703     std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1704     UrlDataManager dataManager(SkString("data"));
1705     SkDynamicMemoryWStream stream;
1706     SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
1707     writer.beginObject(); // root
1708     debugCanvas.toJSON(writer, dataManager, debugCanvas.getSize(), nullCanvas.get());
1709     writer.endObject(); // root
1710     writer.flush();
1711     sk_sp<SkData> json = stream.detachAsData();
1712     fwrite(json->data(), json->size(), 1, stdout);
1713 }
1714