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