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