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