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