Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
FuzzCanvas.cpp
Go to the documentation of this file.
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/Fuzz.h"
9#include "fuzz/FuzzCommon.h"
43#include "src/base/SkUTF.h"
44#include "src/core/SkFontPriv.h"
45#include "src/core/SkOSFile.h"
54
55#if defined(SK_GANESH)
59#endif
60
61#ifdef SK_GL
65#endif
66
67#include <iostream>
68#include <utility>
69
70using namespace skia_private;
71
72static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
73
74// TODO:
75// SkTextBlob with Unicode
76// SkImage: more types
77
78// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
79// In fact, all make_fuzz_foo() functions have this potential problem.
80// Use sequence points!
81template <typename T>
82inline T make_fuzz_t(Fuzz* fuzz) {
83 T t;
84 fuzz->next(&t);
85 return t;
86}
87
89
90static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
91
93 if (depth <= 0) {
94 return nullptr;
95 }
96 int colorFilterType;
97 fuzz->nextRange(&colorFilterType, 0, 8);
98 switch (colorFilterType) {
99 case 0:
100 return nullptr;
101 case 1: {
103 SkBlendMode mode;
104 fuzz->next(&color);
105 fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
106 return SkColorFilters::Blend(color, mode);
107 }
108 case 2: {
109 sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
110 if (!outer) {
111 return nullptr;
112 }
113 sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
114 // makeComposed should be able to handle nullptr.
115 return outer->makeComposed(std::move(inner));
116 }
117 case 3: {
118 float array[20];
119 fuzz->nextN(array, std::size(array));
120 return SkColorFilters::Matrix(array);
121 }
122 case 4: {
123 SkColor mul, add;
124 fuzz->next(&mul, &add);
125 return SkColorFilters::Lighting(mul, add);
126 }
127 case 5: {
128 bool grayscale;
129 int invertStyle;
130 float contrast;
131 fuzz->next(&grayscale);
132 fuzz->nextRange(&invertStyle, 0, 2);
133 fuzz->nextRange(&contrast, -1.0f, 1.0f);
135 grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
136 }
137 case 6:
139 case 7: {
140 uint8_t table[256];
141 fuzz->nextN(table, std::size(table));
143 }
144 case 8: {
145 uint8_t tableA[256];
146 uint8_t tableR[256];
147 uint8_t tableG[256];
148 uint8_t tableB[256];
149 fuzz->nextN(tableA, std::size(tableA));
150 fuzz->nextN(tableR, std::size(tableR));
151 fuzz->nextN(tableG, std::size(tableG));
152 fuzz->nextN(tableB, std::size(tableB));
153 return SkColorFilters::TableARGB(tableA, tableR, tableG, tableB);
154 }
155 default:
156 SkASSERT(false);
157 break;
158 }
159 return nullptr;
160}
161
162static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
163 SkScalar totalPos = 0;
164 for (int i = 0; i < colorCount; ++i) {
165 fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
166 totalPos += pos[i];
167 }
168 totalPos = 1.0f / totalPos;
169 for (int i = 0; i < colorCount; ++i) {
170 pos[i] *= totalPos;
171 }
172 // SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
173 pos[colorCount - 1] = 1.0f;
174}
175
176static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
177 sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
178 sk_sp<SkColorFilter> colorFilter(nullptr);
180 sk_sp<SkImage> img;
181 SkTileMode tmX, tmY;
182 bool useMatrix;
184 SkMatrix matrix;
185 SkBlendMode blendMode;
186 int shaderType;
187 if (depth <= 0) {
188 return nullptr;
189 }
190 fuzz->nextRange(&shaderType, 0, 14);
191 switch (shaderType) {
192 case 0:
193 return nullptr;
194 case 1:
195 return SkShaders::Empty();
196 case 2:
197 fuzz->next(&color);
198 return SkShaders::Color(color);
199 case 3:
200 img = make_fuzz_image(fuzz);
203 fuzz->next(&useMatrix);
204 if (useMatrix) {
205 FuzzNiceMatrix(fuzz, &matrix);
206 }
207 return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
208 case 5:
209 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
210 FuzzNiceMatrix(fuzz, &matrix);
211 return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
212 case 6:
213 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
214 colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
215 return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
216 case 7:
217 shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
218 shader2 = make_fuzz_shader(fuzz, depth - 1);
219 fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
220 return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
221 case 8: {
222 auto pic = make_fuzz_picture(fuzz, depth - 1);
223 bool useTile;
224 SkRect tile;
227 fuzz->next(&useMatrix, &useTile);
228 if (useMatrix) {
229 FuzzNiceMatrix(fuzz, &matrix);
230 }
231 if (useTile) {
232 fuzz->next(&tile);
233 }
234 return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
235 useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
236 }
237 // EFFECTS:
238 case 9:
239 // Deprecated SkGaussianEdgeShader
240 return nullptr;
241 case 10: {
242 constexpr int kMaxColors = 12;
243 SkPoint pts[2];
244 SkColor colors[kMaxColors];
245 SkScalar pos[kMaxColors];
246 int colorCount;
247 bool usePos;
248 fuzz->nextN(pts, 2);
249 fuzz->nextRange(&colorCount, 2, kMaxColors);
250 fuzz->nextN(colors, colorCount);
252 fuzz->next(&useMatrix, &usePos);
253 if (useMatrix) {
254 FuzzNiceMatrix(fuzz, &matrix);
255 }
256 if (usePos) {
257 fuzz_gradient_stops(fuzz, pos, colorCount);
258 }
259 return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
260 tmX, 0, useMatrix ? &matrix : nullptr);
261 }
262 case 11: {
263 constexpr int kMaxColors = 12;
265 SkScalar radius;
266 int colorCount;
267 bool usePos;
268 SkColor colors[kMaxColors];
269 SkScalar pos[kMaxColors];
271 fuzz->next(&useMatrix, &usePos, &center, &radius);
272 fuzz->nextRange(&colorCount, 2, kMaxColors);
273 fuzz->nextN(colors, colorCount);
274 if (useMatrix) {
275 FuzzNiceMatrix(fuzz, &matrix);
276 }
277 if (usePos) {
278 fuzz_gradient_stops(fuzz, pos, colorCount);
279 }
280 return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
281 colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
282 }
283 case 12: {
284 constexpr int kMaxColors = 12;
286 SkScalar startRadius, endRadius;
287 int colorCount;
288 bool usePos;
289 SkColor colors[kMaxColors];
290 SkScalar pos[kMaxColors];
292 fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
293 fuzz->nextRange(&colorCount, 2, kMaxColors);
294 fuzz->nextN(colors, colorCount);
295 if (useMatrix) {
296 FuzzNiceMatrix(fuzz, &matrix);
297 }
298 if (usePos) {
299 fuzz_gradient_stops(fuzz, pos, colorCount);
300 }
301 return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
302 usePos ? pos : nullptr, colorCount, tmX, 0,
303 useMatrix ? &matrix : nullptr);
304 }
305 case 13: {
306 constexpr int kMaxColors = 12;
307 SkScalar cx, cy;
308 int colorCount;
309 bool usePos;
310 SkColor colors[kMaxColors];
311 SkScalar pos[kMaxColors];
312 fuzz->next(&cx, &cy, &useMatrix, &usePos);
313 fuzz->nextRange(&colorCount, 2, kMaxColors);
314 fuzz->nextN(colors, colorCount);
315 if (useMatrix) {
316 FuzzNiceMatrix(fuzz, &matrix);
317 }
318 if (usePos) {
319 fuzz_gradient_stops(fuzz, pos, colorCount);
320 }
321 return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
322 0, useMatrix ? &matrix : nullptr);
323 }
324 case 14: {
325 SkScalar baseFrequencyX, baseFrequencyY, seed;
326 int numOctaves;
327 SkISize tileSize;
328 bool useTileSize, turbulence;
329 fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
330 if (useTileSize) {
331 fuzz->next(&tileSize);
332 }
333 fuzz->nextRange(&numOctaves, 2, 7);
334 if (turbulence) {
335 return SkShaders::MakeTurbulence(baseFrequencyX,
336 baseFrequencyY,
337 numOctaves,
338 seed,
339 useTileSize ? &tileSize : nullptr);
340 } else {
341 return SkShaders::MakeFractalNoise(baseFrequencyX,
342 baseFrequencyY,
343 numOctaves,
344 seed,
345 useTileSize ? &tileSize : nullptr);
346 }
347 }
348 default:
349 SkASSERT(false);
350 break;
351 }
352 return nullptr;
353}
354
356 if (depth <= 0) {
357 return nullptr;
358 }
359 uint8_t pathEffectType;
360 fuzz->nextRange(&pathEffectType, 0, 8);
361 switch (pathEffectType) {
362 case 0: {
363 return nullptr;
364 }
365 case 1: {
366 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
367 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
368 return SkPathEffect::MakeSum(std::move(first), std::move(second));
369 }
370 case 2: {
371 sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
372 sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
373 return SkPathEffect::MakeCompose(std::move(first), std::move(second));
374 }
375 case 3: {
376 SkPath path;
377 FuzzNicePath(fuzz, &path, 20);
378 SkScalar advance, phase;
379 fuzz->next(&advance, &phase);
382 return SkPath1DPathEffect::Make(path, advance, phase, style);
383 }
384 case 4: {
386 SkMatrix matrix;
387 fuzz->next(&width);
388 FuzzNiceMatrix(fuzz, &matrix);
389 return SkLine2DPathEffect::Make(width, matrix);
390 }
391 case 5: {
392 SkPath path;
393 FuzzNicePath(fuzz, &path, 20);
394 SkMatrix matrix;
395 FuzzNiceMatrix(fuzz, &matrix);
396 return SkPath2DPathEffect::Make(matrix, path);
397 }
398 case 6: {
399 SkScalar radius;
400 fuzz->next(&radius);
401 return SkCornerPathEffect::Make(radius);
402 }
403 case 7: {
404 SkScalar phase;
405 fuzz->next(&phase);
406 SkScalar intervals[20];
407 int count;
408 fuzz->nextRange(&count, 0, (int)std::size(intervals));
409 fuzz->nextN(intervals, count);
410 return SkDashPathEffect::Make(intervals, count, phase);
411 }
412 case 8: {
413 SkScalar segLength, dev;
414 uint32_t seed;
415 fuzz->next(&segLength, &dev, &seed);
416 return SkDiscretePathEffect::Make(segLength, dev, seed);
417 }
418 default:
419 SkASSERT(false);
420 return nullptr;
421 }
422}
423
425 int maskfilterType;
426 fuzz->nextRange(&maskfilterType, 0, 1);
427 switch (maskfilterType) {
428 case 0:
429 return nullptr;
430 case 1: {
431 SkBlurStyle blurStyle;
432 fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
433 SkScalar sigma;
434 fuzz->next(&sigma);
435 bool respectCTM;
436 fuzz->next(&respectCTM);
437 return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
438 }
439 default:
440 SkASSERT(false);
441 return nullptr;
442 }
443}
444
446 if (make_fuzz_t<bool>(fuzz)) {
447 return nullptr;
448 }
450 int familyCount = mgr->countFamilies();
451 int i, j;
452 fuzz->nextRange(&i, 0, familyCount - 1);
453 sk_sp<SkFontStyleSet> family(mgr->createStyleSet(i));
454 int styleCount = family->count();
455 fuzz->nextRange(&j, 0, styleCount - 1);
456 return sk_sp<SkTypeface>(family->createTypeface(j));
457}
458
459static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
460
462 if (depth <= 0) {
463 return nullptr;
464 }
465 uint8_t imageFilterType;
466 fuzz->nextRange(&imageFilterType, 1, 6);
467 SkPoint3 p, q;
468 SkColor lightColor;
469 SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
471 SkIRect cropRect;
472 bool useCropRect;
473 fuzz->next(&useCropRect);
474 if (useCropRect) {
475 fuzz->next(&cropRect);
476 }
477 switch (imageFilterType) {
478 case 1:
479 fuzz->next(&p, &lightColor, &surfaceScale, &k);
480 input = make_fuzz_imageFilter(fuzz, depth - 1);
481 return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
482 std::move(input),
483 useCropRect ? &cropRect : nullptr);
484 case 2:
485 fuzz->next(&p, &lightColor, &surfaceScale, &k);
486 input = make_fuzz_imageFilter(fuzz, depth - 1);
487 return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
488 std::move(input),
489 useCropRect ? &cropRect : nullptr);
490 case 3:
491 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
492 input = make_fuzz_imageFilter(fuzz, depth - 1);
494 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
495 std::move(input), useCropRect ? &cropRect : nullptr);
496 case 4:
497 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
498 input = make_fuzz_imageFilter(fuzz, depth - 1);
499 return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
500 shininess, std::move(input),
501 useCropRect ? &cropRect : nullptr);
502 case 5:
503 fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
504 input = make_fuzz_imageFilter(fuzz, depth - 1);
505 return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
506 shininess, std::move(input),
507 useCropRect ? &cropRect : nullptr);
508 case 6:
509 fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
510 &shininess);
511 input = make_fuzz_imageFilter(fuzz, depth - 1);
513 p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
514 std::move(input), useCropRect ? &cropRect : nullptr);
515 default:
516 SkASSERT(false);
517 return nullptr;
518 }
519}
520
521static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
522
524 if (fuzz->nextBool()) {
525 float B, C;
526 fuzz->next(&B, &C);
527 return SkSamplingOptions({B, C});
528 } else {
529 SkFilterMode fm;
530 SkMipmapMode mm;
531 fuzz->nextEnum(&fm, SkFilterMode::kLast);
532 fuzz->nextEnum(&mm, SkMipmapMode::kLast);
533 return SkSamplingOptions(fm, mm);
534 }
535}
536
538 if (depth <= 0) {
539 return nullptr;
540 }
541 uint8_t imageFilterType;
542 fuzz->nextRange(&imageFilterType, 0, 22);
543 switch (imageFilterType) {
544 case 0:
545 return nullptr;
546 case 1: {
547 SkScalar sigmaX, sigmaY;
548 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
549 bool useCropRect;
550 fuzz->next(&sigmaX, &sigmaY, &useCropRect);
551 SkIRect cropRect;
552 if (useCropRect) {
553 fuzz->next(&cropRect);
554 }
555 return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
556 useCropRect ? &cropRect : nullptr);
557 }
558 case 2: {
559 SkMatrix matrix;
560 FuzzNiceMatrix(fuzz, &matrix);
561 const auto sampling = next_sampling(fuzz);
562 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
563 return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
564 }
565 case 3: {
566 float k1, k2, k3, k4;
567 bool enforcePMColor;
568 bool useCropRect;
569 fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
570 sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
571 sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
572 SkIRect cropRect;
573 if (useCropRect) {
574 fuzz->next(&cropRect);
575 }
576 return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
577 std::move(background), std::move(foreground),
578 useCropRect ? &cropRect : nullptr);
579 }
580 case 4: {
581 sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
582 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
583 bool useCropRect;
584 SkIRect cropRect;
585 fuzz->next(&useCropRect);
586 if (useCropRect) {
587 fuzz->next(&cropRect);
588 }
589 return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
590 useCropRect ? &cropRect : nullptr);
591 }
592 case 5: {
593 sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
594 sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
595 return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
596 }
597 case 6: {
598 SkColorChannel xChannelSelector, yChannelSelector;
599 fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
600 fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
602 bool useCropRect;
603 fuzz->next(&scale, &useCropRect);
604 SkIRect cropRect;
605 if (useCropRect) {
606 fuzz->next(&cropRect);
607 }
608 sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
610 return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
611 std::move(displacement), std::move(color),
612 useCropRect ? &cropRect : nullptr);
613 }
614 case 7: {
615 SkScalar dx, dy, sigmaX, sigmaY;
617 bool shadowOnly, useCropRect;
618 fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
619 SkIRect cropRect;
620 if (useCropRect) {
621 fuzz->next(&cropRect);
622 }
623 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
624 if (shadowOnly) {
625 return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
626 std::move(input),
627 useCropRect ? &cropRect : nullptr);
628 } else {
629 return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
630 useCropRect ? &cropRect : nullptr);
631 }
632 }
633 case 8:
635 case 9: {
637 SkRect srcRect, dstRect;
638 fuzz->next(&srcRect, &dstRect);
639 return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
640 }
641 case 10:
642 return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
643 case 11: {
644 SkRect lensBounds;
645 SkScalar zoomAmount;
647 bool useCropRect;
648 SkIRect cropRect;
649 fuzz->next(&lensBounds, &zoomAmount, &inset, &useCropRect);
650 if (useCropRect) {
651 fuzz->next(&cropRect);
652 }
653 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
654 const auto sampling = next_sampling(fuzz);
655 return SkImageFilters::Magnifier(lensBounds, zoomAmount, inset, sampling,
656 std::move(input), useCropRect ? &cropRect : nullptr);
657 }
658 case 12: {
659 constexpr int kMaxKernelSize = 5;
660 int32_t n, m;
661 fuzz->nextRange(&n, 1, kMaxKernelSize);
662 fuzz->nextRange(&m, 1, kMaxKernelSize);
663 SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
664 fuzz->nextN(kernel, n * m);
665 int32_t offsetX, offsetY;
666 fuzz->nextRange(&offsetX, 0, n - 1);
667 fuzz->nextRange(&offsetY, 0, m - 1);
668 SkScalar gain, bias;
669 bool convolveAlpha, useCropRect;
670 fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
671 SkTileMode tileMode;
672 fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
673 SkIRect cropRect;
674 if (useCropRect) {
675 fuzz->next(&cropRect);
676 }
677 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
679 SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
680 convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
681 }
682 case 13: {
683 sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
684 sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
685 bool useCropRect;
686 fuzz->next(&useCropRect);
687 SkIRect cropRect;
688 if (useCropRect) {
689 fuzz->next(&cropRect);
690 }
691 return SkImageFilters::Merge(std::move(first), std::move(second),
692 useCropRect ? &cropRect : nullptr);
693 }
694 case 14: {
695 constexpr int kMaxCount = 4;
696 sk_sp<SkImageFilter> ifs[kMaxCount];
697 int count;
698 fuzz->nextRange(&count, 1, kMaxCount);
699 for (int i = 0; i < count; ++i) {
700 ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
701 }
702 bool useCropRect;
703 fuzz->next(&useCropRect);
704 SkIRect cropRect;
705 if (useCropRect) {
706 fuzz->next(&cropRect);
707 }
708 return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
709 }
710 case 15: {
711 int rx, ry;
712 fuzz->next(&rx, &ry);
713 bool useCropRect;
714 fuzz->next(&useCropRect);
715 SkIRect cropRect;
716 if (useCropRect) {
717 fuzz->next(&cropRect);
718 }
719 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
720 return SkImageFilters::Dilate(rx, ry, std::move(input),
721 useCropRect ? &cropRect : nullptr);
722 }
723 case 16: {
724 int rx, ry;
725 fuzz->next(&rx, &ry);
726 bool useCropRect;
727 fuzz->next(&useCropRect);
728 SkIRect cropRect;
729 if (useCropRect) {
730 fuzz->next(&cropRect);
731 }
732 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
733 return SkImageFilters::Erode(rx, ry, std::move(input),
734 useCropRect ? &cropRect : nullptr);
735 }
736 case 17: {
737 SkScalar dx, dy;
738 fuzz->next(&dx, &dy);
739 bool useCropRect;
740 fuzz->next(&useCropRect);
741 SkIRect cropRect;
742 if (useCropRect) {
743 fuzz->next(&cropRect);
744 }
745 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
746 return SkImageFilters::Offset(dx, dy, std::move(input),
747 useCropRect ? &cropRect : nullptr);
748 }
749 case 18: {
750 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
751 return SkImageFilters::Picture(std::move(picture));
752 }
753 case 19: {
754 SkRect cropRect;
755 fuzz->next(&cropRect);
756 sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
757 return SkImageFilters::Picture(std::move(picture), cropRect);
758 }
759 case 20: {
760 SkRect src, dst;
761 fuzz->next(&src, &dst);
762 sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
763 return SkImageFilters::Tile(src, dst, std::move(input));
764 }
765 case 21: {
766 SkBlendMode blendMode;
767 bool useCropRect;
768 fuzz->next(&useCropRect);
769 fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
770 SkIRect cropRect;
771 if (useCropRect) {
772 fuzz->next(&cropRect);
773 }
774 sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
775 sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
776 return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
777 useCropRect ? &cropRect : nullptr);
778 }
779 case 22: {
780 sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
781 bool useCropRect;
782 fuzz->next(&useCropRect);
783 SkIRect cropRect;
784 if (useCropRect) {
785 fuzz->next(&cropRect);
786 }
787 return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
788 }
789 default:
790 SkASSERT(false);
791 return nullptr;
792 }
793}
794
796 int w, h;
797 fuzz->nextRange(&w, 1, 1024);
798 fuzz->nextRange(&h, 1, 1024);
799 AutoTMalloc<SkPMColor> data(w * h);
800 SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
801 int n = w * h;
802 for (int i = 0; i < n; ++i) {
803 SkColor c;
804 fuzz->next(&c);
805 data[i] = SkPreMultiplyColor(c);
806 }
807 (void)data.release();
809 pixmap, [](const void* p, void*) { sk_free(const_cast<void*>(p)); }, nullptr);
810}
811
812template <typename T>
813static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
814 T value;
815 fuzz->nextEnum(&value, maxv);
816 return value;
817}
818
819static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
820 if (!fuzz || !paint || depth <= 0) {
821 return;
822 }
823
824 paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
825 paint->setDither( make_fuzz_t<bool>(fuzz));
826 paint->setColor( make_fuzz_t<SkColor>(fuzz));
827 paint->setBlendMode( make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
828 paint->setStyle( make_fuzz_enum_range<SkPaint::Style>(fuzz,
830 paint->setShader( make_fuzz_shader(fuzz, depth - 1));
831 paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
832 paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
833 paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
834 paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
835
836 if (paint->getStyle() != SkPaint::kFill_Style) {
837 paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
838 paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
839 paint->setStrokeCap( make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
840 paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
841 }
842}
843
844static SkFont fuzz_font(Fuzz* fuzz) {
845 SkFont font;
846 font.setTypeface( make_fuzz_typeface(fuzz));
847 font.setSize( make_fuzz_t<SkScalar>(fuzz));
848 font.setScaleX( make_fuzz_t<SkScalar>(fuzz));
849 font.setSkewX( make_fuzz_t<SkScalar>(fuzz));
850 font.setLinearMetrics( make_fuzz_t<bool>(fuzz));
851 font.setSubpixel( make_fuzz_t<bool>(fuzz));
852 font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
853 font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
854 font.setEmbolden( make_fuzz_t<bool>(fuzz));
855 font.setHinting( make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
856 font.setEdging( make_fuzz_enum_range<SkFont::Edging>(fuzz,
858 return font;
859}
860
862 return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
863}
864
865constexpr int kMaxGlyphCount = 30;
866
867static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
868 SkTDArray<uint8_t> array;
869 if (SkTextEncoding::kGlyphID == encoding) {
870 int glyphRange = font.getTypeface()->countGlyphs();
871 if (glyphRange == 0) {
872 // Some fuzzing environments have no fonts, so empty array is the best
873 // we can do.
874 return array;
875 }
876 int glyphCount;
877 fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
878 SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
879 for (int i = 0; i < glyphCount; ++i) {
880 fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
881 }
882 return array;
883 }
884 static const SkUnichar ranges[][2] = {
885 {0x0020, 0x007F},
886 {0x00A1, 0x0250},
887 {0x0400, 0x0500},
888 };
889 int32_t count = 0;
890 for (size_t i = 0; i < std::size(ranges); ++i) {
891 count += (ranges[i][1] - ranges[i][0]);
892 }
893 constexpr int kMaxLength = kMaxGlyphCount;
894 SkUnichar buffer[kMaxLength];
895 int length;
896 fuzz->nextRange(&length, 1, kMaxLength);
897 for (int j = 0; j < length; ++j) {
898 int32_t value;
899 fuzz->nextRange(&value, 0, count - 1);
900 for (size_t i = 0; i < std::size(ranges); ++i) {
901 if (value + ranges[i][0] < ranges[i][1]) {
902 buffer[j] = value + ranges[i][0];
903 break;
904 } else {
905 value -= (ranges[i][1] - ranges[i][0]);
906 }
907 }
908 }
909 switch (encoding) {
911 size_t utf8len = 0;
912 for (int j = 0; j < length; ++j) {
913 utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
914 }
915 char* ptr = (char*)array.append(utf8len);
916 for (int j = 0; j < length; ++j) {
917 ptr += SkUTF::ToUTF8(buffer[j], ptr);
918 }
919 } break;
921 size_t utf16len = 0;
922 for (int j = 0; j < length; ++j) {
923 utf16len += SkUTF::ToUTF16(buffer[j]);
924 }
925 uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
926 for (int j = 0; j < length; ++j) {
927 ptr += SkUTF::ToUTF16(buffer[j], ptr);
928 }
929 } break;
931 memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
932 break;
933 default:
934 SkASSERT(false);
935 break;
936 }
937 return array;
938}
939
940static std::string make_fuzz_string(Fuzz* fuzz) {
941 int len;
942 fuzz->nextRange(&len, 0, kMaxGlyphCount);
943 std::string str(len, 0);
944 for (int i = 0; i < len; i++) {
945 fuzz->next(&str[i]);
946 }
947 return str;
948}
949
951 SkTextBlobBuilder textBlobBuilder;
952 int8_t runCount;
953 fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
954 while (runCount-- > 0) {
957 font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
958 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
959 int glyphCount = font.countText(text.begin(), SkToSizeT(text.size()), encoding);
960 SkASSERT(glyphCount <= kMaxGlyphCount);
961 SkScalar x, y;
963 uint8_t runType;
964 fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
965 const void* textPtr = text.begin();
966 size_t textLen = SkToSizeT(text.size());
967 switch (runType) {
968 case 0:
969 fuzz->next(&x, &y);
970 // TODO: Test other variations of this.
971 buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
972 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
973 break;
974 case 1:
975 fuzz->next(&y);
976 // TODO: Test other variations of this.
977 buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
978 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
979 fuzz->nextN(buffer->pos, glyphCount);
980 break;
981 case 2:
982 // TODO: Test other variations of this.
983 buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
984 (void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
985 fuzz->nextN(buffer->pos, glyphCount * 2);
986 break;
987 default:
988 SkASSERT(false);
989 break;
990 }
991 }
992 return textBlobBuilder.make();
993}
994
995static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
996 if (!fuzz || !canvas || depth <= 0) {
997 return;
998 }
999 SkAutoCanvasRestore autoCanvasRestore(canvas, false);
1000 unsigned N;
1001 fuzz->nextRange(&N, 0, 2000);
1002 for (unsigned loop = 0; loop < N; ++loop) {
1003 if (fuzz->exhausted()) {
1004 return;
1005 }
1006 SkPaint paint;
1008 unsigned drawCommand;
1009 fuzz->nextRange(&drawCommand, 0, 62);
1010 switch (drawCommand) {
1011 case 0:
1012#if defined(SK_GANESH)
1013 if (auto dContext = GrAsDirectContext(canvas->recordingContext())) {
1014 dContext->flushAndSubmit();
1015 }
1016#endif
1017 break;
1018 case 1:
1019 canvas->save();
1020 break;
1021 case 2: {
1022 SkRect bounds;
1023 fuzz->next(&bounds);
1024 fuzz_paint(fuzz, &paint, depth - 1);
1025 canvas->saveLayer(&bounds, &paint);
1026 break;
1027 }
1028 case 3: {
1029 SkRect bounds;
1030 fuzz->next(&bounds);
1031 canvas->saveLayer(&bounds, nullptr);
1032 break;
1033 }
1034 case 4:
1035 fuzz_paint(fuzz, &paint, depth - 1);
1036 canvas->saveLayer(nullptr, &paint);
1037 break;
1038 case 5:
1039 canvas->saveLayer(nullptr, nullptr);
1040 break;
1041 case 6: {
1042 uint8_t alpha;
1043 fuzz->next(&alpha);
1044 canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
1045 break;
1046 }
1047 case 7: {
1048 SkRect bounds;
1049 uint8_t alpha;
1050 fuzz->next(&bounds, &alpha);
1051 canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
1052 break;
1053 }
1054 case 8: {
1055 SkCanvas::SaveLayerRec saveLayerRec;
1056 SkRect bounds;
1057 if (make_fuzz_t<bool>(fuzz)) {
1058 fuzz->next(&bounds);
1059 saveLayerRec.fBounds = &bounds;
1060 }
1061 if (make_fuzz_t<bool>(fuzz)) {
1062 fuzz_paint(fuzz, &paint, depth - 1);
1063 saveLayerRec.fPaint = &paint;
1064 }
1065 sk_sp<SkImageFilter> imageFilter;
1066 if (make_fuzz_t<bool>(fuzz)) {
1067 imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
1068 saveLayerRec.fBackdrop = imageFilter.get();
1069 }
1070 // _DumpCanvas can't handle this.
1071 // if (make_fuzz_t<bool>(fuzz)) {
1072 // saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
1073 // }
1074
1075 canvas->saveLayer(saveLayerRec);
1076 break;
1077 }
1078 case 9:
1079 canvas->restore();
1080 break;
1081 case 10: {
1082 int saveCount;
1083 fuzz->next(&saveCount);
1084 canvas->restoreToCount(saveCount);
1085 break;
1086 }
1087 case 11: {
1088 SkScalar x, y;
1089 fuzz->next(&x, &y);
1090 canvas->translate(x, y);
1091 break;
1092 }
1093 case 12: {
1094 SkScalar x, y;
1095 fuzz->next(&x, &y);
1096 canvas->scale(x, y);
1097 break;
1098 }
1099 case 13: {
1100 SkScalar v;
1101 fuzz->next(&v);
1102 canvas->rotate(v);
1103 break;
1104 }
1105 case 14: {
1106 SkScalar x, y, v;
1107 fuzz->next(&x, &y, &v);
1108 canvas->rotate(v, x, y);
1109 break;
1110 }
1111 case 15: {
1112 SkScalar x, y;
1113 fuzz->next(&x, &y);
1114 canvas->skew(x, y);
1115 break;
1116 }
1117 case 16: {
1118 SkMatrix mat;
1119 FuzzNiceMatrix(fuzz, &mat);
1120 canvas->concat(mat);
1121 break;
1122 }
1123 case 17: {
1124 SkMatrix mat;
1125 FuzzNiceMatrix(fuzz, &mat);
1126 canvas->setMatrix(mat);
1127 break;
1128 }
1129 case 18:
1130 canvas->resetMatrix();
1131 break;
1132 case 19: {
1133 SkRect r;
1134 int op;
1135 bool doAntiAlias;
1136 fuzz->next(&r, &doAntiAlias);
1137 fuzz->nextRange(&op, 0, 1);
1138 r.sort();
1139 canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
1140 break;
1141 }
1142 case 20: {
1143 SkRRect rr;
1144 int op;
1145 bool doAntiAlias;
1146 FuzzNiceRRect(fuzz, &rr);
1147 fuzz->next(&doAntiAlias);
1148 fuzz->nextRange(&op, 0, 1);
1149 canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
1150 break;
1151 }
1152 case 21: {
1153 SkPath path;
1154 FuzzNicePath(fuzz, &path, 30);
1155 int op;
1156 bool doAntiAlias;
1157 fuzz->next(&doAntiAlias);
1158 fuzz->nextRange(&op, 0, 1);
1159 canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
1160 break;
1161 }
1162 case 22: {
1163 SkRegion region;
1164 int op;
1165 fuzz->next(&region);
1166 fuzz->nextRange(&op, 0, 1);
1167 canvas->clipRegion(region, (SkClipOp)op);
1168 break;
1169 }
1170 case 23:
1171 fuzz_paint(fuzz, &paint, depth - 1);
1172 canvas->drawPaint(paint);
1173 break;
1174 case 24: {
1175 fuzz_paint(fuzz, &paint, depth - 1);
1176 SkCanvas::PointMode pointMode;
1177 fuzz->nextRange(&pointMode,
1179 size_t count;
1180 constexpr int kMaxCount = 30;
1181 fuzz->nextRange(&count, 0, kMaxCount);
1182 SkPoint pts[kMaxCount];
1183 fuzz->nextN(pts, count);
1184 canvas->drawPoints(pointMode, count, pts, paint);
1185 break;
1186 }
1187 case 25: {
1188 fuzz_paint(fuzz, &paint, depth - 1);
1189 SkRect r;
1190 fuzz->next(&r);
1191 if (!r.isFinite()) {
1192 break;
1193 }
1194 canvas->drawRect(r, paint);
1195 break;
1196 }
1197 case 26: {
1198 fuzz_paint(fuzz, &paint, depth - 1);
1199 SkRegion region;
1200 fuzz->next(&region);
1201 canvas->drawRegion(region, paint);
1202 break;
1203 }
1204 case 27: {
1205 fuzz_paint(fuzz, &paint, depth - 1);
1206 SkRect r;
1207 fuzz->next(&r);
1208 if (!r.isFinite()) {
1209 break;
1210 }
1211 canvas->drawOval(r, paint);
1212 break;
1213 }
1214 case 28: break; // must have deleted this some time earlier
1215 case 29: {
1216 fuzz_paint(fuzz, &paint, depth - 1);
1217 SkRRect rr;
1218 FuzzNiceRRect(fuzz, &rr);
1219 canvas->drawRRect(rr, paint);
1220 break;
1221 }
1222 case 30: {
1223 fuzz_paint(fuzz, &paint, depth - 1);
1224 SkRRect orr, irr;
1225 FuzzNiceRRect(fuzz, &orr);
1226 FuzzNiceRRect(fuzz, &irr);
1227 if (orr.getBounds().contains(irr.getBounds())) {
1228 canvas->drawDRRect(orr, irr, paint);
1229 }
1230 break;
1231 }
1232 case 31: {
1233 fuzz_paint(fuzz, &paint, depth - 1);
1234 SkRect r;
1235 SkScalar start, sweep;
1236 bool useCenter;
1237 fuzz->next(&r, &start, &sweep, &useCenter);
1238 canvas->drawArc(r, start, sweep, useCenter, paint);
1239 break;
1240 }
1241 case 32: {
1242 fuzz_paint(fuzz, &paint, depth - 1);
1243 SkPath path;
1244 FuzzNicePath(fuzz, &path, 60);
1245 canvas->drawPath(path, paint);
1246 break;
1247 }
1248 case 33: {
1249 sk_sp<SkImage> img = make_fuzz_image(fuzz);
1250 SkScalar left, top;
1251 bool usePaint;
1252 fuzz->next(&left, &top, &usePaint);
1253 if (usePaint) {
1254 fuzz_paint(fuzz, &paint, depth - 1);
1255 }
1256 canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
1257 usePaint ? &paint : nullptr);
1258 break;
1259 }
1260 case 35: {
1261 auto img = make_fuzz_image(fuzz);
1262 SkIRect src;
1263 SkRect dst;
1264 bool usePaint;
1265 fuzz->next(&src, &dst, &usePaint);
1266 if (usePaint) {
1267 fuzz_paint(fuzz, &paint, depth - 1);
1268 }
1269 SkCanvas::SrcRectConstraint constraint =
1270 make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
1272 canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
1273 usePaint ? &paint : nullptr, constraint);
1274 break;
1275 }
1276 case 37: {
1277 auto img = make_fuzz_image(fuzz);
1279 SkRect dst;
1280 bool usePaint;
1281 fuzz->next(&usePaint);
1282 if (usePaint) {
1283 fuzz_paint(fuzz, &paint, depth - 1);
1284 }
1285 if (make_fuzz_t<bool>(fuzz)) {
1286 fuzz->next(&center);
1287 } else { // Make valid center, see SkLatticeIter::Valid().
1288 fuzz->nextRange(&center.fLeft, 0, img->width() - 1);
1289 fuzz->nextRange(&center.fTop, 0, img->height() - 1);
1290 fuzz->nextRange(&center.fRight, center.fLeft + 1, img->width());
1291 fuzz->nextRange(&center.fBottom, center.fTop + 1, img->height());
1292 }
1293 fuzz->next(&dst);
1294 canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
1295 usePaint ? &paint : nullptr);
1296 break;
1297 }
1298 case 44: {
1299 auto img = make_fuzz_image(fuzz);
1300 bool usePaint;
1301 SkRect dst;
1302 fuzz->next(&usePaint, &dst);
1303 if (usePaint) {
1304 fuzz_paint(fuzz, &paint, depth - 1);
1305 }
1306 constexpr int kMax = 6;
1307 int xDivs[kMax], yDivs[kMax];
1308 SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
1309 fuzz->nextRange(&lattice.fXCount, 2, kMax);
1310 fuzz->nextRange(&lattice.fYCount, 2, kMax);
1311 fuzz->nextN(xDivs, lattice.fXCount);
1312 fuzz->nextN(yDivs, lattice.fYCount);
1313 canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
1314 usePaint ? &paint : nullptr);
1315 break;
1316 }
1317 case 45: {
1318 fuzz_paint(fuzz, &paint, depth - 1);
1319 font = fuzz_font(fuzz);
1321 SkScalar x, y;
1322 fuzz->next(&x, &y);
1323 SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
1324 canvas->drawSimpleText(text.begin(), SkToSizeT(text.size()), encoding, x, y,
1325 font, paint);
1326 break;
1327 }
1328 case 46: {
1329 // was drawPosText
1330 break;
1331 }
1332 case 47: {
1333 // was drawPosTextH
1334 break;
1335 }
1336 case 48: {
1337 // was drawtextonpath
1338 break;
1339 }
1340 case 49: {
1341 // was drawtextonpath
1342 break;
1343 }
1344 case 50: {
1345 // was drawTextRSXform
1346 break;
1347 }
1348 case 51: {
1350 fuzz_paint(fuzz, &paint, depth - 1);
1351 SkScalar x, y;
1352 fuzz->next(&x, &y);
1353 canvas->drawTextBlob(blob, x, y, paint);
1354 break;
1355 }
1356 case 52: {
1357 SkMatrix matrix;
1358 bool usePaint, useMatrix;
1359 fuzz->next(&usePaint, &useMatrix);
1360 if (usePaint) {
1361 fuzz_paint(fuzz, &paint, depth - 1);
1362 }
1363 if (useMatrix) {
1364 FuzzNiceMatrix(fuzz, &matrix);
1365 }
1366 auto pic = make_fuzz_picture(fuzz, depth - 1);
1367 canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
1368 usePaint ? &paint : nullptr);
1369 break;
1370 }
1371 case 53: {
1372 fuzz_paint(fuzz, &paint, depth - 1);
1373 SkVertices::VertexMode vertexMode;
1374 SkBlendMode blendMode;
1375 fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
1376 fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
1377 constexpr int kMaxCount = 100;
1378 int vertexCount;
1379 SkPoint vertices[kMaxCount];
1380 SkPoint texs[kMaxCount];
1381 SkColor colors[kMaxCount];
1382 fuzz->nextRange(&vertexCount, 3, kMaxCount);
1383 fuzz->nextN(vertices, vertexCount);
1384 bool useTexs, useColors;
1385 fuzz->next(&useTexs, &useColors);
1386 if (useTexs) {
1387 fuzz->nextN(texs, vertexCount);
1388 }
1389 if (useColors) {
1390 fuzz->nextN(colors, vertexCount);
1391 }
1392 int indexCount = 0;
1393 uint16_t indices[kMaxCount * 2];
1394 if (make_fuzz_t<bool>(fuzz)) {
1395 fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
1396 for (int index = 0; index < indexCount; ++index) {
1397 fuzz->nextRange(&indices[index], 0, vertexCount - 1);
1398 }
1399 }
1400 canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
1401 useTexs ? texs : nullptr,
1402 useColors ? colors : nullptr,
1403 indexCount, indices),
1404 blendMode, paint);
1405 break;
1406 }
1407 case 54: {
1408 SkColor color;
1409 SkBlendMode blendMode;
1410 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1411 fuzz->next(&color);
1412 canvas->drawColor(color, blendMode);
1413 break;
1414 }
1415 case 55: {
1417 SkBlendMode blendMode;
1418 float R, G, B, Alpha;
1419 fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
1420 fuzz->nextRange(&R, -1, 2);
1421 fuzz->nextRange(&G, -1, 2);
1422 fuzz->nextRange(&B, -1, 2);
1423 fuzz->nextRange(&Alpha, 0, 1);
1424 color = {R, G, B, Alpha};
1425 canvas->drawColor(color, blendMode);
1426 break;
1427 }
1428 case 56: {
1429 fuzz_paint(fuzz, &paint, depth - 1);
1430 SkPoint p0, p1;
1431 fuzz->next(&p0, &p1);
1432 canvas->drawLine(p0, p1, paint);
1433 break;
1434 }
1435 case 57: {
1436 fuzz_paint(fuzz, &paint, depth - 1);
1437 SkIRect r;
1438 fuzz->next(&r);
1439 canvas->drawIRect(r, paint);
1440 break;
1441 }
1442 case 58: {
1443 fuzz_paint(fuzz, &paint, depth - 1);
1444 SkScalar radius;
1446 fuzz->next(&radius, &center);
1447 canvas->drawCircle(center, radius, paint);
1448 break;
1449 }
1450 case 59: {
1451 fuzz_paint(fuzz, &paint, depth - 1);
1452 SkRect oval;
1453 SkScalar startAngle, sweepAngle;
1454 bool useCenter;
1455 fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
1456 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
1457 break;
1458 }
1459 case 60: {
1460 fuzz_paint(fuzz, &paint, depth - 1);
1461 SkRect rect;
1462 SkScalar rx, ry;
1463 fuzz->next(&rect, &rx, &ry);
1464 canvas->drawRoundRect(rect, rx, ry, paint);
1465 break;
1466 }
1467 case 61: {
1468 fuzz_paint(fuzz, &paint, depth - 1);
1469 font = fuzz_font(fuzz);
1470 std::string str = make_fuzz_string(fuzz);
1471 SkScalar x, y;
1472 fuzz->next(&x, &y);
1473 canvas->drawString(str.c_str(), x, y, font, paint);
1474 break;
1475 }
1476 case 62: {
1477 fuzz_paint(fuzz, &paint, depth - 1);
1478 SkPoint cubics[12];
1479 SkColor colors[4];
1480 SkPoint texCoords[4];
1481 bool useTexCoords;
1482 fuzz->nextN(cubics, 12);
1483 fuzz->nextN(colors, 4);
1484 fuzz->next(&useTexCoords);
1485 if (useTexCoords) {
1486 fuzz->nextN(texCoords, 4);
1487 }
1488 SkBlendMode mode;
1489 fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
1490 canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
1491 , mode, paint);
1492 break;
1493 }
1494 default:
1495 SkASSERT(false);
1496 break;
1497 }
1498 }
1499}
1500
1501static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
1502 SkScalar w, h;
1503 fuzz->next(&w, &h);
1504 SkPictureRecorder pictureRecorder;
1505 fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
1506 return pictureRecorder.finishRecordingAsPicture();
1507}
1508
1509DEF_FUZZ(NullCanvas, fuzz) {
1510 fuzz_canvas(fuzz, SkMakeNullCanvas().get());
1511}
1512
1513constexpr SkISize kCanvasSize = {128, 160};
1514
1515DEF_FUZZ(RasterN32Canvas, fuzz) {
1518 if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
1519 fuzz_canvas(fuzz, surface->getCanvas());
1520}
1521
1522DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
1523 SkPictureRecorder recorder;
1527 if (!pic) { fuzz->signalBug(); }
1528 SkSerialProcs sProcs;
1529 sProcs.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
1530 return SkPngEncoder::Encode(nullptr, img, SkPngEncoder::Options{});
1531 };
1532 sk_sp<SkData> data = pic->serialize(&sProcs);
1533 if (!data) { fuzz->signalBug(); }
1534 SkReadBuffer rb(data->data(), data->size());
1535 SkCodecs::Register(SkPngDecoder::Decoder());
1536 auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
1537 if (!deserialized) { fuzz->signalBug(); }
1540 SkASSERT(surface && surface->getCanvas());
1541 surface->getCanvas()->drawPicture(deserialized);
1542}
1543
1544DEF_FUZZ(ImageFilter, fuzz) {
1546 if (!bitmap.tryAllocN32Pixels(256, 256)) {
1547 SkDEBUGF("Could not allocate 256x256 bitmap in ImageFilter");
1548 return;
1549 }
1550
1551 auto fil = make_fuzz_imageFilter(fuzz, 20);
1552
1553 SkPaint paint;
1554 paint.setImageFilter(fil);
1555 SkCanvas canvas(bitmap);
1556 canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
1557}
1558
1559
1560//SkRandom _rand;
1561#define SK_ADD_RANDOM_BIT_FLIPS
1562
1563DEF_FUZZ(SerializedImageFilter, fuzz) {
1565 if (!bitmap.tryAllocN32Pixels(256, 256)) {
1566 SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
1567 return;
1568 }
1569
1570 auto filter = make_fuzz_imageFilter(fuzz, 20);
1571 if (!filter) {
1572 return;
1573 }
1574 auto data = filter->serialize();
1575 const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
1576 size_t len = data->size();
1577#ifdef SK_ADD_RANDOM_BIT_FLIPS
1578 unsigned char* p = const_cast<unsigned char*>(ptr);
1579 for (size_t i = 0; i < len; ++i, ++p) {
1580 uint8_t j;
1581 fuzz->nextRange(&j, 1, 250);
1582 if (j == 1) { // 0.4% of the time, flip a bit or byte
1583 uint8_t k;
1584 fuzz->nextRange(&k, 1, 10);
1585 if (k == 1) { // Then 10% of the time, change a whole byte
1586 uint8_t s;
1587 fuzz->nextRange(&s, 0, 2);
1588 switch(s) {
1589 case 0:
1590 *p ^= 0xFF; // Flip entire byte
1591 break;
1592 case 1:
1593 *p = 0xFF; // Set all bits to 1
1594 break;
1595 case 2:
1596 *p = 0x00; // Set all bits to 0
1597 break;
1598 }
1599 } else {
1600 uint8_t s;
1601 fuzz->nextRange(&s, 0, 7);
1602 *p ^= (1 << 7);
1603 }
1604 }
1605 }
1606#endif // SK_ADD_RANDOM_BIT_FLIPS
1607 auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
1608
1609 // uncomment below to write out a serialized image filter (to make corpus
1610 // for -t filter_fuzz)
1611 // SkString s("./serialized_filters/sf");
1612 // s.appendU32(_rand.nextU());
1613 // auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
1614 // sk_fwrite(data->bytes(), data->size(), file);
1615 // sk_fclose(file);
1616
1617 SkPaint paint;
1618 paint.setImageFilter(deserializedFil);
1619
1620 SkCanvas canvas(bitmap);
1621 canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
1622 canvas.restore();
1623}
1624
1625#if defined(SK_GANESH)
1626static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
1627 SkASSERT(context);
1629 context,
1632 SkASSERT(surface && surface->getCanvas());
1633 fuzz_canvas(fuzz, surface->getCanvas());
1634}
1635
1636DEF_FUZZ(MockGPUCanvas, fuzz) {
1638 fuzz_ganesh(fuzz, f.get(skgpu::ContextType::kMock));
1639}
1640#endif
1641
1642#ifdef SK_GL
1643static void dump_GPU_info(GrDirectContext* context) {
1644 const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
1645 ->glInterface();
1646 const GrGLubyte* output;
1647 GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
1648 SkDebugf("GL_RENDERER %s\n", (const char*) output);
1649
1650 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
1651 SkDebugf("GL_VENDOR %s\n", (const char*) output);
1652
1653 GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
1654 SkDebugf("GL_VERSION %s\n", (const char*) output);
1655}
1656
1657DEF_FUZZ(NativeGLCanvas, fuzz) {
1659 auto context = f.get(skgpu::ContextType::kGL);
1660 if (!context) {
1661 context = f.get(skgpu::ContextType::kGLES);
1662 }
1663 if (FLAGS_gpuInfo) {
1664 dump_GPU_info(context);
1665 }
1666 fuzz_ganesh(fuzz, context);
1667}
1668#endif
1669
1670DEF_FUZZ(PDFCanvas, fuzz) {
1671 SkNullWStream stream;
1672 auto doc = SkPDF::MakeDocument(&stream);
1673 fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
1675}
1676
1677// not a "real" thing to fuzz, used to debug errors found while fuzzing.
1678DEF_FUZZ(_DumpCanvas, fuzz) {
1680 fuzz_canvas(fuzz, &debugCanvas);
1681 std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
1682 UrlDataManager dataManager(SkString("data"));
1685 writer.beginObject(); // root
1686 debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
1687 writer.endObject(); // root
1688 writer.flush();
1689 sk_sp<SkData> json = stream.detachAsData();
1690 fwrite(json->data(), json->size(), 1, stdout);
1691}
1692
1693DEF_FUZZ(SVGCanvas, fuzz) {
1694 SkNullWStream stream;
1695 SkRect bounds = SkRect::MakeIWH(150, 150);
1696 std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
1697 fuzz_canvas(fuzz, canvas.get());
1698}
#define DEFINE_bool2(name, shortName, defaultValue, helpString)
uint16_t glyphs[5]
int count
static sk_sp< SkPicture > make_fuzz_picture(Fuzz *, int depth)
constexpr int kMaxGlyphCount
static void fuzz_canvas(Fuzz *fuzz, SkCanvas *canvas, int depth=9)
static T make_fuzz_enum_range(Fuzz *fuzz, T maxv)
static sk_sp< SkPathEffect > make_fuzz_patheffect(Fuzz *fuzz, int depth)
static SkFont fuzz_font(Fuzz *fuzz)
static sk_sp< SkTypeface > make_fuzz_typeface(Fuzz *fuzz)
static std::string make_fuzz_string(Fuzz *fuzz)
static SkSamplingOptions next_sampling(Fuzz *fuzz)
static sk_sp< SkMaskFilter > make_fuzz_maskfilter(Fuzz *fuzz)
T make_fuzz_t(Fuzz *fuzz)
static void fuzz_paint(Fuzz *fuzz, SkPaint *paint, int depth)
static SkTDArray< uint8_t > make_fuzz_text(Fuzz *fuzz, const SkFont &font, SkTextEncoding encoding)
static void fuzz_gradient_stops(Fuzz *fuzz, SkScalar *pos, int colorCount)
static sk_sp< SkImageFilter > make_fuzz_lighting_imagefilter(Fuzz *fuzz, int depth)
static SkTextEncoding fuzz_paint_text_encoding(Fuzz *fuzz)
static sk_sp< SkShader > make_fuzz_shader(Fuzz *fuzz, int depth)
static sk_sp< SkColorFilter > make_fuzz_colorfilter(Fuzz *fuzz, int depth)
static sk_sp< SkImageFilter > make_fuzz_imageFilter(Fuzz *fuzz, int depth)
static sk_sp< SkTextBlob > make_fuzz_textblob(Fuzz *fuzz)
constexpr SkISize kCanvasSize
static sk_sp< SkImage > make_fuzz_image(Fuzz *)
void FuzzNiceRRect(Fuzz *fuzz, SkRRect *rr)
void FuzzNiceMatrix(Fuzz *fuzz, SkMatrix *m)
void FuzzNicePath(Fuzz *fuzz, SkPath *path, int maxOps)
#define DEF_FUZZ(name, f)
Definition Fuzz.h:156
#define GR_GL_RENDERER
#define GR_GL_VENDOR
#define GR_GL_VERSION
unsigned char GrGLubyte
Definition GrGLTypes.h:111
#define GR_GL_CALL_RET(IFACE, RET, X)
Definition GrGLUtil.h:396
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
SkPoint pos
SkColor4f color
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
@ kSrcOver
r = s + (1-sa)*d
@ kLastMode
last valid value
SkBlurStyle
Definition SkBlurTypes.h:11
@ kLastEnum_SkBlurStyle
Definition SkBlurTypes.h:17
unsigned U8CPU
Definition SkCPUTypes.h:18
SkClipOp
Definition SkClipOp.h:13
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
SK_API SkPMColor SkPreMultiplyColor(SkColor c)
Definition SkColor.cpp:21
uint32_t SkColor
Definition SkColor.h:37
uint32_t SkPMColor
Definition SkColor.h:205
SkColorChannel
Definition SkColor.h:228
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define SkDEBUGF(...)
Definition SkDebug.h:24
@ kFull
modifies glyph outlines for maximum constrast
SkTextEncoding
Definition SkFontTypes.h:11
@ kUTF8
uses bytes to represent UTF-8 or ASCII
@ kUTF16
uses two byte words to represent most of Unicode
@ kUTF32
uses four byte words to represent all of Unicode
@ kGlyphID
uses two byte words to represent glyph indices
SK_API void sk_free(void *)
SK_API std::unique_ptr< SkCanvas > SkMakeNullCanvas()
static bool left(const SkPoint &p0, const SkPoint &p1)
SkFilterMode
SkMipmapMode
#define SkIntToScalar(x)
Definition SkScalar.h:57
SkTileMode
Definition SkTileMode.h:13
constexpr size_t SkToSizeT(S x)
Definition SkTo.h:31
int32_t SkUnichar
Definition SkTypes.h:175
uint16_t SkGlyphID
Definition SkTypes.h:179
static SkScalar center(float pos0, float pos1)
SI F table(const skcms_Curve *curve, F v)
#define N
Definition beziers.cpp:19
void toJSON(SkJSONWriter &writer, UrlDataManager &urlDataManager, SkCanvas *)
Definition Fuzz.h:24
void next(T *t)
Definition Fuzz.h:64
void nextRange(T *, Min, Max)
Definition Fuzz.h:119
bool nextBool()
Definition Fuzz.h:92
bool exhausted() const
Definition Fuzz.h:39
void nextEnum(T *ptr, T max)
Definition Fuzz.h:131
void nextN(T *ptr, int n)
Definition Fuzz.h:144
GrDirectContextPriv priv()
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
void drawRect(const SkRect &rect, const SkPaint &paint)
void drawOval(const SkRect &oval, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint &paint)
void drawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4], SkBlendMode mode, const SkPaint &paint)
void restore()
Definition SkCanvas.cpp:465
void drawSimpleText(const void *text, size_t byteLength, SkTextEncoding encoding, SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
void drawImageNine(const SkImage *image, const SkIRect &center, const SkRect &dst, SkFilterMode filter, const SkPaint *paint=nullptr)
void drawColor(SkColor color, SkBlendMode mode=SkBlendMode::kSrcOver)
Definition SkCanvas.h:1182
virtual GrRecordingContext * recordingContext() const
void drawPaint(const SkPaint &paint)
void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint &paint)
int saveLayerAlpha(const SkRect *bounds, U8CPU alpha)
Definition SkCanvas.h:661
SrcRectConstraint
Definition SkCanvas.h:1541
@ kStrict_SrcRectConstraint
sample only inside bounds; slower
Definition SkCanvas.h:1542
@ kFast_SrcRectConstraint
sample outside bounds; faster
Definition SkCanvas.h:1543
void clipRegion(const SkRegion &deviceRgn, SkClipOp op=SkClipOp::kIntersect)
void drawIRect(const SkIRect &rect, const SkPaint &paint)
Definition SkCanvas.h:1358
void rotate(SkScalar degrees)
void restoreToCount(int saveCount)
Definition SkCanvas.cpp:482
void drawRRect(const SkRRect &rrect, const SkPaint &paint)
void drawRoundRect(const SkRect &rect, SkScalar rx, SkScalar ry, const SkPaint &paint)
void drawArc(const SkRect &oval, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, const SkPaint &paint)
void drawImageLattice(const SkImage *image, const Lattice &lattice, const SkRect &dst, SkFilterMode filter, const SkPaint *paint=nullptr)
void resetMatrix()
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
void drawRegion(const SkRegion &region, const SkPaint &paint)
void drawImageRect(const SkImage *, const SkRect &src, const SkRect &dst, const SkSamplingOptions &, const SkPaint *, SrcRectConstraint)
int save()
Definition SkCanvas.cpp:451
void drawPath(const SkPath &path, const SkPaint &paint)
void setMatrix(const SkM44 &matrix)
void drawDRRect(const SkRRect &outer, const SkRRect &inner, const SkPaint &paint)
void scale(SkScalar sx, SkScalar sy)
void concat(const SkMatrix &matrix)
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition SkCanvas.h:1803
void drawPicture(const SkPicture *picture)
Definition SkCanvas.h:1961
void drawVertices(const SkVertices *vertices, SkBlendMode mode, const SkPaint &paint)
@ kPolygon_PointMode
draw the array of points as a open polygon
Definition SkCanvas.h:1243
@ kPoints_PointMode
draw each point separately
Definition SkCanvas.h:1241
void skew(SkScalar sx, SkScalar sy)
void drawTextBlob(const SkTextBlob *blob, SkScalar x, SkScalar y, const SkPaint &paint)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
void clipRRect(const SkRRect &rrect, SkClipOp op, bool doAntiAlias)
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Table(const uint8_t table[256])
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorFilter > Lighting(SkColor mul, SkColor add)
static sk_sp< SkColorFilter > TableARGB(const uint8_t tableA[256], const uint8_t tableR[256], const uint8_t tableG[256], const uint8_t tableB[256])
static sk_sp< SkPathEffect > Make(SkScalar radius)
static sk_sp< SkPathEffect > Make(const SkScalar intervals[], int count, SkScalar phase)
static sk_sp< SkPathEffect > Make(SkScalar segLength, SkScalar dev, uint32_t seedAssist=0)
@ kAntiAlias
may have transparent pixels on glyph edges
@ kAlias
no transparent pixels on glyph edges
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
static sk_sp< SkShader > MakeTwoPointConical(const SkPoint &start, SkScalar startRadius, const SkPoint &end, SkScalar endRadius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeSweep(SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, SkScalar startAngle, SkScalar endAngle, uint32_t flags, const SkMatrix *localMatrix)
static sk_sp< SkShader > MakeRadial(const SkPoint &center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static sk_sp< SkImageFilter > Deserialize(const void *data, size_t size, const SkDeserialProcs *procs=nullptr)
static sk_sp< SkImageFilter > PointLitDiffuse(const SkPoint3 &location, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > MatrixConvolution(const SkISize &kernelSize, const SkScalar kernel[], SkScalar gain, SkScalar bias, const SkIPoint &kernelOffset, SkTileMode tileMode, bool convolveAlpha, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > ColorFilter(sk_sp< SkColorFilter > cf, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DropShadow(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Erode(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DistantLitSpecular(const SkPoint3 &direction, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DistantLitDiffuse(const SkPoint3 &direction, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Merge(sk_sp< SkImageFilter > *const filters, int count, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Arithmetic(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4, bool enforcePMColor, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DropShadowOnly(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Magnifier(const SkRect &lensBounds, SkScalar zoomAmount, SkScalar inset, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DisplacementMap(SkColorChannel xChannelSelector, SkColorChannel yChannelSelector, SkScalar scale, sk_sp< SkImageFilter > displacement, sk_sp< SkImageFilter > color, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Compose(sk_sp< SkImageFilter > outer, sk_sp< SkImageFilter > inner)
static sk_sp< SkImageFilter > Image(sk_sp< SkImage > image, const SkRect &srcRect, const SkRect &dstRect, const SkSamplingOptions &sampling)
static sk_sp< SkImageFilter > Picture(sk_sp< SkPicture > pic, const SkRect &targetRect)
static sk_sp< SkImageFilter > MatrixTransform(const SkMatrix &matrix, const SkSamplingOptions &sampling, sk_sp< SkImageFilter > input)
static sk_sp< SkImageFilter > Blend(SkBlendMode mode, sk_sp< SkImageFilter > background, sk_sp< SkImageFilter > foreground=nullptr, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Offset(SkScalar dx, SkScalar dy, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Shader(sk_sp< SkShader > shader, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Dilate(SkScalar radiusX, SkScalar radiusY, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Tile(const SkRect &src, const SkRect &dst, sk_sp< SkImageFilter > input)
static sk_sp< SkImageFilter > PointLitSpecular(const SkPoint3 &location, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > SpotLitDiffuse(const SkPoint3 &location, const SkPoint3 &target, SkScalar falloffExponent, SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar kd, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > SpotLitSpecular(const SkPoint3 &location, const SkPoint3 &target, SkScalar falloffExponent, SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
void beginObject(const char *name=nullptr, bool multiline=true)
static sk_sp< SkPathEffect > Make(SkScalar width, const SkMatrix &matrix)
static sk_sp< SkMaskFilter > MakeBlur(SkBlurStyle style, SkScalar sigma, bool respectCTM=true)
@ kLast_Cap
largest Cap value
Definition SkPaint.h:337
@ kFill_Style
set to fill geometry
Definition SkPaint.h:193
@ kStrokeAndFill_Style
sets to stroke and fill geometry
Definition SkPaint.h:195
@ kLast_Join
equivalent to the largest value for Join
Definition SkPaint.h:362
static sk_sp< SkPathEffect > Make(const SkPath &path, SkScalar advance, SkScalar phase, Style)
static sk_sp< SkPathEffect > Make(const SkMatrix &matrix, const SkPath &path)
static sk_sp< SkPathEffect > MakeCompose(sk_sp< SkPathEffect > outer, sk_sp< SkPathEffect > inner)
static sk_sp< SkPathEffect > MakeSum(sk_sp< SkPathEffect > first, sk_sp< SkPathEffect > second)
static sk_sp< SkPicture > MakeFromBuffer(SkReadBuffer &buffer)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
const SkRect & getBounds() const
Definition SkRRect.h:279
static std::unique_ptr< SkCanvas > Make(const SkRect &bounds, SkWStream *, uint32_t flags=0)
T * append()
Definition SkTDArray.h:191
const RunBuffer & allocRunPosH(const SkFont &font, int count, SkScalar y, const SkRect *bounds=nullptr)
const RunBuffer & allocRun(const SkFont &font, int count, SkScalar x, SkScalar y, const SkRect *bounds=nullptr)
sk_sp< SkTextBlob > make()
const RunBuffer & allocRunPos(const SkFont &font, int count, const SkRect *bounds=nullptr)
static sk_sp< SkVertices > MakeCopy(VertexMode mode, int vertexCount, const SkPoint positions[], const SkPoint texs[], const SkColor colors[], int indexCount, const uint16_t indices[])
@ kTriangleFan_VertexMode
Definition SkVertices.h:33
T * get() const
Definition SkRefCnt.h:303
const Paint & paint
VkSurfaceKHR surface
Definition main.cc:49
sk_sp< SkImage > image
Definition examples.cpp:29
float SkScalar
Definition extension.cpp:12
struct MyStruct s
glong glong end
static const uint8_t buffer[]
uint8_t value
#define R(r)
size_t length
std::u16string text
double y
double x
SK_API sk_sp< SkImage > RasterFromPixmap(const SkPixmap &pixmap, RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
SK_API sk_sp< SkDocument > MakeDocument(SkWStream *stream, const Metadata &metadata)
constexpr SkCodecs::Decoder Decoder()
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
SK_API sk_sp< SkShader > MakeTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY, int numOctaves, SkScalar seed, const SkISize *tileSize=nullptr)
SK_API sk_sp< SkShader > MakeFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY, int numOctaves, SkScalar seed, const SkISize *tileSize=nullptr)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
SK_SPI size_t ToUTF8(SkUnichar uni, char utf8[kMaxBytesInUTF8Sequence]=nullptr)
SK_SPI size_t ToUTF16(SkUnichar uni, uint16_t utf16[2]=nullptr)
Definition SkUTF.cpp:243
SkFont DefaultFont()
sk_sp< SkFontMgr > TestFontMgr()
static SkRect inset(const SkRect &r)
SkScalar offsetX
SkScalar w
SkScalar offsetY
SkScalar h
#define T
int32_t width
const Scalar scale
Definition SkMD5.cpp:125
const SkRect * fBounds
Definition SkCanvas.h:740
const SkImageFilter * fBackdrop
Definition SkCanvas.h:753
const SkPaint * fPaint
Definition SkCanvas.h:743
static constexpr SkCubicResampler Mitchell()
static sk_sp< SkColorFilter > Make(const SkHighContrastConfig &config)
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37
static SkImageInfo MakeN32Premul(int width, int height)
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static sk_sp< SkColorFilter > Make()
static SkRect Make(const SkISize &size)
Definition SkRect.h:669
bool isFinite() const
Definition SkRect.h:711
static SkRect MakeIWH(int w, int h)
Definition SkRect.h:623
bool contains(SkScalar x, SkScalar y) const
Definition extension.cpp:19
void sort()
Definition SkRect.h:1313
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
SkSerialImageProc fImageProc