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