blob: 1a1a3ad7b04e25e9c24e505738516a740f3552dd [file] [log] [blame]
Hal Canary24ac42b2017-02-14 13:35:14 -05001/*
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"
Hal Canary24ac42b2017-02-14 13:35:14 -05009
10// CORE
11#include "SkCanvas.h"
12#include "SkColorFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050013#include "SkDebugCanvas.h"
14#include "SkDocument.h"
Hal Canary671e4422017-02-27 13:36:38 -050015#include "SkFontMgr.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050016#include "SkImageFilter.h"
17#include "SkMaskFilter.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050018#include "SkNullCanvas.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050019#include "SkPathEffect.h"
20#include "SkPictureRecorder.h"
21#include "SkRegion.h"
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050022#include "SkSurface.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050023#include "SkTypeface.h"
24
25// EFFECTS
Hal Canary27bece82017-03-07 16:23:20 -050026#include "SkColorMatrixFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050027#include "SkGaussianEdgeShader.h"
28#include "SkGradientShader.h"
Hal Canary27bece82017-03-07 16:23:20 -050029#include "SkHighContrastFilter.h"
30#include "SkLumaColorFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050031#include "SkPerlinNoiseShader.h"
Hal Canary27bece82017-03-07 16:23:20 -050032#include "SkTableColorFilter.h"
Hal Canary24ac42b2017-02-14 13:35:14 -050033
34// SRC
35#include "SkUtils.h"
36
Kevin Lubick1ac8fd22017-03-01 10:42:45 -050037// MISC
38
39#include <iostream>
40
Hal Canary24ac42b2017-02-14 13:35:14 -050041// TODO:
42// SkCanvas::drawTextBlob
43// SkCanvas::drawTextRSXform
Hal Canary24ac42b2017-02-14 13:35:14 -050044// SkImageFilter
45// SkMaskFilter
46// SkPathEffect
Hal Canary24ac42b2017-02-14 13:35:14 -050047
48template <typename T, void (SkPaint::*S)(T)>
49inline void fuzz_input(Fuzz* fuzz, SkPaint* paint) {
50 T value;
51 fuzz->next(&value);
52 (paint->*S)(value);
53}
54
55template <typename T, void (SkPaint::*S)(T)>
56inline void fuzz_enum_input(Fuzz* fuzz, SkPaint* paint, T rmin, T rmax) {
57 using U = skstd::underlying_type_t<T>;
58 U value;
59 fuzz->nextRange(&value, (U)rmin, (U)rmax);
60 (paint->*S)((T)value);
61}
62
63// be careful: `foo(make_bool(f), make_bool(f))` is undefined.
64static bool make_bool(Fuzz* fuzz) {
65 bool b;
66 fuzz->next(&b);
67 return b;
68}
69
Hal Canaryce540ea2017-03-06 08:30:44 -050070// We don't always want to test NaNs.
71static void fuzz_nice_float(Fuzz* fuzz, float* f) {
72 fuzz->next(f);
73 if (*f != *f || ::fabs(*f) > 1.0e35f) {
74 *f = 0.0f;
75 }
76}
Hal Canary24ac42b2017-02-14 13:35:14 -050077
Hal Canaryce540ea2017-03-06 08:30:44 -050078template <typename... Args>
79void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
80 fuzz_nice_float(fuzz, f);
81 fuzz_nice_float(fuzz, rest...);
82}
83
84static void fuzz_path(Fuzz* fuzz, SkPath* path, int maxOps) {
85 if (maxOps < 2) {
86 maxOps = 2;
87 }
Hal Canary24ac42b2017-02-14 13:35:14 -050088 uint8_t fillType;
89 fuzz->nextRange(&fillType, 0, (uint8_t)SkPath::kInverseEvenOdd_FillType);
90 path->setFillType((SkPath::FillType)fillType);
91 uint8_t numOps;
Hal Canaryce540ea2017-03-06 08:30:44 -050092 fuzz->nextRange(&numOps, 2, maxOps);
Hal Canary24ac42b2017-02-14 13:35:14 -050093 for (uint8_t i = 0; i < numOps; ++i) {
94 uint8_t op;
95 fuzz->nextRange(&op, 0, 6);
96 SkScalar a, b, c, d, e, f;
97 switch (op) {
98 case 0:
Hal Canaryce540ea2017-03-06 08:30:44 -050099 fuzz_nice_float(fuzz, &a, &b);
Hal Canary24ac42b2017-02-14 13:35:14 -0500100 path->moveTo(a, b);
101 break;
102 case 1:
Hal Canaryce540ea2017-03-06 08:30:44 -0500103 fuzz_nice_float(fuzz, &a, &b);
Hal Canary24ac42b2017-02-14 13:35:14 -0500104 path->lineTo(a, b);
105 break;
106 case 2:
Hal Canaryce540ea2017-03-06 08:30:44 -0500107 fuzz_nice_float(fuzz, &a, &b, &c, &d);
Hal Canary24ac42b2017-02-14 13:35:14 -0500108 path->quadTo(a, b, c, d);
109 break;
110 case 3:
Hal Canaryce540ea2017-03-06 08:30:44 -0500111 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
Hal Canary24ac42b2017-02-14 13:35:14 -0500112 path->conicTo(a, b, c, d, e);
113 break;
114 case 4:
Hal Canaryce540ea2017-03-06 08:30:44 -0500115 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500116 path->cubicTo(a, b, c, d, e, f);
117 break;
118 case 5:
Hal Canaryce540ea2017-03-06 08:30:44 -0500119 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
Hal Canary24ac42b2017-02-14 13:35:14 -0500120 path->arcTo(a, b, c, d, e);
121 break;
122 case 6:
123 path->close();
124 break;
125 default:
126 break;
127 }
128 }
129}
130
131static void fuzz_region(Fuzz* fuzz, SkRegion* region) {
132 uint8_t N;
133 fuzz->nextRange(&N, 0, 10);
134 for (uint8_t i = 0; i < N; ++i) {
135 SkIRect r;
136 uint8_t op;
137 fuzz->next(&r);
138 r.sort();
139 fuzz->nextRange(&op, 0, (uint8_t)SkRegion::kLastOp);
140 if (!region->op(r, (SkRegion::Op)op)) {
141 return;
142 }
143 }
144}
145
Hal Canaryb69c4b82017-03-08 11:02:40 -0500146template <>
147inline void Fuzz::next(SkShader::TileMode* m) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500148 using U = skstd::underlying_type_t<SkShader::TileMode>;
149 this->nextRange((U*)m, (U)0, (U)(SkShader::kTileModeCount - 1));
150}
151
Hal Canaryb69c4b82017-03-08 11:02:40 -0500152template <>
153inline void Fuzz::next(SkMatrix* m) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500154 constexpr int kArrayLength = 9;
155 SkScalar buffer[kArrayLength];
156 int matrixType;
157 this->nextRange(&matrixType, 0, 4);
158 switch (matrixType) {
159 case 0: // identity
160 *m = SkMatrix::I();
161 return;
162 case 1: // translate
163 this->nextRange(&buffer[0], -4000.0f, 4000.0f);
164 this->nextRange(&buffer[1], -4000.0f, 4000.0f);
165 *m = SkMatrix::MakeTrans(buffer[0], buffer[1]);
166 return;
167 case 2: // translate + scale
168 this->nextRange(&buffer[0], -400.0f, 400.0f);
169 this->nextRange(&buffer[1], -400.0f, 400.0f);
170 this->nextRange(&buffer[2], -4000.0f, 4000.0f);
171 this->nextRange(&buffer[3], -4000.0f, 4000.0f);
172 *m = SkMatrix::MakeScale(buffer[0], buffer[1]);
173 m->postTranslate(buffer[2], buffer[3]);
174 return;
175 case 3: // affine
176 this->nextN(buffer, 6);
177 m->setAffine(buffer);
178 return;
179 case 4: // perspective
180 this->nextN(buffer, kArrayLength);
181 m->set9(buffer);
182 return;
183 default:
184 return;
185 }
186}
187
Hal Canaryb69c4b82017-03-08 11:02:40 -0500188template <>
189inline void Fuzz::next(SkRRect* rr) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500190 SkRect r;
191 SkVector radii[4];
192 this->next(&r);
Hal Canary27bece82017-03-07 16:23:20 -0500193 r.sort();
194 for (SkVector& vec : radii) {
195 this->nextRange(&vec.fX, 0.0f, 1.0f);
196 vec.fX *= 0.5f * r.width();
197 this->nextRange(&vec.fY, 0.0f, 1.0f);
198 vec.fY *= 0.5f * r.height();
199 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500200 rr->setRectRadii(r, radii);
Hal Canary24ac42b2017-02-14 13:35:14 -0500201}
202
Hal Canaryb69c4b82017-03-08 11:02:40 -0500203template <>
204inline void Fuzz::next(SkBlendMode* mode) {
Hal Canary24ac42b2017-02-14 13:35:14 -0500205 using U = skstd::underlying_type_t<SkBlendMode>;
206 this->nextRange((U*)mode, (U)0, (U)SkBlendMode::kLastMode);
207}
208
209sk_sp<SkImage> MakeFuzzImage(Fuzz*);
Hal Canary671e4422017-02-27 13:36:38 -0500210
Hal Canary24ac42b2017-02-14 13:35:14 -0500211SkBitmap MakeFuzzBitmap(Fuzz*);
212
Hal Canary671e4422017-02-27 13:36:38 -0500213static sk_sp<SkPicture> make_picture(Fuzz*, int depth);
214
Hal Canary27bece82017-03-07 16:23:20 -0500215sk_sp<SkColorFilter> MakeColorFilter(Fuzz* fuzz, int depth = 3) {
216 if (depth <= 0) {
217 return nullptr;
218 }
219 int colorFilterType;
220 fuzz->nextRange(&colorFilterType, 0, 8);
221 switch (colorFilterType) {
222 case 0:
223 return nullptr;
224 case 1: {
225 SkColor color;
226 SkBlendMode mode;
227 fuzz->next(&color, &mode);
228 return SkColorFilter::MakeModeFilter(color, mode);
229 }
230 case 2: {
231 sk_sp<SkColorFilter> outer = MakeColorFilter(fuzz, depth - 1);
232 sk_sp<SkColorFilter> inner = MakeColorFilter(fuzz, depth - 1);
233 return SkColorFilter::MakeComposeFilter(std::move(outer), std::move(inner));
234 }
235 case 3: {
236 SkScalar array[20];
237 fuzz->nextN(array, SK_ARRAY_COUNT(array));
238 return SkColorFilter::MakeMatrixFilterRowMajor255(array);
239 }
240 case 4: {
241 SkColor mul, add;
242 fuzz->next(&mul, &add);
243 return SkColorMatrixFilter::MakeLightingFilter(mul, add);
244 }
245 case 5: {
246 bool grayscale;
247 int invertStyle;
248 float contrast;
249 fuzz->next(&grayscale);
250 fuzz->nextRange(&invertStyle, 0, 2);
251 fuzz->nextRange(&contrast, -1.0f, 1.0f);
252 return SkHighContrastFilter::Make(SkHighContrastConfig(
253 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
254 }
255 case 6:
256 return SkLumaColorFilter::Make();
257 case 7: {
258 uint8_t table[256];
259 fuzz->nextN(table, SK_ARRAY_COUNT(table));
260 return SkTableColorFilter::Make(table);
261 }
262 case 8: {
263 uint8_t tableA[256];
264 uint8_t tableR[256];
265 uint8_t tableG[256];
266 uint8_t tableB[256];
267 fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
268 fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
269 fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
270 fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
271 return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
272 }
273 }
274 return nullptr;
275}
Hal Canary24ac42b2017-02-14 13:35:14 -0500276
277void make_pos(Fuzz* fuzz, SkScalar* pos, int colorCount) {
278 SkScalar totalPos = 0;
279 for (int i = 0; i < colorCount; ++i) {
280 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
281 totalPos += pos[i];
282 }
283 totalPos = 1.0f / totalPos;
284 for (int i = 0; i < colorCount; ++i) {
285 pos[i] *= totalPos;
286 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500287 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
Hal Canary24ac42b2017-02-14 13:35:14 -0500288 pos[colorCount - 1] = 1.0f;
289}
290
291sk_sp<SkShader> MakeFuzzShader(Fuzz* fuzz, int depth) {
292 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
293 sk_sp<SkColorFilter> colorFilter(nullptr);
294 SkBitmap bitmap;
295 sk_sp<SkImage> img;
296 SkShader::TileMode tmX, tmY;
297 bool useMatrix;
298 SkColor color;
299 SkMatrix matrix;
300 SkBlendMode blendMode;
301 int shaderType;
302 if (depth <= 0) {
303 return nullptr;
304 }
Hal Canary671e4422017-02-27 13:36:38 -0500305 fuzz->nextRange(&shaderType, 0, 14);
Hal Canary24ac42b2017-02-14 13:35:14 -0500306 switch (shaderType) {
307 case 0:
308 return nullptr;
309 case 1:
310 return SkShader::MakeEmptyShader();
311 case 2:
312 fuzz->next(&color);
313 return SkShader::MakeColorShader(color);
314 case 3:
315 img = MakeFuzzImage(fuzz);
316 fuzz->next(&tmX, &tmY, &useMatrix);
317 if (useMatrix) {
318 fuzz->next(&matrix);
319 }
320 return img->makeShader(tmX, tmY, useMatrix ? &matrix : nullptr);
321 case 4:
322 bitmap = MakeFuzzBitmap(fuzz);
323 fuzz->next(&tmX, &tmY, &useMatrix);
324 if (useMatrix) {
325 fuzz->next(&matrix);
326 }
327 return SkShader::MakeBitmapShader(bitmap, tmX, tmY, useMatrix ? &matrix : nullptr);
328 case 5:
329 shader1 = MakeFuzzShader(fuzz, depth - 1); // limit recursion.
330 fuzz->next(&matrix);
331 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
332 case 6:
333 shader1 = MakeFuzzShader(fuzz, depth - 1); // limit recursion.
334 colorFilter = MakeColorFilter(fuzz);
335 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
336 case 7:
337 shader1 = MakeFuzzShader(fuzz, depth - 1); // limit recursion.
338 shader2 = MakeFuzzShader(fuzz, depth - 1);
339 fuzz->next(&blendMode);
340 return SkShader::MakeComposeShader(std::move(shader1), std::move(shader2), blendMode);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500341 case 8: {
342 auto pic = make_picture(fuzz, depth);
343 bool useTile;
344 SkRect tile;
345 fuzz->next(&tmX, &tmY, &useMatrix, &useTile);
346 if (useMatrix) {
347 fuzz->next(&matrix);
Hal Canary671e4422017-02-27 13:36:38 -0500348 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500349 if (useTile) {
350 fuzz->next(&tile);
351 }
352 return SkShader::MakePictureShader(std::move(pic), tmX, tmY,
353 useMatrix ? &matrix : nullptr,
354 useTile ? &tile : nullptr);
355 }
Hal Canary671e4422017-02-27 13:36:38 -0500356 // EFFECTS:
Hal Canary24ac42b2017-02-14 13:35:14 -0500357 case 9:
Hal Canary671e4422017-02-27 13:36:38 -0500358 return SkGaussianEdgeShader::Make();
Hal Canaryb69c4b82017-03-08 11:02:40 -0500359 case 10: {
360 constexpr int kMaxColors = 12;
361 SkPoint pts[2];
362 SkColor colors[kMaxColors];
363 SkScalar pos[kMaxColors];
364 int colorCount;
365 bool usePos;
366 fuzz->nextN(pts, 2);
367 fuzz->nextRange(&colorCount, 2, kMaxColors);
368 fuzz->nextN(colors, colorCount);
369 fuzz->next(&tmX, &useMatrix, &usePos);
370 if (useMatrix) {
371 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500372 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500373 if (usePos) {
374 make_pos(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500375 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500376 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
377 tmX, 0, useMatrix ? &matrix : nullptr);
378 }
379 case 11: {
380 constexpr int kMaxColors = 12;
381 SkPoint center;
382 SkScalar radius;
383 int colorCount;
384 bool usePos;
385 SkColor colors[kMaxColors];
386 SkScalar pos[kMaxColors];
387 fuzz->next(&tmX, &useMatrix, &usePos, &center, &radius);
388 fuzz->nextRange(&colorCount, 2, kMaxColors);
389 fuzz->nextN(colors, colorCount);
390 if (useMatrix) {
391 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500392 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500393 if (usePos) {
394 make_pos(fuzz, pos, colorCount);
Hal Canary24ac42b2017-02-14 13:35:14 -0500395 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500396 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
397 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
398 }
399 case 12: {
400 constexpr int kMaxColors = 12;
401 SkPoint start, end;
402 SkScalar startRadius, endRadius;
403 int colorCount;
404 bool usePos;
405 SkColor colors[kMaxColors];
406 SkScalar pos[kMaxColors];
407 fuzz->next(&tmX, &useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
408 fuzz->nextRange(&colorCount, 2, kMaxColors);
409 fuzz->nextN(colors, colorCount);
410 if (useMatrix) {
411 fuzz->next(&matrix);
Hal Canary24ac42b2017-02-14 13:35:14 -0500412 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500413 if (usePos) {
414 make_pos(fuzz, pos, colorCount);
415 }
416 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
417 usePos ? pos : nullptr, colorCount, tmX, 0,
418 useMatrix ? &matrix : nullptr);
419 }
420 case 13: {
421 constexpr int kMaxColors = 12;
422 SkScalar cx, cy;
423 int colorCount;
424 bool usePos;
425 SkColor colors[kMaxColors];
426 SkScalar pos[kMaxColors];
427 fuzz->next(&cx, &cy, &useMatrix, &usePos);
428 fuzz->nextRange(&colorCount, 2, kMaxColors);
429 fuzz->nextN(colors, colorCount);
430 if (useMatrix) {
431 fuzz->next(&matrix);
432 }
433 if (usePos) {
434 make_pos(fuzz, pos, colorCount);
435 }
436 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
437 0, useMatrix ? &matrix : nullptr);
438 }
439 case 14: {
440 SkScalar baseFrequencyX, baseFrequencyY, seed;
441 int numOctaves;
442 SkISize tileSize;
443 bool useTileSize, turbulence;
444 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
445 if (useTileSize) {
446 fuzz->next(&tileSize);
447 }
448 fuzz->nextRange(&numOctaves, 2, 7);
449 if (turbulence) {
450 return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
451 numOctaves, seed,
452 useTileSize ? &tileSize : nullptr);
453 } else {
454 return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
455 numOctaves, seed,
456 useTileSize ? &tileSize : nullptr);
457 }
458 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500459 default:
460 break;
461 }
Kevin Lubickedbeb8b2017-02-27 16:45:32 -0500462 return nullptr;
Hal Canary24ac42b2017-02-14 13:35:14 -0500463}
464
Hal Canary24ac42b2017-02-14 13:35:14 -0500465sk_sp<SkPathEffect> MakeFuzzPathEffect(Fuzz* fuzz) { return nullptr; /*TODO*/ }
466
467sk_sp<SkMaskFilter> MakeFuzzMaskFilter(Fuzz* fuzz) { return nullptr; /*TODO*/ }
468
Hal Canary671e4422017-02-27 13:36:38 -0500469sk_sp<SkTypeface> MakeFuzzTypeface(Fuzz* fuzz) {
470 if (make_bool(fuzz)) {
471 return nullptr;
472 }
473 auto fontMugger = SkFontMgr::RefDefault();
474 SkASSERT(fontMugger);
475 int familyCount = fontMugger->countFamilies();
476 int i, j;
477 fuzz->nextRange(&i, 0, familyCount - 1);
478 sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
479 int styleCount = family->count();
480 fuzz->nextRange(&j, 0, styleCount - 1);
481 return sk_sp<SkTypeface>(family->createTypeface(j));
482}
Hal Canary24ac42b2017-02-14 13:35:14 -0500483
484sk_sp<SkImageFilter> MakeFuzzImageFilter(Fuzz* fuzz) { return nullptr; /*TODO*/ }
485
486sk_sp<SkImage> MakeFuzzImage(Fuzz* fuzz) {
487 int w, h;
488 fuzz->nextRange(&w, 1, 1024);
489 fuzz->nextRange(&h, 1, 1024);
490 SkAutoTMalloc<SkPMColor> data(w * h);
491 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
492 int n = w * h;
493 for (int i = 0; i < n; ++i) {
494 SkColor c;
495 fuzz->next(&c);
496 data[i] = SkPreMultiplyColor(c);
497 }
498 (void)data.release();
Hal Canaryb69c4b82017-03-08 11:02:40 -0500499 return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
500 nullptr);
Hal Canary24ac42b2017-02-14 13:35:14 -0500501}
502
503SkBitmap MakeFuzzBitmap(Fuzz* fuzz) {
504 SkBitmap bitmap;
505 int w, h;
506 fuzz->nextRange(&w, 1, 1024);
507 fuzz->nextRange(&h, 1, 1024);
508 bitmap.allocN32Pixels(w, h);
509 SkAutoLockPixels autoLockPixels(bitmap);
510 for (int y = 0; y < h; ++y) {
511 for (int x = 0; x < w; ++x) {
512 SkColor c;
513 fuzz->next(&c);
514 *bitmap.getAddr32(x, y) = SkPreMultiplyColor(c);
515 }
516 }
517 return bitmap;
518}
519
Hal Canary24ac42b2017-02-14 13:35:14 -0500520void FuzzPaint(Fuzz* fuzz, SkPaint* paint, int depth) {
521 if (!fuzz || !paint || depth <= 0) {
522 return;
523 }
524
525 fuzz_input<bool, &SkPaint::setAntiAlias>(fuzz, paint);
526 fuzz_input<bool, &SkPaint::setDither>(fuzz, paint);
527 fuzz_input<SkColor, &SkPaint::setColor>(fuzz, paint);
528 fuzz_enum_input<SkBlendMode, &SkPaint::setBlendMode>(fuzz, paint, (SkBlendMode)0,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500529 SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -0500530 fuzz_enum_input<SkPaint::Hinting, &SkPaint::setHinting>(fuzz, paint, SkPaint::kNo_Hinting,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500531 SkPaint::kFull_Hinting);
Hal Canary24ac42b2017-02-14 13:35:14 -0500532 fuzz_enum_input<SkFilterQuality, &SkPaint::setFilterQuality>(
533 fuzz, paint, SkFilterQuality::kNone_SkFilterQuality,
534 SkFilterQuality::kLast_SkFilterQuality);
535 fuzz_enum_input<SkPaint::Style, &SkPaint::setStyle>(fuzz, paint, SkPaint::kFill_Style,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500536 SkPaint::kStrokeAndFill_Style);
Hal Canary24ac42b2017-02-14 13:35:14 -0500537 paint->setShader(MakeFuzzShader(fuzz, depth));
538 paint->setPathEffect(MakeFuzzPathEffect(fuzz));
539 paint->setMaskFilter(MakeFuzzMaskFilter(fuzz));
540 paint->setImageFilter(MakeFuzzImageFilter(fuzz));
541 paint->setColorFilter(MakeColorFilter(fuzz));
542
543 if (paint->getStyle() != SkPaint::kFill_Style) {
544 fuzz_input<SkScalar, &SkPaint::setStrokeWidth>(fuzz, paint);
545 fuzz_input<SkScalar, &SkPaint::setStrokeMiter>(fuzz, paint);
546 fuzz_enum_input<SkPaint::Cap, &SkPaint::setStrokeCap>(fuzz, paint, SkPaint::kButt_Cap,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500547 SkPaint::kLast_Cap);
Hal Canary24ac42b2017-02-14 13:35:14 -0500548 fuzz_enum_input<SkPaint::Join, &SkPaint::setStrokeJoin>(fuzz, paint, SkPaint::kMiter_Join,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500549 SkPaint::kLast_Join);
Hal Canary24ac42b2017-02-14 13:35:14 -0500550 }
551}
552
553void FuzzPaintText(Fuzz* fuzz, SkPaint* paint) {
554 paint->setTypeface(MakeFuzzTypeface(fuzz));
555 fuzz_input<SkScalar, &SkPaint::setTextSize>(fuzz, paint);
556 fuzz_input<SkScalar, &SkPaint::setTextScaleX>(fuzz, paint);
557 fuzz_input<SkScalar, &SkPaint::setTextSkewX>(fuzz, paint);
558 fuzz_input<bool, &SkPaint::setLinearText>(fuzz, paint);
559 fuzz_input<bool, &SkPaint::setSubpixelText>(fuzz, paint);
560 fuzz_input<bool, &SkPaint::setLCDRenderText>(fuzz, paint);
561 fuzz_input<bool, &SkPaint::setEmbeddedBitmapText>(fuzz, paint);
562 fuzz_input<bool, &SkPaint::setAutohinted>(fuzz, paint);
563 fuzz_input<bool, &SkPaint::setVerticalText>(fuzz, paint);
564 fuzz_input<bool, &SkPaint::setFakeBoldText>(fuzz, paint);
565 fuzz_input<bool, &SkPaint::setDevKernText>(fuzz, paint);
566 fuzz_enum_input<SkPaint::Align, &SkPaint::setTextAlign>(fuzz, paint, SkPaint::kLeft_Align,
Hal Canaryb69c4b82017-03-08 11:02:40 -0500567 SkPaint::kRight_Align);
Hal Canary671e4422017-02-27 13:36:38 -0500568 fuzz_enum_input<SkPaint::TextEncoding, &SkPaint::setTextEncoding>(
569 fuzz, paint, SkPaint::kUTF8_TextEncoding, SkPaint::kGlyphID_TextEncoding);
Hal Canary24ac42b2017-02-14 13:35:14 -0500570}
571
Hal Canary671e4422017-02-27 13:36:38 -0500572SkTDArray<uint8_t> fuzz_text(Fuzz* fuzz, const SkPaint& paint) {
573 SkTDArray<uint8_t> array;
574 if (SkPaint::kGlyphID_TextEncoding == paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500575 int glyphRange = paint.getTypeface() ? paint.getTypeface()->countGlyphs()
576 : SkTypeface::MakeDefault()->countGlyphs();
Hal Canary671e4422017-02-27 13:36:38 -0500577 constexpr int kMaxGlyphCount = 20;
578 int glyphCount;
579 fuzz->nextRange(&glyphCount, 0, kMaxGlyphCount);
580 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
581 for (int i = 0; i < glyphCount; ++i) {
582 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
583 }
584 return array;
585 }
586 static const SkUnichar ranges[][2] = {
587 {0x0020, 0x007F},
588 {0x00A1, 0x0250},
589 {0x0400, 0x0500},
590 };
591 int32_t count = 0;
Hal Canaryb69c4b82017-03-08 11:02:40 -0500592 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500593 count += (ranges[i][1] - ranges[i][0]);
594 }
595 constexpr int kMaxLength = 30;
596 SkUnichar buffer[kMaxLength];
597 int length;
598 fuzz->nextRange(&length, 1, kMaxLength);
599 for (int j = 0; j < length; ++j) {
600 int32_t value;
601 fuzz->nextRange(&value, 0, count - 1);
Hal Canaryb69c4b82017-03-08 11:02:40 -0500602 for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
Hal Canary671e4422017-02-27 13:36:38 -0500603 if (value + ranges[i][0] < ranges[i][1]) {
604 buffer[j] = value + ranges[i][0];
605 break;
606 } else {
607 value -= (ranges[i][1] - ranges[i][0]);
608 }
609 }
610 }
611 switch (paint.getTextEncoding()) {
Hal Canaryb69c4b82017-03-08 11:02:40 -0500612 case SkPaint::kUTF8_TextEncoding: {
613 size_t utf8len = 0;
614 for (int j = 0; j < length; ++j) {
615 utf8len += SkUTF8_FromUnichar(buffer[j], nullptr);
Hal Canary671e4422017-02-27 13:36:38 -0500616 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500617 char* ptr = (char*)array.append(utf8len);
618 for (int j = 0; j < length; ++j) {
619 ptr += SkUTF8_FromUnichar(buffer[j], ptr);
Hal Canary671e4422017-02-27 13:36:38 -0500620 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500621 } break;
622 case SkPaint::kUTF16_TextEncoding: {
623 size_t utf16len = 0;
624 for (int j = 0; j < length; ++j) {
625 utf16len += SkUTF16_FromUnichar(buffer[j]);
626 }
627 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
628 for (int j = 0; j < length; ++j) {
629 ptr += SkUTF16_FromUnichar(buffer[j], ptr);
630 }
631 } break;
Hal Canary671e4422017-02-27 13:36:38 -0500632 case SkPaint::kUTF32_TextEncoding:
633 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
Hal Canaryc1a70e22017-03-01 15:40:46 -0500634 break;
Hal Canary671e4422017-02-27 13:36:38 -0500635 default:
Hal Canaryb69c4b82017-03-08 11:02:40 -0500636 SkASSERT(false);
Hal Canary671e4422017-02-27 13:36:38 -0500637 }
638 return array;
639}
640
Hal Canary24ac42b2017-02-14 13:35:14 -0500641void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 4) {
642 if (!fuzz || !canvas || depth <= 0) {
643 return;
644 }
645 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
646 unsigned N;
647 fuzz->nextRange(&N, 0, 2000);
648 for (unsigned i = 0; i < N; ++i) {
649 if (fuzz->exhausted()) {
650 return;
651 }
652 SkPaint paint;
653 SkMatrix matrix;
654 unsigned drawCommand;
655 fuzz->nextRange(&drawCommand, 0, 54);
656 switch (drawCommand) {
657 case 0:
658 canvas->flush();
659 break;
660 case 1:
661 canvas->save();
662 break;
663 case 2: {
664 SkRect bounds;
665 fuzz->next(&bounds);
666 FuzzPaint(fuzz, &paint, depth);
667 canvas->saveLayer(&bounds, &paint);
668 break;
669 }
670 case 3: {
671 SkRect bounds;
672 fuzz->next(&bounds);
673 canvas->saveLayer(&bounds, nullptr);
674 break;
675 }
676 case 4:
677 FuzzPaint(fuzz, &paint, depth);
678 canvas->saveLayer(nullptr, &paint);
679 break;
680 case 5:
681 canvas->saveLayer(nullptr, nullptr);
682 break;
683 case 6: {
684 uint8_t alpha;
685 fuzz->next(&alpha);
686 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
687 break;
688 }
689 case 7: {
690 SkRect bounds;
691 uint8_t alpha;
692 fuzz->next(&bounds, &alpha);
693 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
694 break;
695 }
696 case 8: {
697 SkCanvas::SaveLayerRec saveLayerRec;
698 SkRect bounds;
699 if (make_bool(fuzz)) {
700 fuzz->next(&bounds);
701 saveLayerRec.fBounds = &bounds;
702 }
703 if (make_bool(fuzz)) {
704 FuzzPaint(fuzz, &paint, depth);
705 saveLayerRec.fPaint = &paint;
706 }
707 sk_sp<SkImageFilter> imageFilter;
708 if (make_bool(fuzz)) {
709 imageFilter = MakeFuzzImageFilter(fuzz);
710 saveLayerRec.fBackdrop = imageFilter.get();
711 }
712 if (make_bool(fuzz)) {
713 saveLayerRec.fSaveLayerFlags |= SkCanvas::kIsOpaque_SaveLayerFlag;
714 }
715 if (make_bool(fuzz)) {
716 saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
717 }
718 canvas->saveLayer(saveLayerRec);
719 break;
720 }
721 case 9:
722 canvas->restore();
723 break;
724 case 10: {
725 int saveCount;
726 fuzz->next(&saveCount);
727 canvas->restoreToCount(saveCount);
728 break;
729 }
730 case 11: {
731 SkScalar x, y;
732 fuzz->next(&x, &y);
733 canvas->translate(x, y);
734 break;
735 }
736 case 12: {
737 SkScalar x, y;
738 fuzz->next(&x, &y);
739 canvas->scale(x, y);
740 break;
741 }
742 case 13: {
743 SkScalar v;
744 fuzz->next(&v);
745 canvas->rotate(v);
746 break;
747 }
748 case 14: {
749 SkScalar x, y, v;
750 fuzz->next(&x, &y, &v);
751 canvas->rotate(v, x, y);
752 break;
753 }
754 case 15: {
755 SkScalar x, y;
756 fuzz->next(&x, &y);
757 canvas->skew(x, y);
758 break;
759 }
760 case 16: {
761 SkMatrix mat;
762 fuzz->next(&mat);
763 canvas->concat(mat);
764 break;
765 }
766 case 17: {
767 SkMatrix mat;
768 fuzz->next(&mat);
769 canvas->setMatrix(mat);
770 break;
771 }
772 case 18:
773 canvas->resetMatrix();
774 break;
775 case 19: {
776 SkRect r;
777 int op;
778 bool doAntiAlias;
779 fuzz->next(&r, &doAntiAlias);
780 fuzz->nextRange(&op, 0, 1);
781 r.sort();
782 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
783 break;
784 }
785 case 20: {
786 SkRRect rr;
787 int op;
788 bool doAntiAlias;
789 fuzz->next(&rr);
790 fuzz->next(&doAntiAlias);
791 fuzz->nextRange(&op, 0, 1);
792 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
793 break;
794 }
795 case 21: {
796 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -0500797 fuzz_path(fuzz, &path, 30);
Hal Canary24ac42b2017-02-14 13:35:14 -0500798 int op;
799 bool doAntiAlias;
800 fuzz->next(&doAntiAlias);
801 fuzz->nextRange(&op, 0, 1);
802 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
803 break;
804 }
805 case 22: {
806 SkRegion region;
807 fuzz_region(fuzz, &region);
808 int op;
809 fuzz->nextRange(&op, 0, 1);
810 canvas->clipRegion(region, (SkClipOp)op);
811 break;
812 }
813 case 23:
814 FuzzPaint(fuzz, &paint, depth);
815 canvas->drawPaint(paint);
816 break;
817 case 24: {
818 FuzzPaint(fuzz, &paint, depth);
819 uint8_t pointMode;
820 fuzz->nextRange(&pointMode, 0, 3);
821 size_t count;
822 constexpr int kMaxCount = 30;
823 fuzz->nextRange(&count, 0, kMaxCount);
824 SkPoint pts[kMaxCount];
825 fuzz->nextN(pts, count);
826 canvas->drawPoints((SkCanvas::PointMode)pointMode, count, pts, paint);
827 break;
828 }
829 case 25: {
830 FuzzPaint(fuzz, &paint, depth);
831 SkRect r;
832 fuzz->next(&r);
833 canvas->drawRect(r, paint);
834 break;
835 }
836 case 26: {
837 FuzzPaint(fuzz, &paint, depth);
838 SkRegion region;
839 fuzz_region(fuzz, &region);
840 canvas->drawRegion(region, paint);
841 break;
842 }
843 case 27: {
844 FuzzPaint(fuzz, &paint, depth);
845 SkRect r;
846 fuzz->next(&r);
847 canvas->drawOval(r, paint);
848 break;
849 }
850 case 29: {
851 FuzzPaint(fuzz, &paint, depth);
852 SkRRect rr;
853 fuzz->next(&rr);
854 canvas->drawRRect(rr, paint);
855 break;
856 }
857 case 30: {
858 FuzzPaint(fuzz, &paint, depth);
859 SkRRect orr, irr;
860 fuzz->next(&orr);
861 fuzz->next(&irr);
Hal Canary27bece82017-03-07 16:23:20 -0500862 if (orr.getBounds().contains(irr.getBounds())) {
863 canvas->drawDRRect(orr, irr, paint);
864 }
Hal Canary24ac42b2017-02-14 13:35:14 -0500865 break;
866 }
867 case 31: {
868 FuzzPaint(fuzz, &paint, depth);
869 SkRect r;
870 SkScalar start, sweep;
871 bool useCenter;
872 fuzz->next(&r, &start, &sweep, &useCenter);
873 canvas->drawArc(r, start, sweep, useCenter, paint);
874 break;
875 }
876 case 32: {
877 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -0500878 fuzz_path(fuzz, &path, 60);
Hal Canary24ac42b2017-02-14 13:35:14 -0500879 canvas->drawPath(path, paint);
880 break;
881 }
882 case 33: {
883 sk_sp<SkImage> img = MakeFuzzImage(fuzz);
884 SkScalar left, top;
885 bool usePaint;
886 fuzz->next(&left, &top, &usePaint);
887 if (usePaint) {
888 FuzzPaint(fuzz, &paint, depth);
889 }
890 canvas->drawImage(img.get(), left, top, usePaint ? &paint : nullptr);
891 break;
892 }
893 case 34: {
894 auto img = MakeFuzzImage(fuzz);
895 SkRect src, dst;
896 bool usePaint;
897 fuzz->next(&src, &dst, &usePaint);
898 if (usePaint) {
899 FuzzPaint(fuzz, &paint, depth);
900 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500901 SkCanvas::SrcRectConstraint constraint =
902 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
903 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500904 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
905 break;
906 }
907 case 35: {
908 auto img = MakeFuzzImage(fuzz);
909 SkIRect src;
910 SkRect dst;
911 bool usePaint;
912 fuzz->next(&src, &dst, &usePaint);
913 if (usePaint) {
914 FuzzPaint(fuzz, &paint, depth);
915 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500916 SkCanvas::SrcRectConstraint constraint =
917 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
918 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500919 canvas->drawImageRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
920 break;
921 }
922 case 36: {
923 bool usePaint;
924 auto img = MakeFuzzImage(fuzz);
925 SkRect dst;
926 fuzz->next(&dst, &usePaint);
927 if (usePaint) {
928 FuzzPaint(fuzz, &paint, depth);
929 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500930 SkCanvas::SrcRectConstraint constraint =
931 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
932 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500933 canvas->drawImageRect(img, dst, usePaint ? &paint : nullptr, constraint);
934 break;
935 }
936 case 37: {
937 auto img = MakeFuzzImage(fuzz);
938 SkIRect center;
939 SkRect dst;
940 bool usePaint;
941 fuzz->next(&center, &dst, &usePaint);
942 if (usePaint) {
943 FuzzPaint(fuzz, &paint, depth);
944 }
945 canvas->drawImageNine(img, center, dst, usePaint ? &paint : nullptr);
946 break;
947 }
948 case 38: {
949 SkBitmap bitmap = MakeFuzzBitmap(fuzz);
950 SkScalar left, top;
951 bool usePaint;
952 fuzz->next(&left, &top, &usePaint);
953 if (usePaint) {
954 FuzzPaint(fuzz, &paint, depth);
955 }
956 canvas->drawBitmap(bitmap, left, top, usePaint ? &paint : nullptr);
957 break;
958 }
959 case 39: {
960 SkBitmap bitmap = MakeFuzzBitmap(fuzz);
961 SkRect src, dst;
962 bool usePaint;
963 fuzz->next(&src, &dst, &usePaint);
964 if (usePaint) {
965 FuzzPaint(fuzz, &paint, depth);
966 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500967 SkCanvas::SrcRectConstraint constraint =
968 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
969 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500970 canvas->drawBitmapRect(bitmap, src, dst, usePaint ? &paint : nullptr, constraint);
971 break;
972 }
973 case 40: {
974 SkBitmap img = MakeFuzzBitmap(fuzz);
975 SkIRect src;
976 SkRect dst;
977 bool usePaint;
978 fuzz->next(&src, &dst, &usePaint);
979 if (usePaint) {
980 FuzzPaint(fuzz, &paint, depth);
981 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500982 SkCanvas::SrcRectConstraint constraint =
983 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
984 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500985 canvas->drawBitmapRect(img, src, dst, usePaint ? &paint : nullptr, constraint);
986 break;
987 }
988 case 41: {
989 SkBitmap img = MakeFuzzBitmap(fuzz);
990 SkRect dst;
991 bool usePaint;
992 fuzz->next(&dst, &usePaint);
993 if (usePaint) {
994 FuzzPaint(fuzz, &paint, depth);
995 }
Hal Canaryb69c4b82017-03-08 11:02:40 -0500996 SkCanvas::SrcRectConstraint constraint =
997 make_bool(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
998 : SkCanvas::kFast_SrcRectConstraint;
Hal Canary24ac42b2017-02-14 13:35:14 -0500999 canvas->drawBitmapRect(img, dst, usePaint ? &paint : nullptr, constraint);
1000 break;
1001 }
1002 case 42: {
1003 SkBitmap img = MakeFuzzBitmap(fuzz);
1004 SkIRect center;
1005 SkRect dst;
1006 bool usePaint;
1007 fuzz->next(&center, &dst, &usePaint);
1008 if (usePaint) {
1009 FuzzPaint(fuzz, &paint, depth);
1010 }
1011 canvas->drawBitmapNine(img, center, dst, usePaint ? &paint : nullptr);
1012 break;
1013 }
1014 case 43: {
1015 SkBitmap img = MakeFuzzBitmap(fuzz);
1016 bool usePaint;
1017 SkRect dst;
1018 fuzz->next(&usePaint, &dst);
1019 if (usePaint) {
1020 FuzzPaint(fuzz, &paint, depth);
1021 }
1022 constexpr int kMax = 6;
1023 int xDivs[kMax], yDivs[kMax];
1024 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr};
1025 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1026 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1027 fuzz->nextN(xDivs, lattice.fXCount);
1028 fuzz->nextN(yDivs, lattice.fYCount);
1029 canvas->drawBitmapLattice(img, lattice, dst, usePaint ? &paint : nullptr);
1030 break;
1031 }
1032 case 44: {
1033 auto img = MakeFuzzImage(fuzz);
1034 bool usePaint;
1035 SkRect dst;
1036 fuzz->next(&usePaint, &dst);
1037 if (usePaint) {
1038 FuzzPaint(fuzz, &paint, depth);
1039 }
1040 constexpr int kMax = 6;
1041 int xDivs[kMax], yDivs[kMax];
1042 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr};
1043 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1044 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1045 fuzz->nextN(xDivs, lattice.fXCount);
1046 fuzz->nextN(yDivs, lattice.fYCount);
1047 canvas->drawImageLattice(img.get(), lattice, dst, usePaint ? &paint : nullptr);
1048 break;
1049 }
1050 case 45: {
Hal Canary671e4422017-02-27 13:36:38 -05001051 FuzzPaint(fuzz, &paint, depth);
Hal Canary24ac42b2017-02-14 13:35:14 -05001052 FuzzPaintText(fuzz, &paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001053 SkScalar x, y;
1054 fuzz->next(&x, &y);
Hal Canary671e4422017-02-27 13:36:38 -05001055 SkTDArray<uint8_t> text = fuzz_text(fuzz, paint);
1056 canvas->drawText(text.begin(), SkToSizeT(text.count()), x, y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001057 break;
1058 }
1059 case 46: {
Hal Canary671e4422017-02-27 13:36:38 -05001060 FuzzPaint(fuzz, &paint, depth);
Hal Canary24ac42b2017-02-14 13:35:14 -05001061 FuzzPaintText(fuzz, &paint);
Hal Canary671e4422017-02-27 13:36:38 -05001062 SkTDArray<uint8_t> text = fuzz_text(fuzz, paint);
1063 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001064 if (glyphCount < 1) {
1065 break;
1066 }
1067 SkAutoTMalloc<SkPoint> pos(glyphCount);
1068 SkAutoTMalloc<SkScalar> widths(glyphCount);
Hal Canary671e4422017-02-27 13:36:38 -05001069 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001070 pos[0] = {0, 0};
1071 for (int i = 1; i < glyphCount; ++i) {
1072 float y;
Hal Canaryb69c4b82017-03-08 11:02:40 -05001073 fuzz->nextRange(&y, -0.5f * paint.getTextSize(), 0.5f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001074 pos[i] = {pos[i - 1].x() + widths[i - 1], y};
1075 }
Hal Canary671e4422017-02-27 13:36:38 -05001076 canvas->drawPosText(text.begin(), SkToSizeT(text.count()), pos.get(), paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001077 break;
1078 }
1079 case 47: {
Hal Canary671e4422017-02-27 13:36:38 -05001080 FuzzPaint(fuzz, &paint, depth);
Hal Canary24ac42b2017-02-14 13:35:14 -05001081 FuzzPaintText(fuzz, &paint);
Hal Canary671e4422017-02-27 13:36:38 -05001082 SkTDArray<uint8_t> text = fuzz_text(fuzz, paint);
1083 int glyphCount = paint.countText(text.begin(), SkToSizeT(text.count()));
Hal Canary24ac42b2017-02-14 13:35:14 -05001084 SkAutoTMalloc<SkScalar> widths(glyphCount);
1085 if (glyphCount < 1) {
1086 break;
1087 }
Hal Canary671e4422017-02-27 13:36:38 -05001088 paint.getTextWidths(text.begin(), SkToSizeT(text.count()), widths.get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001089 SkScalar x = widths[0];
1090 for (int i = 0; i < glyphCount; ++i) {
1091 SkTSwap(x, widths[i]);
1092 x += widths[i];
1093 SkScalar offset;
1094 fuzz->nextRange(&offset, -0.125f * paint.getTextSize(),
Hal Canaryb69c4b82017-03-08 11:02:40 -05001095 0.125f * paint.getTextSize());
Hal Canary24ac42b2017-02-14 13:35:14 -05001096 widths[i] += offset;
1097 }
1098 SkScalar y;
1099 fuzz->next(&y);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001100 canvas->drawPosTextH(text.begin(), SkToSizeT(text.count()), widths.get(), y, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001101 break;
1102 }
1103 case 48: {
Hal Canary671e4422017-02-27 13:36:38 -05001104 FuzzPaint(fuzz, &paint, depth);
Hal Canary24ac42b2017-02-14 13:35:14 -05001105 FuzzPaintText(fuzz, &paint);
Hal Canary671e4422017-02-27 13:36:38 -05001106 SkTDArray<uint8_t> text = fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001107 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001108 fuzz_path(fuzz, &path, 20);
Hal Canary24ac42b2017-02-14 13:35:14 -05001109 SkScalar hOffset, vOffset;
1110 fuzz->next(&hOffset, &vOffset);
Hal Canaryb69c4b82017-03-08 11:02:40 -05001111 canvas->drawTextOnPathHV(text.begin(), SkToSizeT(text.count()), path, hOffset,
1112 vOffset, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001113 break;
1114 }
1115 case 49: {
1116 SkMatrix matrix;
1117 bool useMatrix = make_bool(fuzz);
1118 if (useMatrix) {
1119 fuzz->next(&matrix);
1120 }
Hal Canary671e4422017-02-27 13:36:38 -05001121 FuzzPaint(fuzz, &paint, depth);
Hal Canary24ac42b2017-02-14 13:35:14 -05001122 FuzzPaintText(fuzz, &paint);
Hal Canary671e4422017-02-27 13:36:38 -05001123 SkTDArray<uint8_t> text = fuzz_text(fuzz, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001124 SkPath path;
Hal Canaryce540ea2017-03-06 08:30:44 -05001125 fuzz_path(fuzz, &path, 20);
Hal Canary671e4422017-02-27 13:36:38 -05001126 canvas->drawTextOnPath(text.begin(), SkToSizeT(text.count()), path,
Hal Canary24ac42b2017-02-14 13:35:14 -05001127 useMatrix ? &matrix : nullptr, paint);
1128 break;
1129 }
1130 case 50: {
1131 // canvas->drawTextRSXform(...); // TODO
1132 break;
1133 }
1134 case 51: {
1135 // canvas->drawTextBlob(...); // TODO
1136 break;
1137 }
1138 case 52: {
1139 bool usePaint, useMatrix;
1140 fuzz->next(&usePaint, &useMatrix);
1141 if (usePaint) {
1142 FuzzPaint(fuzz, &paint, depth);
1143 }
1144 if (useMatrix) {
1145 fuzz->next(&matrix);
1146 }
1147 auto pic = make_picture(fuzz, depth);
1148 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1149 usePaint ? &paint : nullptr);
1150 break;
1151 }
1152 case 53: {
1153 FuzzPaint(fuzz, &paint, depth);
1154 SkCanvas::VertexMode vertexMode;
1155 SkBlendMode mode;
1156 uint8_t vm, bm;
Hal Canary3a97d272017-03-07 15:06:29 -05001157 fuzz->nextRange(&vm, 0, (uint8_t)SkCanvas::kTriangleFan_VertexMode);
1158 fuzz->nextRange(&bm, 0, (uint8_t)SkBlendMode::kLastMode);
Hal Canary24ac42b2017-02-14 13:35:14 -05001159 vertexMode = (SkCanvas::VertexMode)vm;
1160 mode = (SkBlendMode)bm;
1161 constexpr int kMaxCount = 100;
1162 int vertexCount;
1163 SkPoint vertices[kMaxCount];
1164 SkPoint texs[kMaxCount];
1165 SkColor colors[kMaxCount];
Hal Canary24ac42b2017-02-14 13:35:14 -05001166 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1167 fuzz->nextN(vertices, vertexCount);
1168 bool useTexs, useColors;
1169 fuzz->next(&useTexs, &useColors);
1170 if (useTexs) {
1171 fuzz->nextN(texs, vertexCount);
1172 }
1173 if (useColors) {
1174 fuzz->nextN(colors, vertexCount);
1175 }
1176 int indexCount = 0;
Hal Canary68b9b572017-03-02 15:27:23 -05001177 uint16_t indices[kMaxCount * 2];
Hal Canary24ac42b2017-02-14 13:35:14 -05001178 if (make_bool(fuzz)) {
Hal Canary68b9b572017-03-02 15:27:23 -05001179 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1180 for (int i = 0; i < indexCount; ++i) {
1181 fuzz->nextRange(&indices[i], 0, vertexCount - 1);
1182 }
Hal Canary24ac42b2017-02-14 13:35:14 -05001183 }
Hal Canaryb69c4b82017-03-08 11:02:40 -05001184 canvas->drawVertices(vertexMode, vertexCount, vertices, useTexs ? texs : nullptr,
1185 useColors ? colors : nullptr, mode,
1186 indexCount > 0 ? indices : nullptr, indexCount, paint);
Hal Canary24ac42b2017-02-14 13:35:14 -05001187 break;
1188 }
1189 case 54: {
1190 // canvas->drawVertices(...);
1191 // TODO
1192 break;
1193 }
1194 default:
1195 break;
1196 }
1197 }
1198}
1199
1200static sk_sp<SkPicture> make_picture(Fuzz* fuzz, int depth) {
1201 SkScalar w, h;
1202 fuzz->next(&w, &h);
1203 SkPictureRecorder pictureRecorder;
1204 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1205 return pictureRecorder.finishRecordingAsPicture();
1206}
1207
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001208DEF_FUZZ(NullCanvas, fuzz) {
1209 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
Hal Canary24ac42b2017-02-14 13:35:14 -05001210}
1211
Kevin Lubick1ac8fd22017-03-01 10:42:45 -05001212DEF_FUZZ(RasterN32Canvas, fuzz) {
1213 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1214 auto surface = SkSurface::MakeRasterN32Premul(612, 792);
1215 SkASSERT(surface && surface->getCanvas());
1216 fuzz_canvas(fuzz, surface->getCanvas());
1217}
1218
1219DEF_FUZZ(PDFCanvas, fuzz) {
1220 struct final : public SkWStream {
1221 bool write(const void*, size_t n) override { fN += n; return true; }
1222 size_t bytesWritten() const override { return fN; }
1223 size_t fN = 0;
1224 } stream;
1225 auto doc = SkDocument::MakePDF(&stream);
1226 fuzz_canvas(fuzz, doc->beginPage(612.0f, 792.0f));
1227}
1228
1229// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1230DEF_FUZZ(_DumpCanvas, fuzz) {
1231 SkDebugCanvas debugCanvas(612, 792);
1232 fuzz_canvas(fuzz, &debugCanvas);
1233 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1234 UrlDataManager dataManager(SkString("data"));
1235 Json::Value json = debugCanvas.toJSON(dataManager, debugCanvas.getSize(), nullCanvas.get());
1236 Json::StyledStreamWriter(" ").write(std::cout, json);
1237}