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