2017-02-14 18:35:14 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2017 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "fuzz/Fuzz.h"
|
|
|
|
#include "fuzz/FuzzCommon.h"
|
2017-02-14 18:35:14 +00:00
|
|
|
|
|
|
|
// CORE
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkCanvas.h"
|
|
|
|
#include "include/core/SkColorFilter.h"
|
|
|
|
#include "include/core/SkFontMgr.h"
|
|
|
|
#include "include/core/SkImageFilter.h"
|
|
|
|
#include "include/core/SkMaskFilter.h"
|
|
|
|
#include "include/core/SkPathEffect.h"
|
|
|
|
#include "include/core/SkPictureRecorder.h"
|
|
|
|
#include "include/core/SkPoint3.h"
|
|
|
|
#include "include/core/SkRSXform.h"
|
|
|
|
#include "include/core/SkRegion.h"
|
|
|
|
#include "include/core/SkSurface.h"
|
|
|
|
#include "include/core/SkTypeface.h"
|
|
|
|
#include "include/docs/SkPDFDocument.h"
|
|
|
|
#include "include/private/SkTo.h"
|
2020-07-01 13:21:03 +00:00
|
|
|
#include "include/svg/SkSVGCanvas.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/utils/SkNullCanvas.h"
|
|
|
|
#include "src/core/SkOSFile.h"
|
2020-12-19 20:14:06 +00:00
|
|
|
#include "src/core/SkPaintPriv.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/core/SkPicturePriv.h"
|
|
|
|
#include "tools/debugger/DebugCanvas.h"
|
2017-02-14 18:35:14 +00:00
|
|
|
|
|
|
|
// EFFECTS
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkTextBlob.h"
|
|
|
|
#include "include/effects/Sk1DPathEffect.h"
|
|
|
|
#include "include/effects/Sk2DPathEffect.h"
|
|
|
|
#include "include/effects/SkColorMatrixFilter.h"
|
|
|
|
#include "include/effects/SkCornerPathEffect.h"
|
|
|
|
#include "include/effects/SkDashPathEffect.h"
|
|
|
|
#include "include/effects/SkDiscretePathEffect.h"
|
|
|
|
#include "include/effects/SkGradientShader.h"
|
|
|
|
#include "include/effects/SkHighContrastFilter.h"
|
2019-08-01 20:38:46 +00:00
|
|
|
#include "include/effects/SkImageFilters.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/effects/SkLumaColorFilter.h"
|
|
|
|
#include "include/effects/SkPerlinNoiseShader.h"
|
|
|
|
#include "include/effects/SkTableColorFilter.h"
|
|
|
|
#include "src/core/SkReadBuffer.h"
|
2017-02-14 18:35:14 +00:00
|
|
|
|
|
|
|
// SRC
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/utils/SkUTF.h"
|
|
|
|
#include "tools/flags/CommandLineFlags.h"
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2020-03-19 19:54:28 +00:00
|
|
|
#ifdef SK_GL
|
2020-07-01 20:59:17 +00:00
|
|
|
#include "include/gpu/GrDirectContext.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/gpu/gl/GrGLFunctions.h"
|
2020-10-14 15:23:11 +00:00
|
|
|
#include "src/gpu/GrDirectContextPriv.h"
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "src/gpu/gl/GrGLGpu.h"
|
|
|
|
#include "src/gpu/gl/GrGLUtil.h"
|
|
|
|
#include "tools/gpu/GrContextFactory.h"
|
2017-03-15 15:39:06 +00:00
|
|
|
#endif
|
|
|
|
|
2017-03-01 15:42:45 +00:00
|
|
|
// MISC
|
|
|
|
|
|
|
|
#include <iostream>
|
2018-06-18 19:11:00 +00:00
|
|
|
#include <utility>
|
2017-03-01 15:42:45 +00:00
|
|
|
|
2019-03-21 16:31:36 +00:00
|
|
|
static DEFINE_bool2(gpuInfo, g, false, "Display GPU information on relevant targets.");
|
2018-06-07 14:33:11 +00:00
|
|
|
|
2017-02-14 18:35:14 +00:00
|
|
|
// TODO:
|
2017-03-08 21:52:18 +00:00
|
|
|
// SkTextBlob with Unicode
|
2017-03-15 15:39:06 +00:00
|
|
|
// SkImage: more types
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
// be careful: `foo(make_fuzz_t<T>(f), make_fuzz_t<U>(f))` is undefined.
|
|
|
|
// In fact, all make_fuzz_foo() functions have this potential problem.
|
|
|
|
// Use sequence points!
|
|
|
|
template <typename T>
|
|
|
|
inline T make_fuzz_t(Fuzz* fuzz) {
|
|
|
|
T t;
|
|
|
|
fuzz->next(&t);
|
|
|
|
return t;
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkImage> make_fuzz_image(Fuzz*);
|
2017-02-27 18:36:38 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkPicture> make_fuzz_picture(Fuzz*, int depth);
|
2017-02-27 18:36:38 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkColorFilter> make_fuzz_colorfilter(Fuzz* fuzz, int depth) {
|
2017-03-07 21:23:20 +00:00
|
|
|
if (depth <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
int colorFilterType;
|
|
|
|
fuzz->nextRange(&colorFilterType, 0, 8);
|
|
|
|
switch (colorFilterType) {
|
|
|
|
case 0:
|
|
|
|
return nullptr;
|
|
|
|
case 1: {
|
|
|
|
SkColor color;
|
|
|
|
SkBlendMode mode;
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&color);
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
|
2019-04-08 20:23:20 +00:00
|
|
|
return SkColorFilters::Blend(color, mode);
|
2017-03-07 21:23:20 +00:00
|
|
|
}
|
|
|
|
case 2: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkColorFilter> outer = make_fuzz_colorfilter(fuzz, depth - 1);
|
2018-02-21 13:07:26 +00:00
|
|
|
if (!outer) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkColorFilter> inner = make_fuzz_colorfilter(fuzz, depth - 1);
|
2018-02-21 13:07:26 +00:00
|
|
|
// makeComposed should be able to handle nullptr.
|
2018-02-19 19:10:57 +00:00
|
|
|
return outer->makeComposed(std::move(inner));
|
2017-03-07 21:23:20 +00:00
|
|
|
}
|
|
|
|
case 3: {
|
2019-04-30 16:18:54 +00:00
|
|
|
float array[20];
|
2017-03-07 21:23:20 +00:00
|
|
|
fuzz->nextN(array, SK_ARRAY_COUNT(array));
|
2019-04-30 16:18:54 +00:00
|
|
|
return SkColorFilters::Matrix(array);
|
2017-03-07 21:23:20 +00:00
|
|
|
}
|
|
|
|
case 4: {
|
|
|
|
SkColor mul, add;
|
|
|
|
fuzz->next(&mul, &add);
|
|
|
|
return SkColorMatrixFilter::MakeLightingFilter(mul, add);
|
|
|
|
}
|
|
|
|
case 5: {
|
|
|
|
bool grayscale;
|
|
|
|
int invertStyle;
|
|
|
|
float contrast;
|
|
|
|
fuzz->next(&grayscale);
|
|
|
|
fuzz->nextRange(&invertStyle, 0, 2);
|
|
|
|
fuzz->nextRange(&contrast, -1.0f, 1.0f);
|
|
|
|
return SkHighContrastFilter::Make(SkHighContrastConfig(
|
|
|
|
grayscale, SkHighContrastConfig::InvertStyle(invertStyle), contrast));
|
|
|
|
}
|
|
|
|
case 6:
|
|
|
|
return SkLumaColorFilter::Make();
|
|
|
|
case 7: {
|
|
|
|
uint8_t table[256];
|
|
|
|
fuzz->nextN(table, SK_ARRAY_COUNT(table));
|
|
|
|
return SkTableColorFilter::Make(table);
|
|
|
|
}
|
|
|
|
case 8: {
|
|
|
|
uint8_t tableA[256];
|
|
|
|
uint8_t tableR[256];
|
|
|
|
uint8_t tableG[256];
|
|
|
|
uint8_t tableB[256];
|
|
|
|
fuzz->nextN(tableA, SK_ARRAY_COUNT(tableA));
|
|
|
|
fuzz->nextN(tableR, SK_ARRAY_COUNT(tableR));
|
|
|
|
fuzz->nextN(tableG, SK_ARRAY_COUNT(tableG));
|
|
|
|
fuzz->nextN(tableB, SK_ARRAY_COUNT(tableB));
|
|
|
|
return SkTableColorFilter::MakeARGB(tableA, tableR, tableG, tableB);
|
|
|
|
}
|
2018-01-11 19:50:21 +00:00
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
|
|
|
break;
|
2017-03-07 21:23:20 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static void fuzz_gradient_stops(Fuzz* fuzz, SkScalar* pos, int colorCount) {
|
2017-02-14 18:35:14 +00:00
|
|
|
SkScalar totalPos = 0;
|
|
|
|
for (int i = 0; i < colorCount; ++i) {
|
|
|
|
fuzz->nextRange(&pos[i], 1.0f, 1024.0f);
|
|
|
|
totalPos += pos[i];
|
|
|
|
}
|
|
|
|
totalPos = 1.0f / totalPos;
|
|
|
|
for (int i = 0; i < colorCount; ++i) {
|
|
|
|
pos[i] *= totalPos;
|
|
|
|
}
|
2017-03-08 16:02:40 +00:00
|
|
|
// SkASSERT(fabs(pos[colorCount - 1] - 1.0f) < 0.00001f);
|
2017-02-14 18:35:14 +00:00
|
|
|
pos[colorCount - 1] = 1.0f;
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkShader> make_fuzz_shader(Fuzz* fuzz, int depth) {
|
2017-02-14 18:35:14 +00:00
|
|
|
sk_sp<SkShader> shader1(nullptr), shader2(nullptr);
|
|
|
|
sk_sp<SkColorFilter> colorFilter(nullptr);
|
|
|
|
SkBitmap bitmap;
|
|
|
|
sk_sp<SkImage> img;
|
2019-04-03 14:27:45 +00:00
|
|
|
SkTileMode tmX, tmY;
|
2017-02-14 18:35:14 +00:00
|
|
|
bool useMatrix;
|
|
|
|
SkColor color;
|
|
|
|
SkMatrix matrix;
|
|
|
|
SkBlendMode blendMode;
|
|
|
|
int shaderType;
|
|
|
|
if (depth <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-02-27 18:36:38 +00:00
|
|
|
fuzz->nextRange(&shaderType, 0, 14);
|
2017-02-14 18:35:14 +00:00
|
|
|
switch (shaderType) {
|
|
|
|
case 0:
|
|
|
|
return nullptr;
|
|
|
|
case 1:
|
2019-04-09 17:55:36 +00:00
|
|
|
return SkShaders::Empty();
|
2017-02-14 18:35:14 +00:00
|
|
|
case 2:
|
|
|
|
fuzz->next(&color);
|
2019-04-09 17:55:36 +00:00
|
|
|
return SkShaders::Color(color);
|
2017-02-14 18:35:14 +00:00
|
|
|
case 3:
|
2017-03-10 18:56:08 +00:00
|
|
|
img = make_fuzz_image(fuzz);
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
|
|
|
fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useMatrix);
|
2017-02-14 18:35:14 +00:00
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2020-12-08 18:16:56 +00:00
|
|
|
return img->makeShader(tmX, tmY, SkSamplingOptions(), useMatrix ? &matrix : nullptr);
|
2017-02-14 18:35:14 +00:00
|
|
|
case 5:
|
2017-03-10 18:56:08 +00:00
|
|
|
shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-02-14 18:35:14 +00:00
|
|
|
return shader1 ? shader1->makeWithLocalMatrix(matrix) : nullptr;
|
|
|
|
case 6:
|
2017-03-10 18:56:08 +00:00
|
|
|
shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
|
|
|
|
colorFilter = make_fuzz_colorfilter(fuzz, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
return shader1 ? shader1->makeWithColorFilter(std::move(colorFilter)) : nullptr;
|
|
|
|
case 7:
|
2017-03-10 18:56:08 +00:00
|
|
|
shader1 = make_fuzz_shader(fuzz, depth - 1); // limit recursion.
|
|
|
|
shader2 = make_fuzz_shader(fuzz, depth - 1);
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
|
2019-04-09 17:55:36 +00:00
|
|
|
return SkShaders::Blend(blendMode, std::move(shader1), std::move(shader2));
|
2017-03-08 16:02:40 +00:00
|
|
|
case 8: {
|
2017-03-10 18:56:08 +00:00
|
|
|
auto pic = make_fuzz_picture(fuzz, depth - 1);
|
2017-03-08 16:02:40 +00:00
|
|
|
bool useTile;
|
|
|
|
SkRect tile;
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
|
|
|
fuzz->nextEnum(&tmY, SkTileMode::kLastTileMode);
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useMatrix, &useTile);
|
2017-03-08 16:02:40 +00:00
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
if (useTile) {
|
|
|
|
fuzz->next(&tile);
|
2017-02-27 18:36:38 +00:00
|
|
|
}
|
2021-03-18 21:18:58 +00:00
|
|
|
return pic->makeShader(tmX, tmY, SkFilterMode::kNearest,
|
|
|
|
useMatrix ? &matrix : nullptr, useTile ? &tile : nullptr);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
2017-02-27 18:36:38 +00:00
|
|
|
// EFFECTS:
|
2017-02-14 18:35:14 +00:00
|
|
|
case 9:
|
2017-05-31 14:20:12 +00:00
|
|
|
// Deprecated SkGaussianEdgeShader
|
|
|
|
return nullptr;
|
2017-03-08 16:02:40 +00:00
|
|
|
case 10: {
|
|
|
|
constexpr int kMaxColors = 12;
|
|
|
|
SkPoint pts[2];
|
|
|
|
SkColor colors[kMaxColors];
|
|
|
|
SkScalar pos[kMaxColors];
|
|
|
|
int colorCount;
|
|
|
|
bool usePos;
|
|
|
|
fuzz->nextN(pts, 2);
|
|
|
|
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
|
|
|
fuzz->nextN(colors, colorCount);
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useMatrix, &usePos);
|
2017-03-08 16:02:40 +00:00
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2017-03-08 16:02:40 +00:00
|
|
|
if (usePos) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_gradient_stops(fuzz, pos, colorCount);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
return SkGradientShader::MakeLinear(pts, colors, usePos ? pos : nullptr, colorCount,
|
|
|
|
tmX, 0, useMatrix ? &matrix : nullptr);
|
|
|
|
}
|
|
|
|
case 11: {
|
|
|
|
constexpr int kMaxColors = 12;
|
|
|
|
SkPoint center;
|
|
|
|
SkScalar radius;
|
|
|
|
int colorCount;
|
|
|
|
bool usePos;
|
|
|
|
SkColor colors[kMaxColors];
|
|
|
|
SkScalar pos[kMaxColors];
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useMatrix, &usePos, ¢er, &radius);
|
2017-03-08 16:02:40 +00:00
|
|
|
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
|
|
|
fuzz->nextN(colors, colorCount);
|
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
if (usePos) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_gradient_stops(fuzz, pos, colorCount);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
return SkGradientShader::MakeRadial(center, radius, colors, usePos ? pos : nullptr,
|
|
|
|
colorCount, tmX, 0, useMatrix ? &matrix : nullptr);
|
|
|
|
}
|
|
|
|
case 12: {
|
|
|
|
constexpr int kMaxColors = 12;
|
|
|
|
SkPoint start, end;
|
|
|
|
SkScalar startRadius, endRadius;
|
|
|
|
int colorCount;
|
|
|
|
bool usePos;
|
|
|
|
SkColor colors[kMaxColors];
|
|
|
|
SkScalar pos[kMaxColors];
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&tmX, SkTileMode::kLastTileMode);
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useMatrix, &usePos, &startRadius, &endRadius, &start, &end);
|
2017-03-08 16:02:40 +00:00
|
|
|
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
|
|
|
fuzz->nextN(colors, colorCount);
|
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
if (usePos) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_gradient_stops(fuzz, pos, colorCount);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
return SkGradientShader::MakeTwoPointConical(start, startRadius, end, endRadius, colors,
|
|
|
|
usePos ? pos : nullptr, colorCount, tmX, 0,
|
|
|
|
useMatrix ? &matrix : nullptr);
|
|
|
|
}
|
|
|
|
case 13: {
|
|
|
|
constexpr int kMaxColors = 12;
|
|
|
|
SkScalar cx, cy;
|
|
|
|
int colorCount;
|
|
|
|
bool usePos;
|
|
|
|
SkColor colors[kMaxColors];
|
|
|
|
SkScalar pos[kMaxColors];
|
|
|
|
fuzz->next(&cx, &cy, &useMatrix, &usePos);
|
|
|
|
fuzz->nextRange(&colorCount, 2, kMaxColors);
|
|
|
|
fuzz->nextN(colors, colorCount);
|
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
if (usePos) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_gradient_stops(fuzz, pos, colorCount);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
return SkGradientShader::MakeSweep(cx, cy, colors, usePos ? pos : nullptr, colorCount,
|
|
|
|
0, useMatrix ? &matrix : nullptr);
|
|
|
|
}
|
|
|
|
case 14: {
|
|
|
|
SkScalar baseFrequencyX, baseFrequencyY, seed;
|
|
|
|
int numOctaves;
|
|
|
|
SkISize tileSize;
|
|
|
|
bool useTileSize, turbulence;
|
|
|
|
fuzz->next(&baseFrequencyX, &baseFrequencyY, &seed, &useTileSize, &turbulence);
|
|
|
|
if (useTileSize) {
|
|
|
|
fuzz->next(&tileSize);
|
|
|
|
}
|
|
|
|
fuzz->nextRange(&numOctaves, 2, 7);
|
|
|
|
if (turbulence) {
|
|
|
|
return SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY,
|
|
|
|
numOctaves, seed,
|
|
|
|
useTileSize ? &tileSize : nullptr);
|
|
|
|
} else {
|
|
|
|
return SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY,
|
|
|
|
numOctaves, seed,
|
|
|
|
useTileSize ? &tileSize : nullptr);
|
|
|
|
}
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
default:
|
2018-01-11 19:50:21 +00:00
|
|
|
SkASSERT(false);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2017-02-27 21:45:32 +00:00
|
|
|
return nullptr;
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkPathEffect> make_fuzz_patheffect(Fuzz* fuzz, int depth) {
|
2017-03-08 21:52:18 +00:00
|
|
|
if (depth <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
uint8_t pathEffectType;
|
2017-07-23 02:12:59 +00:00
|
|
|
fuzz->nextRange(&pathEffectType, 0, 8);
|
2017-03-08 21:52:18 +00:00
|
|
|
switch (pathEffectType) {
|
|
|
|
case 0: {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
case 1: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
|
|
|
|
sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
|
2017-03-08 21:52:18 +00:00
|
|
|
return SkPathEffect::MakeSum(std::move(first), std::move(second));
|
|
|
|
}
|
|
|
|
case 2: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkPathEffect> first = make_fuzz_patheffect(fuzz, depth - 1);
|
|
|
|
sk_sp<SkPathEffect> second = make_fuzz_patheffect(fuzz, depth - 1);
|
2017-03-08 21:52:18 +00:00
|
|
|
return SkPathEffect::MakeCompose(std::move(first), std::move(second));
|
|
|
|
}
|
|
|
|
case 3: {
|
|
|
|
SkPath path;
|
2018-09-25 16:16:53 +00:00
|
|
|
FuzzNicePath(fuzz, &path, 20);
|
2017-03-08 21:52:18 +00:00
|
|
|
SkScalar advance, phase;
|
|
|
|
fuzz->next(&advance, &phase);
|
2017-03-10 13:48:28 +00:00
|
|
|
SkPath1DPathEffect::Style style;
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&style, SkPath1DPathEffect::kLastEnum_Style);
|
2017-03-10 13:48:28 +00:00
|
|
|
return SkPath1DPathEffect::Make(path, advance, phase, style);
|
2017-03-08 21:52:18 +00:00
|
|
|
}
|
|
|
|
case 4: {
|
|
|
|
SkScalar width;
|
|
|
|
SkMatrix matrix;
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&width);
|
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 21:52:18 +00:00
|
|
|
return SkLine2DPathEffect::Make(width, matrix);
|
|
|
|
}
|
|
|
|
case 5: {
|
|
|
|
SkPath path;
|
2018-09-25 16:16:53 +00:00
|
|
|
FuzzNicePath(fuzz, &path, 20);
|
2017-03-08 21:52:18 +00:00
|
|
|
SkMatrix matrix;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-03-08 21:52:18 +00:00
|
|
|
return SkPath2DPathEffect::Make(matrix, path);
|
|
|
|
}
|
|
|
|
case 6: {
|
|
|
|
SkScalar radius;
|
|
|
|
fuzz->next(&radius);
|
|
|
|
return SkCornerPathEffect::Make(radius);
|
|
|
|
}
|
2017-07-23 02:12:59 +00:00
|
|
|
case 7: {
|
2017-03-08 21:52:18 +00:00
|
|
|
SkScalar phase;
|
|
|
|
fuzz->next(&phase);
|
|
|
|
SkScalar intervals[20];
|
|
|
|
int count;
|
|
|
|
fuzz->nextRange(&count, 0, (int)SK_ARRAY_COUNT(intervals));
|
|
|
|
fuzz->nextN(intervals, count);
|
|
|
|
return SkDashPathEffect::Make(intervals, count, phase);
|
|
|
|
}
|
2017-07-23 02:12:59 +00:00
|
|
|
case 8: {
|
2017-03-08 21:52:18 +00:00
|
|
|
SkScalar segLength, dev;
|
|
|
|
uint32_t seed;
|
|
|
|
fuzz->next(&segLength, &dev, &seed);
|
|
|
|
return SkDiscretePathEffect::Make(segLength, dev, seed);
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkMaskFilter> make_fuzz_maskfilter(Fuzz* fuzz) {
|
2017-03-08 21:52:18 +00:00
|
|
|
int maskfilterType;
|
2018-04-18 14:05:00 +00:00
|
|
|
fuzz->nextRange(&maskfilterType, 0, 1);
|
2017-03-08 21:52:18 +00:00
|
|
|
switch (maskfilterType) {
|
|
|
|
case 0:
|
|
|
|
return nullptr;
|
|
|
|
case 1: {
|
2017-03-10 13:48:28 +00:00
|
|
|
SkBlurStyle blurStyle;
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&blurStyle, kLastEnum_SkBlurStyle);
|
2017-03-08 21:52:18 +00:00
|
|
|
SkScalar sigma;
|
|
|
|
fuzz->next(&sigma);
|
2018-06-04 21:02:46 +00:00
|
|
|
bool respectCTM;
|
|
|
|
fuzz->next(&respectCTM);
|
|
|
|
return SkMaskFilter::MakeBlur(blurStyle, sigma, respectCTM);
|
2017-03-08 21:52:18 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkTypeface> make_fuzz_typeface(Fuzz* fuzz) {
|
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
2017-02-27 18:36:38 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
auto fontMugger = SkFontMgr::RefDefault();
|
|
|
|
SkASSERT(fontMugger);
|
|
|
|
int familyCount = fontMugger->countFamilies();
|
|
|
|
int i, j;
|
|
|
|
fuzz->nextRange(&i, 0, familyCount - 1);
|
|
|
|
sk_sp<SkFontStyleSet> family(fontMugger->createStyleSet(i));
|
|
|
|
int styleCount = family->count();
|
|
|
|
fuzz->nextRange(&j, 0, styleCount - 1);
|
|
|
|
return sk_sp<SkTypeface>(family->createTypeface(j));
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth);
|
2017-03-09 16:33:35 +00:00
|
|
|
|
|
|
|
static sk_sp<SkImageFilter> make_fuzz_lighting_imagefilter(Fuzz* fuzz, int depth) {
|
|
|
|
if (depth <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
uint8_t imageFilterType;
|
|
|
|
fuzz->nextRange(&imageFilterType, 1, 6);
|
|
|
|
SkPoint3 p, q;
|
|
|
|
SkColor lightColor;
|
|
|
|
SkScalar surfaceScale, k, specularExponent, cutoffAngle, shininess;
|
|
|
|
sk_sp<SkImageFilter> input;
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
|
|
|
if (useCropRect) {
|
|
|
|
fuzz->next(&cropRect);
|
|
|
|
}
|
|
|
|
switch (imageFilterType) {
|
|
|
|
case 1:
|
|
|
|
fuzz->next(&p, &lightColor, &surfaceScale, &k);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::DistantLitDiffuse(p, lightColor, surfaceScale, k,
|
|
|
|
std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
case 2:
|
|
|
|
fuzz->next(&p, &lightColor, &surfaceScale, &k);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::PointLitDiffuse(p, lightColor, surfaceScale, k,
|
|
|
|
std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
case 3:
|
|
|
|
fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::SpotLitDiffuse(
|
2017-03-09 16:33:35 +00:00
|
|
|
p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k,
|
|
|
|
std::move(input), useCropRect ? &cropRect : nullptr);
|
|
|
|
case 4:
|
|
|
|
fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::DistantLitSpecular(p, lightColor, surfaceScale, k,
|
|
|
|
shininess, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
case 5:
|
|
|
|
fuzz->next(&p, &lightColor, &surfaceScale, &k, &shininess);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::PointLitSpecular(p, lightColor, surfaceScale, k,
|
|
|
|
shininess, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
case 6:
|
|
|
|
fuzz->next(&p, &q, &specularExponent, &cutoffAngle, &lightColor, &surfaceScale, &k,
|
|
|
|
&shininess);
|
2017-03-10 18:56:08 +00:00
|
|
|
input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::SpotLitSpecular(
|
2017-03-09 16:33:35 +00:00
|
|
|
p, q, specularExponent, cutoffAngle, lightColor, surfaceScale, k, shininess,
|
|
|
|
std::move(input), useCropRect ? &cropRect : nullptr);
|
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth);
|
2017-03-09 16:33:35 +00:00
|
|
|
|
2021-07-18 14:54:25 +00:00
|
|
|
static SkSamplingOptions next_sampling(Fuzz* fuzz) {
|
|
|
|
if (fuzz->nextBool()) {
|
|
|
|
float B, C;
|
|
|
|
fuzz->next(&B, &C);
|
|
|
|
return SkSamplingOptions({B, C});
|
|
|
|
} else {
|
|
|
|
SkFilterMode fm;
|
|
|
|
SkMipmapMode mm;
|
|
|
|
fuzz->nextEnum(&fm, SkFilterMode::kLast);
|
|
|
|
fuzz->nextEnum(&mm, SkMipmapMode::kLast);
|
|
|
|
return SkSamplingOptions(fm, mm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkImageFilter> make_fuzz_imageFilter(Fuzz* fuzz, int depth) {
|
2017-03-09 16:33:35 +00:00
|
|
|
if (depth <= 0) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
uint8_t imageFilterType;
|
Add SkImageFilters::Shader in place of Paint factory
SkImageFilters::Paint did not use every slot of the SkPaint, with only
its color, alpha, color filter, and shader having a meaningful effect on
the image filter result. It was always blended into a transparent dst,
so blend mode wasn't very relevant, and it was always filled to whatever
required geometry, so stroke style, path effect, and mask filters were
ignored or not well specified.
Color, alpha, and color filter can all be combined into an SkShader, so
a more constrained SkImageFilters::Shader provides the same useful
capabilities without as many surprises.
SkImageFilters::Paint still exists, but is deprecated to be removed
once I've confirmed clients aren't depending on it.
Bug: skia:9310
Change-Id: I11a82bda1a5d440726cf4e2b5bfaae4929568679
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323680
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-10-07 19:27:20 +00:00
|
|
|
fuzz->nextRange(&imageFilterType, 0, 24);
|
2017-03-09 16:33:35 +00:00
|
|
|
switch (imageFilterType) {
|
|
|
|
case 0:
|
|
|
|
return nullptr;
|
|
|
|
case 1: {
|
|
|
|
SkScalar sigmaX, sigmaY;
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&sigmaX, &sigmaY, &useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Blur(sigmaX, sigmaY, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 2: {
|
|
|
|
SkMatrix matrix;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2021-07-18 14:54:25 +00:00
|
|
|
const auto sampling = next_sampling(fuzz);
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2021-02-01 18:07:32 +00:00
|
|
|
return SkImageFilters::MatrixTransform(matrix, sampling, std::move(input));
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 3: {
|
|
|
|
SkRegion region;
|
|
|
|
SkScalar innerMin, outerMax;
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(®ion, &innerMin, &outerMax, &useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::AlphaThreshold(region, innerMin, outerMax, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 4: {
|
|
|
|
float k1, k2, k3, k4;
|
|
|
|
bool enforcePMColor;
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&k1, &k2, &k3, &k4, &enforcePMColor, &useCropRect);
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> background = make_fuzz_imageFilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> foreground = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Arithmetic(k1, k2, k3, k4, enforcePMColor,
|
|
|
|
std::move(background), std::move(foreground),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 5: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkColorFilter> cf = make_fuzz_colorfilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
fuzz->next(&useCropRect);
|
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::ColorFilter(std::move(cf), std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 6: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> ifo = make_fuzz_imageFilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> ifi = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Compose(std::move(ifo), std::move(ifi));
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 7: {
|
2019-08-01 20:38:46 +00:00
|
|
|
SkColorChannel xChannelSelector, yChannelSelector;
|
|
|
|
fuzz->nextEnum(&xChannelSelector, SkColorChannel::kLastEnum);
|
|
|
|
fuzz->nextEnum(&yChannelSelector, SkColorChannel::kLastEnum);
|
2017-03-09 16:33:35 +00:00
|
|
|
SkScalar scale;
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&scale, &useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> displacement = make_fuzz_imageFilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> color = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::DisplacementMap(xChannelSelector, yChannelSelector, scale,
|
|
|
|
std::move(displacement), std::move(color),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 8: {
|
|
|
|
SkScalar dx, dy, sigmaX, sigmaY;
|
|
|
|
SkColor color;
|
2019-08-01 20:38:46 +00:00
|
|
|
bool shadowOnly, useCropRect;
|
|
|
|
fuzz->next(&dx, &dy, &sigmaX, &sigmaY, &color, &shadowOnly, &useCropRect);
|
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
if (shadowOnly) {
|
|
|
|
return SkImageFilters::DropShadowOnly(dx, dy, sigmaX, sigmaY, color,
|
|
|
|
std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
|
|
|
} else {
|
|
|
|
return SkImageFilters::DropShadow(dx, dy, sigmaX, sigmaY, color, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
|
|
|
}
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 9:
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Image(make_fuzz_image(fuzz));
|
2017-03-09 16:33:35 +00:00
|
|
|
case 10: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImage> image = make_fuzz_image(fuzz);
|
2017-03-09 16:33:35 +00:00
|
|
|
SkRect srcRect, dstRect;
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&srcRect, &dstRect);
|
2021-07-18 14:54:25 +00:00
|
|
|
return SkImageFilters::Image(std::move(image), srcRect, dstRect, next_sampling(fuzz));
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 11:
|
|
|
|
return make_fuzz_lighting_imagefilter(fuzz, depth - 1);
|
|
|
|
case 12: {
|
|
|
|
SkRect srcRect;
|
|
|
|
SkScalar inset;
|
|
|
|
bool useCropRect;
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
fuzz->next(&srcRect, &inset, &useCropRect);
|
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Magnifier(srcRect, inset, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 13: {
|
|
|
|
constexpr int kMaxKernelSize = 5;
|
|
|
|
int32_t n, m;
|
|
|
|
fuzz->nextRange(&n, 1, kMaxKernelSize);
|
|
|
|
fuzz->nextRange(&m, 1, kMaxKernelSize);
|
|
|
|
SkScalar kernel[kMaxKernelSize * kMaxKernelSize];
|
|
|
|
fuzz->nextN(kernel, n * m);
|
|
|
|
int32_t offsetX, offsetY;
|
|
|
|
fuzz->nextRange(&offsetX, 0, n - 1);
|
|
|
|
fuzz->nextRange(&offsetY, 0, m - 1);
|
|
|
|
SkScalar gain, bias;
|
|
|
|
bool convolveAlpha, useCropRect;
|
|
|
|
fuzz->next(&gain, &bias, &convolveAlpha, &useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkTileMode tileMode;
|
|
|
|
fuzz->nextEnum(&tileMode, SkTileMode::kLastTileMode);
|
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::MatrixConvolution(
|
2017-03-09 16:33:35 +00:00
|
|
|
SkISize{n, m}, kernel, gain, bias, SkIPoint{offsetX, offsetY}, tileMode,
|
|
|
|
convolveAlpha, std::move(input), useCropRect ? &cropRect : nullptr);
|
|
|
|
}
|
|
|
|
case 14: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> first = make_fuzz_imageFilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> second = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
2017-06-19 03:35:57 +00:00
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Merge(std::move(first), std::move(second),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 15: {
|
|
|
|
constexpr int kMaxCount = 4;
|
|
|
|
sk_sp<SkImageFilter> ifs[kMaxCount];
|
|
|
|
int count;
|
|
|
|
fuzz->nextRange(&count, 1, kMaxCount);
|
|
|
|
for (int i = 0; i < count; ++i) {
|
2017-03-10 18:56:08 +00:00
|
|
|
ifs[i] = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Merge(ifs, count, useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 16: {
|
|
|
|
int rx, ry;
|
|
|
|
fuzz->next(&rx, &ry);
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Dilate(rx, ry, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 17: {
|
|
|
|
int rx, ry;
|
|
|
|
fuzz->next(&rx, &ry);
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Erode(rx, ry, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 18: {
|
|
|
|
SkScalar dx, dy;
|
|
|
|
fuzz->next(&dx, &dy);
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Offset(dx, dy, std::move(input),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 19: {
|
|
|
|
SkPaint paint;
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-03-09 16:33:35 +00:00
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Paint(paint, useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 20: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Picture(std::move(picture));
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 21: {
|
|
|
|
SkRect cropRect;
|
|
|
|
fuzz->next(&cropRect);
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkPicture> picture = make_fuzz_picture(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Picture(std::move(picture), cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
|
|
|
case 22: {
|
|
|
|
SkRect src, dst;
|
|
|
|
fuzz->next(&src, &dst);
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> input = make_fuzz_imageFilter(fuzz, depth - 1);
|
2019-08-01 20:38:46 +00:00
|
|
|
return SkImageFilters::Tile(src, dst, std::move(input));
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-11-09 21:50:20 +00:00
|
|
|
case 23: {
|
2017-03-09 16:33:35 +00:00
|
|
|
SkBlendMode blendMode;
|
|
|
|
bool useCropRect;
|
2018-09-17 18:46:57 +00:00
|
|
|
fuzz->next(&useCropRect);
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&blendMode, SkBlendMode::kLastMode);
|
2019-08-01 20:38:46 +00:00
|
|
|
SkIRect cropRect;
|
2017-03-09 16:33:35 +00:00
|
|
|
if (useCropRect) {
|
2017-03-14 21:20:24 +00:00
|
|
|
fuzz->next(&cropRect);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImageFilter> bg = make_fuzz_imageFilter(fuzz, depth - 1);
|
|
|
|
sk_sp<SkImageFilter> fg = make_fuzz_imageFilter(fuzz, depth - 1);
|
2020-10-09 14:45:07 +00:00
|
|
|
return SkImageFilters::Blend(blendMode, std::move(bg), std::move(fg),
|
|
|
|
useCropRect ? &cropRect : nullptr);
|
2017-03-09 16:33:35 +00:00
|
|
|
}
|
Add SkImageFilters::Shader in place of Paint factory
SkImageFilters::Paint did not use every slot of the SkPaint, with only
its color, alpha, color filter, and shader having a meaningful effect on
the image filter result. It was always blended into a transparent dst,
so blend mode wasn't very relevant, and it was always filled to whatever
required geometry, so stroke style, path effect, and mask filters were
ignored or not well specified.
Color, alpha, and color filter can all be combined into an SkShader, so
a more constrained SkImageFilters::Shader provides the same useful
capabilities without as many surprises.
SkImageFilters::Paint still exists, but is deprecated to be removed
once I've confirmed clients aren't depending on it.
Bug: skia:9310
Change-Id: I11a82bda1a5d440726cf4e2b5bfaae4929568679
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323680
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2020-10-07 19:27:20 +00:00
|
|
|
case 24: {
|
|
|
|
sk_sp<SkShader> shader = make_fuzz_shader(fuzz, depth - 1);
|
|
|
|
bool useCropRect;
|
|
|
|
fuzz->next(&useCropRect);
|
|
|
|
SkIRect cropRect;
|
|
|
|
if (useCropRect) {
|
|
|
|
fuzz->next(&cropRect);
|
|
|
|
}
|
|
|
|
return SkImageFilters::Shader(std::move(shader), useCropRect ? &cropRect : nullptr);
|
|
|
|
}
|
2017-03-09 16:33:35 +00:00
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkImage> make_fuzz_image(Fuzz* fuzz) {
|
2017-02-14 18:35:14 +00:00
|
|
|
int w, h;
|
|
|
|
fuzz->nextRange(&w, 1, 1024);
|
|
|
|
fuzz->nextRange(&h, 1, 1024);
|
|
|
|
SkAutoTMalloc<SkPMColor> data(w * h);
|
|
|
|
SkPixmap pixmap(SkImageInfo::MakeN32Premul(w, h), data.get(), w * sizeof(SkPMColor));
|
|
|
|
int n = w * h;
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
SkColor c;
|
|
|
|
fuzz->next(&c);
|
|
|
|
data[i] = SkPreMultiplyColor(c);
|
|
|
|
}
|
|
|
|
(void)data.release();
|
2017-03-08 16:02:40 +00:00
|
|
|
return SkImage::MakeFromRaster(pixmap, [](const void* p, void*) { sk_free((void*)p); },
|
|
|
|
nullptr);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
|
2019-06-03 15:27:16 +00:00
|
|
|
template <typename T>
|
|
|
|
static T make_fuzz_enum_range(Fuzz* fuzz, T maxv) {
|
2017-03-10 18:56:08 +00:00
|
|
|
T value;
|
2019-06-03 15:27:16 +00:00
|
|
|
fuzz->nextEnum(&value, maxv);
|
2017-03-10 18:56:08 +00:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void fuzz_paint(Fuzz* fuzz, SkPaint* paint, int depth) {
|
2017-02-14 18:35:14 +00:00
|
|
|
if (!fuzz || !paint || depth <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
paint->setAntiAlias( make_fuzz_t<bool>(fuzz));
|
|
|
|
paint->setDither( make_fuzz_t<bool>(fuzz));
|
|
|
|
paint->setColor( make_fuzz_t<SkColor>(fuzz));
|
2019-06-03 15:27:16 +00:00
|
|
|
paint->setBlendMode( make_fuzz_enum_range<SkBlendMode>(fuzz, SkBlendMode::kLastMode));
|
|
|
|
paint->setStyle( make_fuzz_enum_range<SkPaint::Style>(fuzz,
|
|
|
|
SkPaint::Style::kStrokeAndFill_Style));
|
2017-03-10 18:56:08 +00:00
|
|
|
paint->setShader( make_fuzz_shader(fuzz, depth - 1));
|
|
|
|
paint->setPathEffect( make_fuzz_patheffect(fuzz, depth - 1));
|
|
|
|
paint->setMaskFilter( make_fuzz_maskfilter(fuzz));
|
|
|
|
paint->setImageFilter( make_fuzz_imageFilter(fuzz, depth - 1));
|
|
|
|
paint->setColorFilter( make_fuzz_colorfilter(fuzz, depth - 1));
|
2017-02-14 18:35:14 +00:00
|
|
|
|
|
|
|
if (paint->getStyle() != SkPaint::kFill_Style) {
|
2017-03-10 18:56:08 +00:00
|
|
|
paint->setStrokeWidth(make_fuzz_t<SkScalar>(fuzz));
|
|
|
|
paint->setStrokeMiter(make_fuzz_t<SkScalar>(fuzz));
|
2019-06-03 15:27:16 +00:00
|
|
|
paint->setStrokeCap( make_fuzz_enum_range<SkPaint::Cap>(fuzz, SkPaint::kLast_Cap));
|
|
|
|
paint->setStrokeJoin( make_fuzz_enum_range<SkPaint::Join>(fuzz, SkPaint::kLast_Join));
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-23 20:27:51 +00:00
|
|
|
static SkFont fuzz_font(Fuzz* fuzz) {
|
|
|
|
SkFont font;
|
|
|
|
font.setTypeface( make_fuzz_typeface(fuzz));
|
|
|
|
font.setSize( make_fuzz_t<SkScalar>(fuzz));
|
|
|
|
font.setScaleX( make_fuzz_t<SkScalar>(fuzz));
|
|
|
|
font.setSkewX( make_fuzz_t<SkScalar>(fuzz));
|
|
|
|
font.setLinearMetrics( make_fuzz_t<bool>(fuzz));
|
|
|
|
font.setSubpixel( make_fuzz_t<bool>(fuzz));
|
|
|
|
font.setEmbeddedBitmaps( make_fuzz_t<bool>(fuzz));
|
|
|
|
font.setForceAutoHinting( make_fuzz_t<bool>(fuzz));
|
|
|
|
font.setEmbolden( make_fuzz_t<bool>(fuzz));
|
2019-06-03 15:27:16 +00:00
|
|
|
font.setHinting( make_fuzz_enum_range<SkFontHinting>(fuzz, SkFontHinting::kFull));
|
|
|
|
font.setEdging( make_fuzz_enum_range<SkFont::Edging>(fuzz,
|
|
|
|
SkFont::Edging::kSubpixelAntiAlias));
|
2018-11-23 20:27:51 +00:00
|
|
|
return font;
|
2017-03-08 21:52:18 +00:00
|
|
|
}
|
|
|
|
|
2018-11-21 20:10:08 +00:00
|
|
|
static SkTextEncoding fuzz_paint_text_encoding(Fuzz* fuzz) {
|
2019-06-03 15:27:16 +00:00
|
|
|
return make_fuzz_enum_range<SkTextEncoding>(fuzz, SkTextEncoding::kUTF32);
|
2017-02-27 18:36:38 +00:00
|
|
|
}
|
|
|
|
|
2017-03-08 21:52:18 +00:00
|
|
|
constexpr int kMaxGlyphCount = 30;
|
|
|
|
|
2018-11-21 20:10:08 +00:00
|
|
|
static SkTDArray<uint8_t> make_fuzz_text(Fuzz* fuzz, const SkFont& font, SkTextEncoding encoding) {
|
2017-02-27 18:36:38 +00:00
|
|
|
SkTDArray<uint8_t> array;
|
2019-05-07 19:38:46 +00:00
|
|
|
if (SkTextEncoding::kGlyphID == encoding) {
|
2019-01-22 19:45:16 +00:00
|
|
|
int glyphRange = font.getTypefaceOrDefault()->countGlyphs();
|
2018-02-27 15:59:10 +00:00
|
|
|
if (glyphRange == 0) {
|
|
|
|
// Some fuzzing environments have no fonts, so empty array is the best
|
|
|
|
// we can do.
|
|
|
|
return array;
|
|
|
|
}
|
2017-02-27 18:36:38 +00:00
|
|
|
int glyphCount;
|
2017-03-08 21:52:18 +00:00
|
|
|
fuzz->nextRange(&glyphCount, 1, kMaxGlyphCount);
|
2017-02-27 18:36:38 +00:00
|
|
|
SkGlyphID* glyphs = (SkGlyphID*)array.append(glyphCount * sizeof(SkGlyphID));
|
|
|
|
for (int i = 0; i < glyphCount; ++i) {
|
|
|
|
fuzz->nextRange(&glyphs[i], 0, glyphRange - 1);
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
static const SkUnichar ranges[][2] = {
|
|
|
|
{0x0020, 0x007F},
|
|
|
|
{0x00A1, 0x0250},
|
|
|
|
{0x0400, 0x0500},
|
|
|
|
};
|
|
|
|
int32_t count = 0;
|
2017-03-08 16:02:40 +00:00
|
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
|
2017-02-27 18:36:38 +00:00
|
|
|
count += (ranges[i][1] - ranges[i][0]);
|
|
|
|
}
|
2017-03-08 21:52:18 +00:00
|
|
|
constexpr int kMaxLength = kMaxGlyphCount;
|
2017-02-27 18:36:38 +00:00
|
|
|
SkUnichar buffer[kMaxLength];
|
|
|
|
int length;
|
|
|
|
fuzz->nextRange(&length, 1, kMaxLength);
|
|
|
|
for (int j = 0; j < length; ++j) {
|
|
|
|
int32_t value;
|
|
|
|
fuzz->nextRange(&value, 0, count - 1);
|
2017-03-08 16:02:40 +00:00
|
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(ranges); ++i) {
|
2017-02-27 18:36:38 +00:00
|
|
|
if (value + ranges[i][0] < ranges[i][1]) {
|
|
|
|
buffer[j] = value + ranges[i][0];
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
value -= (ranges[i][1] - ranges[i][0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-11-21 20:10:08 +00:00
|
|
|
switch (encoding) {
|
2019-05-07 19:38:46 +00:00
|
|
|
case SkTextEncoding::kUTF8: {
|
2017-03-08 16:02:40 +00:00
|
|
|
size_t utf8len = 0;
|
|
|
|
for (int j = 0; j < length; ++j) {
|
2018-07-25 20:52:48 +00:00
|
|
|
utf8len += SkUTF::ToUTF8(buffer[j], nullptr);
|
2017-02-27 18:36:38 +00:00
|
|
|
}
|
2017-03-08 16:02:40 +00:00
|
|
|
char* ptr = (char*)array.append(utf8len);
|
|
|
|
for (int j = 0; j < length; ++j) {
|
2018-07-25 20:52:48 +00:00
|
|
|
ptr += SkUTF::ToUTF8(buffer[j], ptr);
|
2017-02-27 18:36:38 +00:00
|
|
|
}
|
2017-03-08 16:02:40 +00:00
|
|
|
} break;
|
2019-05-07 19:38:46 +00:00
|
|
|
case SkTextEncoding::kUTF16: {
|
2017-03-08 16:02:40 +00:00
|
|
|
size_t utf16len = 0;
|
|
|
|
for (int j = 0; j < length; ++j) {
|
2018-07-25 20:52:48 +00:00
|
|
|
utf16len += SkUTF::ToUTF16(buffer[j]);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
uint16_t* ptr = (uint16_t*)array.append(utf16len * sizeof(uint16_t));
|
|
|
|
for (int j = 0; j < length; ++j) {
|
2018-07-25 20:52:48 +00:00
|
|
|
ptr += SkUTF::ToUTF16(buffer[j], ptr);
|
2017-03-08 16:02:40 +00:00
|
|
|
}
|
|
|
|
} break;
|
2019-05-07 19:38:46 +00:00
|
|
|
case SkTextEncoding::kUTF32:
|
2017-02-27 18:36:38 +00:00
|
|
|
memcpy(array.append(length * sizeof(SkUnichar)), buffer, length * sizeof(SkUnichar));
|
2017-03-01 20:40:46 +00:00
|
|
|
break;
|
2017-02-27 18:36:38 +00:00
|
|
|
default:
|
2017-03-08 16:02:40 +00:00
|
|
|
SkASSERT(false);
|
2018-01-11 19:50:21 +00:00
|
|
|
break;
|
2017-02-27 18:36:38 +00:00
|
|
|
}
|
|
|
|
return array;
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
|
2020-07-01 13:21:03 +00:00
|
|
|
static std::string make_fuzz_string(Fuzz* fuzz) {
|
|
|
|
int len;
|
|
|
|
fuzz->nextRange(&len, 0, kMaxGlyphCount);
|
|
|
|
std::string str(len, 0);
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
fuzz->next(&str[i]);
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2017-03-08 21:52:18 +00:00
|
|
|
static sk_sp<SkTextBlob> make_fuzz_textblob(Fuzz* fuzz) {
|
|
|
|
SkTextBlobBuilder textBlobBuilder;
|
|
|
|
int8_t runCount;
|
|
|
|
fuzz->nextRange(&runCount, (int8_t)1, (int8_t)8);
|
|
|
|
while (runCount-- > 0) {
|
2018-11-21 20:10:08 +00:00
|
|
|
SkFont font;
|
|
|
|
SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
|
|
|
|
font.setEdging(make_fuzz_t<bool>(fuzz) ? SkFont::Edging::kAlias : SkFont::Edging::kAntiAlias);
|
|
|
|
SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
|
|
|
|
int glyphCount = font.countText(text.begin(), SkToSizeT(text.count()), encoding);
|
2017-03-08 21:52:18 +00:00
|
|
|
SkASSERT(glyphCount <= kMaxGlyphCount);
|
|
|
|
SkScalar x, y;
|
|
|
|
const SkTextBlobBuilder::RunBuffer* buffer;
|
|
|
|
uint8_t runType;
|
|
|
|
fuzz->nextRange(&runType, (uint8_t)0, (uint8_t)2);
|
2018-12-17 18:48:44 +00:00
|
|
|
const void* textPtr = text.begin();
|
|
|
|
size_t textLen = SkToSizeT(text.count());
|
2017-03-08 21:52:18 +00:00
|
|
|
switch (runType) {
|
|
|
|
case 0:
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
// TODO: Test other variations of this.
|
2018-11-21 20:10:08 +00:00
|
|
|
buffer = &textBlobBuilder.allocRun(font, glyphCount, x, y);
|
2018-12-17 18:48:44 +00:00
|
|
|
(void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
|
2017-03-08 21:52:18 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
fuzz->next(&y);
|
|
|
|
// TODO: Test other variations of this.
|
2018-11-21 20:10:08 +00:00
|
|
|
buffer = &textBlobBuilder.allocRunPosH(font, glyphCount, y);
|
2018-12-17 18:48:44 +00:00
|
|
|
(void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
|
2017-03-08 21:52:18 +00:00
|
|
|
fuzz->nextN(buffer->pos, glyphCount);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
// TODO: Test other variations of this.
|
2018-11-21 20:10:08 +00:00
|
|
|
buffer = &textBlobBuilder.allocRunPos(font, glyphCount);
|
2018-12-17 18:48:44 +00:00
|
|
|
(void)font.textToGlyphs(textPtr, textLen, encoding, buffer->glyphs, glyphCount);
|
2017-03-08 21:52:18 +00:00
|
|
|
fuzz->nextN(buffer->pos, glyphCount * 2);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
SkASSERT(false);
|
2018-01-11 19:50:21 +00:00
|
|
|
break;
|
2017-03-08 21:52:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return textBlobBuilder.make();
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static void fuzz_canvas(Fuzz* fuzz, SkCanvas* canvas, int depth = 9) {
|
2017-02-14 18:35:14 +00:00
|
|
|
if (!fuzz || !canvas || depth <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SkAutoCanvasRestore autoCanvasRestore(canvas, false);
|
|
|
|
unsigned N;
|
|
|
|
fuzz->nextRange(&N, 0, 2000);
|
2021-08-16 16:16:29 +00:00
|
|
|
for (unsigned loop = 0; loop < N; ++loop) {
|
2017-02-14 18:35:14 +00:00
|
|
|
if (fuzz->exhausted()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SkPaint paint;
|
2018-11-23 20:27:51 +00:00
|
|
|
SkFont font;
|
2017-02-14 18:35:14 +00:00
|
|
|
unsigned drawCommand;
|
2020-07-01 13:21:03 +00:00
|
|
|
fuzz->nextRange(&drawCommand, 0, 62);
|
2017-02-14 18:35:14 +00:00
|
|
|
switch (drawCommand) {
|
|
|
|
case 0:
|
|
|
|
canvas->flush();
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
canvas->save();
|
|
|
|
break;
|
|
|
|
case 2: {
|
|
|
|
SkRect bounds;
|
|
|
|
fuzz->next(&bounds);
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->saveLayer(&bounds, &paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3: {
|
|
|
|
SkRect bounds;
|
|
|
|
fuzz->next(&bounds);
|
|
|
|
canvas->saveLayer(&bounds, nullptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4:
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->saveLayer(nullptr, &paint);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
canvas->saveLayer(nullptr, nullptr);
|
|
|
|
break;
|
|
|
|
case 6: {
|
|
|
|
uint8_t alpha;
|
|
|
|
fuzz->next(&alpha);
|
|
|
|
canvas->saveLayerAlpha(nullptr, (U8CPU)alpha);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 7: {
|
|
|
|
SkRect bounds;
|
|
|
|
uint8_t alpha;
|
|
|
|
fuzz->next(&bounds, &alpha);
|
|
|
|
canvas->saveLayerAlpha(&bounds, (U8CPU)alpha);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 8: {
|
|
|
|
SkCanvas::SaveLayerRec saveLayerRec;
|
|
|
|
SkRect bounds;
|
2017-03-10 18:56:08 +00:00
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
2017-02-14 18:35:14 +00:00
|
|
|
fuzz->next(&bounds);
|
|
|
|
saveLayerRec.fBounds = &bounds;
|
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
saveLayerRec.fPaint = &paint;
|
|
|
|
}
|
|
|
|
sk_sp<SkImageFilter> imageFilter;
|
2017-03-10 18:56:08 +00:00
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
|
|
|
imageFilter = make_fuzz_imageFilter(fuzz, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
saveLayerRec.fBackdrop = imageFilter.get();
|
|
|
|
}
|
2017-03-08 21:52:18 +00:00
|
|
|
// _DumpCanvas can't handle this.
|
2017-03-10 18:56:08 +00:00
|
|
|
// if (make_fuzz_t<bool>(fuzz)) {
|
2017-03-08 21:52:18 +00:00
|
|
|
// saveLayerRec.fSaveLayerFlags |= SkCanvas::kPreserveLCDText_SaveLayerFlag;
|
|
|
|
// }
|
|
|
|
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->saveLayer(saveLayerRec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 9:
|
|
|
|
canvas->restore();
|
|
|
|
break;
|
|
|
|
case 10: {
|
|
|
|
int saveCount;
|
|
|
|
fuzz->next(&saveCount);
|
|
|
|
canvas->restoreToCount(saveCount);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 11: {
|
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
canvas->translate(x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 12: {
|
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
canvas->scale(x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 13: {
|
|
|
|
SkScalar v;
|
|
|
|
fuzz->next(&v);
|
|
|
|
canvas->rotate(v);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 14: {
|
|
|
|
SkScalar x, y, v;
|
|
|
|
fuzz->next(&x, &y, &v);
|
|
|
|
canvas->rotate(v, x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 15: {
|
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
canvas->skew(x, y);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 16: {
|
|
|
|
SkMatrix mat;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &mat);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->concat(mat);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 17: {
|
|
|
|
SkMatrix mat;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &mat);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->setMatrix(mat);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 18:
|
|
|
|
canvas->resetMatrix();
|
|
|
|
break;
|
|
|
|
case 19: {
|
|
|
|
SkRect r;
|
|
|
|
int op;
|
|
|
|
bool doAntiAlias;
|
|
|
|
fuzz->next(&r, &doAntiAlias);
|
|
|
|
fuzz->nextRange(&op, 0, 1);
|
|
|
|
r.sort();
|
|
|
|
canvas->clipRect(r, (SkClipOp)op, doAntiAlias);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 20: {
|
|
|
|
SkRRect rr;
|
|
|
|
int op;
|
|
|
|
bool doAntiAlias;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceRRect(fuzz, &rr);
|
2017-02-14 18:35:14 +00:00
|
|
|
fuzz->next(&doAntiAlias);
|
|
|
|
fuzz->nextRange(&op, 0, 1);
|
|
|
|
canvas->clipRRect(rr, (SkClipOp)op, doAntiAlias);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 21: {
|
|
|
|
SkPath path;
|
2018-09-25 16:16:53 +00:00
|
|
|
FuzzNicePath(fuzz, &path, 30);
|
2017-02-14 18:35:14 +00:00
|
|
|
int op;
|
|
|
|
bool doAntiAlias;
|
|
|
|
fuzz->next(&doAntiAlias);
|
|
|
|
fuzz->nextRange(&op, 0, 1);
|
|
|
|
canvas->clipPath(path, (SkClipOp)op, doAntiAlias);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 22: {
|
|
|
|
SkRegion region;
|
|
|
|
int op;
|
2017-03-09 16:33:35 +00:00
|
|
|
fuzz->next(®ion);
|
2017-02-14 18:35:14 +00:00
|
|
|
fuzz->nextRange(&op, 0, 1);
|
|
|
|
canvas->clipRegion(region, (SkClipOp)op);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 23:
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawPaint(paint);
|
|
|
|
break;
|
|
|
|
case 24: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-12-20 16:21:05 +00:00
|
|
|
SkCanvas::PointMode pointMode;
|
2018-11-19 17:21:46 +00:00
|
|
|
fuzz->nextRange(&pointMode,
|
2017-12-20 16:21:05 +00:00
|
|
|
SkCanvas::kPoints_PointMode, SkCanvas::kPolygon_PointMode);
|
2017-02-14 18:35:14 +00:00
|
|
|
size_t count;
|
|
|
|
constexpr int kMaxCount = 30;
|
|
|
|
fuzz->nextRange(&count, 0, kMaxCount);
|
|
|
|
SkPoint pts[kMaxCount];
|
|
|
|
fuzz->nextN(pts, count);
|
2017-12-20 16:21:05 +00:00
|
|
|
canvas->drawPoints(pointMode, count, pts, paint);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 25: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRect r;
|
|
|
|
fuzz->next(&r);
|
2018-04-05 16:54:00 +00:00
|
|
|
if (!r.isFinite()) {
|
|
|
|
break;
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawRect(r, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 26: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRegion region;
|
2017-03-09 16:33:35 +00:00
|
|
|
fuzz->next(®ion);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawRegion(region, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 27: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRect r;
|
|
|
|
fuzz->next(&r);
|
2018-04-05 16:54:00 +00:00
|
|
|
if (!r.isFinite()) {
|
|
|
|
break;
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawOval(r, paint);
|
|
|
|
break;
|
|
|
|
}
|
2018-01-19 17:57:01 +00:00
|
|
|
case 28: break; // must have deleted this some time earlier
|
2017-02-14 18:35:14 +00:00
|
|
|
case 29: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRRect rr;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceRRect(fuzz, &rr);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawRRect(rr, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 30: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRRect orr, irr;
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceRRect(fuzz, &orr);
|
|
|
|
FuzzNiceRRect(fuzz, &irr);
|
2017-03-07 21:23:20 +00:00
|
|
|
if (orr.getBounds().contains(irr.getBounds())) {
|
|
|
|
canvas->drawDRRect(orr, irr, paint);
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 31: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkRect r;
|
|
|
|
SkScalar start, sweep;
|
|
|
|
bool useCenter;
|
|
|
|
fuzz->next(&r, &start, &sweep, &useCenter);
|
|
|
|
canvas->drawArc(r, start, sweep, useCenter, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 32: {
|
2018-05-22 01:17:15 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkPath path;
|
2018-09-25 16:16:53 +00:00
|
|
|
FuzzNicePath(fuzz, &path, 60);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawPath(path, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 33: {
|
2017-03-10 18:56:08 +00:00
|
|
|
sk_sp<SkImage> img = make_fuzz_image(fuzz);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkScalar left, top;
|
|
|
|
bool usePaint;
|
|
|
|
fuzz->next(&left, &top, &usePaint);
|
|
|
|
if (usePaint) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2021-01-22 20:26:41 +00:00
|
|
|
canvas->drawImage(img.get(), left, top, SkSamplingOptions(),
|
|
|
|
usePaint ? &paint : nullptr);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 35: {
|
2017-03-10 18:56:08 +00:00
|
|
|
auto img = make_fuzz_image(fuzz);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkIRect src;
|
|
|
|
SkRect dst;
|
|
|
|
bool usePaint;
|
|
|
|
fuzz->next(&src, &dst, &usePaint);
|
|
|
|
if (usePaint) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2017-03-08 16:02:40 +00:00
|
|
|
SkCanvas::SrcRectConstraint constraint =
|
2017-03-10 18:56:08 +00:00
|
|
|
make_fuzz_t<bool>(fuzz) ? SkCanvas::kStrict_SrcRectConstraint
|
|
|
|
: SkCanvas::kFast_SrcRectConstraint;
|
2021-01-22 20:26:41 +00:00
|
|
|
canvas->drawImageRect(img.get(), SkRect::Make(src), dst, SkSamplingOptions(),
|
|
|
|
usePaint ? &paint : nullptr, constraint);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 37: {
|
2017-03-10 18:56:08 +00:00
|
|
|
auto img = make_fuzz_image(fuzz);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkIRect center;
|
|
|
|
SkRect dst;
|
|
|
|
bool usePaint;
|
2017-03-15 16:58:15 +00:00
|
|
|
fuzz->next(&usePaint);
|
2017-02-14 18:35:14 +00:00
|
|
|
if (usePaint) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2017-03-15 16:58:15 +00:00
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
|
|
|
fuzz->next(¢er);
|
|
|
|
} else { // Make valid center, see SkLatticeIter::Valid().
|
|
|
|
fuzz->nextRange(¢er.fLeft, 0, img->width() - 1);
|
|
|
|
fuzz->nextRange(¢er.fTop, 0, img->height() - 1);
|
|
|
|
fuzz->nextRange(¢er.fRight, center.fLeft + 1, img->width());
|
|
|
|
fuzz->nextRange(¢er.fBottom, center.fTop + 1, img->height());
|
|
|
|
}
|
|
|
|
fuzz->next(&dst);
|
2021-01-25 16:37:10 +00:00
|
|
|
canvas->drawImageNine(img.get(), center, dst, SkFilterMode::kNearest,
|
|
|
|
usePaint ? &paint : nullptr);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 44: {
|
2017-03-10 18:56:08 +00:00
|
|
|
auto img = make_fuzz_image(fuzz);
|
2017-02-14 18:35:14 +00:00
|
|
|
bool usePaint;
|
|
|
|
SkRect dst;
|
|
|
|
fuzz->next(&usePaint, &dst);
|
|
|
|
if (usePaint) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
constexpr int kMax = 6;
|
|
|
|
int xDivs[kMax], yDivs[kMax];
|
2017-12-11 18:01:58 +00:00
|
|
|
SkCanvas::Lattice lattice{xDivs, yDivs, nullptr, 0, 0, nullptr, nullptr};
|
2017-02-14 18:35:14 +00:00
|
|
|
fuzz->nextRange(&lattice.fXCount, 2, kMax);
|
|
|
|
fuzz->nextRange(&lattice.fYCount, 2, kMax);
|
|
|
|
fuzz->nextN(xDivs, lattice.fXCount);
|
|
|
|
fuzz->nextN(yDivs, lattice.fYCount);
|
2021-01-25 16:37:10 +00:00
|
|
|
canvas->drawImageLattice(img.get(), lattice, dst, SkFilterMode::kLinear,
|
|
|
|
usePaint ? &paint : nullptr);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 45: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2018-11-23 20:27:51 +00:00
|
|
|
font = fuzz_font(fuzz);
|
|
|
|
SkTextEncoding encoding = fuzz_paint_text_encoding(fuzz);
|
2017-02-14 18:35:14 +00:00
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
2018-11-23 20:27:51 +00:00
|
|
|
SkTDArray<uint8_t> text = make_fuzz_text(fuzz, font, encoding);
|
|
|
|
canvas->drawSimpleText(text.begin(), SkToSizeT(text.count()), encoding, x, y,
|
|
|
|
font, paint);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 46: {
|
2018-12-25 22:35:49 +00:00
|
|
|
// was drawPosText
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 47: {
|
2018-12-25 22:35:49 +00:00
|
|
|
// was drawPosTextH
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 48: {
|
2018-10-01 16:16:59 +00:00
|
|
|
// was drawtextonpath
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 49: {
|
2018-10-01 16:16:59 +00:00
|
|
|
// was drawtextonpath
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 50: {
|
2018-12-25 22:35:49 +00:00
|
|
|
// was drawTextRSXform
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 51: {
|
2017-03-08 21:52:18 +00:00
|
|
|
sk_sp<SkTextBlob> blob = make_fuzz_textblob(fuzz);
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-03-08 21:52:18 +00:00
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
canvas->drawTextBlob(blob, x, y, paint);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 52: {
|
2018-09-17 18:46:57 +00:00
|
|
|
SkMatrix matrix;
|
2017-02-14 18:35:14 +00:00
|
|
|
bool usePaint, useMatrix;
|
|
|
|
fuzz->next(&usePaint, &useMatrix);
|
|
|
|
if (usePaint) {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
|
|
|
if (useMatrix) {
|
2018-09-17 18:46:57 +00:00
|
|
|
FuzzNiceMatrix(fuzz, &matrix);
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2017-03-10 18:56:08 +00:00
|
|
|
auto pic = make_fuzz_picture(fuzz, depth - 1);
|
2017-02-14 18:35:14 +00:00
|
|
|
canvas->drawPicture(pic, useMatrix ? &matrix : nullptr,
|
|
|
|
usePaint ? &paint : nullptr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 53: {
|
2017-03-10 18:56:08 +00:00
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
2017-04-03 15:11:09 +00:00
|
|
|
SkVertices::VertexMode vertexMode;
|
2017-03-09 19:10:36 +00:00
|
|
|
SkBlendMode blendMode;
|
2018-11-19 17:21:46 +00:00
|
|
|
fuzz->nextRange(&vertexMode, 0, SkVertices::kTriangleFan_VertexMode);
|
|
|
|
fuzz->nextRange(&blendMode, 0, SkBlendMode::kLastMode);
|
2017-02-14 18:35:14 +00:00
|
|
|
constexpr int kMaxCount = 100;
|
|
|
|
int vertexCount;
|
|
|
|
SkPoint vertices[kMaxCount];
|
|
|
|
SkPoint texs[kMaxCount];
|
|
|
|
SkColor colors[kMaxCount];
|
|
|
|
fuzz->nextRange(&vertexCount, 3, kMaxCount);
|
|
|
|
fuzz->nextN(vertices, vertexCount);
|
|
|
|
bool useTexs, useColors;
|
|
|
|
fuzz->next(&useTexs, &useColors);
|
|
|
|
if (useTexs) {
|
|
|
|
fuzz->nextN(texs, vertexCount);
|
|
|
|
}
|
|
|
|
if (useColors) {
|
|
|
|
fuzz->nextN(colors, vertexCount);
|
|
|
|
}
|
|
|
|
int indexCount = 0;
|
2017-03-02 20:27:23 +00:00
|
|
|
uint16_t indices[kMaxCount * 2];
|
2017-03-10 18:56:08 +00:00
|
|
|
if (make_fuzz_t<bool>(fuzz)) {
|
2017-03-02 20:27:23 +00:00
|
|
|
fuzz->nextRange(&indexCount, vertexCount, vertexCount + kMaxCount);
|
2021-08-16 16:16:29 +00:00
|
|
|
for (int index = 0; index < indexCount; ++index) {
|
|
|
|
fuzz->nextRange(&indices[index], 0, vertexCount - 1);
|
2017-03-02 20:27:23 +00:00
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
}
|
2017-04-03 15:11:09 +00:00
|
|
|
canvas->drawVertices(SkVertices::MakeCopy(vertexMode, vertexCount, vertices,
|
|
|
|
useTexs ? texs : nullptr,
|
|
|
|
useColors ? colors : nullptr,
|
|
|
|
indexCount, indices),
|
|
|
|
blendMode, paint);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-07-01 13:21:03 +00:00
|
|
|
case 54: {
|
|
|
|
SkColor color;
|
|
|
|
SkBlendMode blendMode;
|
|
|
|
fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
|
|
|
|
fuzz->next(&color);
|
|
|
|
canvas->drawColor(color, blendMode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 55: {
|
|
|
|
SkColor4f color;
|
|
|
|
SkBlendMode blendMode;
|
|
|
|
float R, G, B, Alpha;
|
|
|
|
fuzz->nextRange(&blendMode, 0, SkBlendMode::kSrcOver);
|
|
|
|
fuzz->nextRange(&R, -1, 2);
|
|
|
|
fuzz->nextRange(&G, -1, 2);
|
|
|
|
fuzz->nextRange(&B, -1, 2);
|
|
|
|
fuzz->nextRange(&Alpha, 0, 1);
|
|
|
|
color = {R, G, B, Alpha};
|
|
|
|
canvas->drawColor(color, blendMode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 56: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkPoint p0, p1;
|
|
|
|
fuzz->next(&p0, &p1);
|
|
|
|
canvas->drawLine(p0, p1, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 57: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkIRect r;
|
|
|
|
fuzz->next(&r);
|
|
|
|
canvas->drawIRect(r, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 58: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkScalar radius;
|
|
|
|
SkPoint center;
|
|
|
|
fuzz->next(&radius, ¢er);
|
|
|
|
canvas->drawCircle(center, radius, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 59: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkRect oval;
|
|
|
|
SkScalar startAngle, sweepAngle;
|
|
|
|
bool useCenter;
|
|
|
|
fuzz->next(&oval, &startAngle, &sweepAngle, &useCenter);
|
|
|
|
canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 60: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkRect rect;
|
|
|
|
SkScalar rx, ry;
|
|
|
|
fuzz->next(&rect, &rx, &ry);
|
|
|
|
canvas->drawRoundRect(rect, rx, ry, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 61: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
font = fuzz_font(fuzz);
|
|
|
|
std::string str = make_fuzz_string(fuzz);
|
|
|
|
SkScalar x, y;
|
|
|
|
fuzz->next(&x, &y);
|
|
|
|
canvas->drawString(str.c_str(), x, y, font, paint);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 62: {
|
|
|
|
fuzz_paint(fuzz, &paint, depth - 1);
|
|
|
|
SkPoint cubics[12];
|
|
|
|
SkColor colors[4];
|
|
|
|
SkPoint texCoords[4];
|
|
|
|
bool useTexCoords;
|
|
|
|
fuzz->nextN(cubics, 12);
|
|
|
|
fuzz->nextN(colors, 4);
|
|
|
|
fuzz->next(&useTexCoords);
|
|
|
|
if (useTexCoords) {
|
|
|
|
fuzz->nextN(texCoords, 4);
|
|
|
|
}
|
|
|
|
SkBlendMode mode;
|
|
|
|
fuzz->nextEnum(&mode, SkBlendMode::kLastMode);
|
|
|
|
canvas->drawPatch(cubics, colors, useTexCoords ? texCoords : nullptr
|
|
|
|
, mode, paint);
|
|
|
|
break;
|
|
|
|
}
|
2017-02-14 18:35:14 +00:00
|
|
|
default:
|
2018-01-11 19:50:21 +00:00
|
|
|
SkASSERT(false);
|
2017-02-14 18:35:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-10 18:56:08 +00:00
|
|
|
static sk_sp<SkPicture> make_fuzz_picture(Fuzz* fuzz, int depth) {
|
2017-02-14 18:35:14 +00:00
|
|
|
SkScalar w, h;
|
|
|
|
fuzz->next(&w, &h);
|
|
|
|
SkPictureRecorder pictureRecorder;
|
|
|
|
fuzz_canvas(fuzz, pictureRecorder.beginRecording(w, h), depth - 1);
|
|
|
|
return pictureRecorder.finishRecordingAsPicture();
|
|
|
|
}
|
|
|
|
|
2017-03-01 15:42:45 +00:00
|
|
|
DEF_FUZZ(NullCanvas, fuzz) {
|
|
|
|
fuzz_canvas(fuzz, SkMakeNullCanvas().get());
|
|
|
|
}
|
|
|
|
|
2018-03-21 14:17:25 +00:00
|
|
|
constexpr SkISize kCanvasSize = {128, 160};
|
2017-03-15 15:39:06 +00:00
|
|
|
|
2017-03-01 15:42:45 +00:00
|
|
|
DEF_FUZZ(RasterN32Canvas, fuzz) {
|
2017-03-15 15:39:06 +00:00
|
|
|
auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
|
2018-03-21 14:17:25 +00:00
|
|
|
if (!surface || !surface->getCanvas()) { fuzz->signalBug(); }
|
2017-03-15 15:39:06 +00:00
|
|
|
fuzz_canvas(fuzz, surface->getCanvas());
|
|
|
|
}
|
|
|
|
|
2017-12-01 16:46:26 +00:00
|
|
|
DEF_FUZZ(RasterN32CanvasViaSerialization, fuzz) {
|
|
|
|
SkPictureRecorder recorder;
|
|
|
|
fuzz_canvas(fuzz, recorder.beginRecording(SkIntToScalar(kCanvasSize.width()),
|
|
|
|
SkIntToScalar(kCanvasSize.height())));
|
|
|
|
sk_sp<SkPicture> pic(recorder.finishRecordingAsPicture());
|
|
|
|
if (!pic) { fuzz->signalBug(); }
|
|
|
|
sk_sp<SkData> data = pic->serialize();
|
|
|
|
if (!data) { fuzz->signalBug(); }
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer rb(data->data(), data->size());
|
2018-06-11 20:25:43 +00:00
|
|
|
auto deserialized = SkPicturePriv::MakeFromBuffer(rb);
|
2017-12-01 16:46:26 +00:00
|
|
|
if (!deserialized) { fuzz->signalBug(); }
|
|
|
|
auto surface = SkSurface::MakeRasterN32Premul(kCanvasSize.width(), kCanvasSize.height());
|
|
|
|
SkASSERT(surface && surface->getCanvas());
|
|
|
|
surface->getCanvas()->drawPicture(deserialized);
|
|
|
|
}
|
|
|
|
|
2018-01-09 20:32:58 +00:00
|
|
|
DEF_FUZZ(ImageFilter, fuzz) {
|
|
|
|
auto fil = make_fuzz_imageFilter(fuzz, 20);
|
|
|
|
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setImageFilter(fil);
|
|
|
|
SkBitmap bitmap;
|
|
|
|
SkCanvas canvas(bitmap);
|
|
|
|
canvas.saveLayer(SkRect::MakeWH(500, 500), &paint);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//SkRandom _rand;
|
|
|
|
#define SK_ADD_RANDOM_BIT_FLIPS
|
|
|
|
|
|
|
|
DEF_FUZZ(SerializedImageFilter, fuzz) {
|
2019-03-14 17:30:08 +00:00
|
|
|
SkBitmap bitmap;
|
|
|
|
if (!bitmap.tryAllocN32Pixels(256, 256)) {
|
|
|
|
SkDEBUGF("Could not allocate 256x256 bitmap in SerializedImageFilter");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-09 20:32:58 +00:00
|
|
|
auto filter = make_fuzz_imageFilter(fuzz, 20);
|
2018-09-14 15:58:40 +00:00
|
|
|
if (!filter) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-09 20:32:58 +00:00
|
|
|
auto data = filter->serialize();
|
|
|
|
const unsigned char* ptr = static_cast<const unsigned char*>(data->data());
|
|
|
|
size_t len = data->size();
|
|
|
|
#ifdef SK_ADD_RANDOM_BIT_FLIPS
|
|
|
|
unsigned char* p = const_cast<unsigned char*>(ptr);
|
|
|
|
for (size_t i = 0; i < len; ++i, ++p) {
|
|
|
|
uint8_t j;
|
|
|
|
fuzz->nextRange(&j, 1, 250);
|
|
|
|
if (j == 1) { // 0.4% of the time, flip a bit or byte
|
|
|
|
uint8_t k;
|
|
|
|
fuzz->nextRange(&k, 1, 10);
|
|
|
|
if (k == 1) { // Then 10% of the time, change a whole byte
|
|
|
|
uint8_t s;
|
|
|
|
fuzz->nextRange(&s, 0, 2);
|
|
|
|
switch(s) {
|
|
|
|
case 0:
|
|
|
|
*p ^= 0xFF; // Flip entire byte
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
*p = 0xFF; // Set all bits to 1
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
*p = 0x00; // Set all bits to 0
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
uint8_t s;
|
|
|
|
fuzz->nextRange(&s, 0, 7);
|
|
|
|
*p ^= (1 << 7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // SK_ADD_RANDOM_BIT_FLIPS
|
|
|
|
auto deserializedFil = SkImageFilter::Deserialize(ptr, len);
|
|
|
|
|
|
|
|
// uncomment below to write out a serialized image filter (to make corpus
|
|
|
|
// for -t filter_fuzz)
|
|
|
|
// SkString s("./serialized_filters/sf");
|
|
|
|
// s.appendU32(_rand.nextU());
|
|
|
|
// auto file = sk_fopen(s.c_str(), SkFILE_Flags::kWrite_SkFILE_Flag);
|
|
|
|
// sk_fwrite(data->bytes(), data->size(), file);
|
|
|
|
// sk_fclose(file);
|
|
|
|
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setImageFilter(deserializedFil);
|
2019-03-14 17:30:08 +00:00
|
|
|
|
2018-01-09 20:32:58 +00:00
|
|
|
SkCanvas canvas(bitmap);
|
2019-03-14 17:30:08 +00:00
|
|
|
canvas.saveLayer(SkRect::MakeWH(256, 256), &paint);
|
|
|
|
canvas.restore();
|
2018-01-09 20:32:58 +00:00
|
|
|
}
|
|
|
|
|
2020-03-19 19:54:28 +00:00
|
|
|
#ifdef SK_GL
|
2018-06-07 14:33:11 +00:00
|
|
|
|
2020-07-01 20:59:17 +00:00
|
|
|
static void dump_GPU_info(GrDirectContext* context) {
|
2019-02-04 18:26:26 +00:00
|
|
|
const GrGLInterface* gl = static_cast<GrGLGpu*>(context->priv().getGpu())
|
2018-06-07 14:33:11 +00:00
|
|
|
->glInterface();
|
|
|
|
const GrGLubyte* output;
|
|
|
|
GR_GL_CALL_RET(gl, output, GetString(GR_GL_RENDERER));
|
|
|
|
SkDebugf("GL_RENDERER %s\n", (const char*) output);
|
|
|
|
|
|
|
|
GR_GL_CALL_RET(gl, output, GetString(GR_GL_VENDOR));
|
|
|
|
SkDebugf("GL_VENDOR %s\n", (const char*) output);
|
|
|
|
|
|
|
|
GR_GL_CALL_RET(gl, output, GetString(GR_GL_VERSION));
|
|
|
|
SkDebugf("GL_VERSION %s\n", (const char*) output);
|
|
|
|
}
|
|
|
|
|
2020-07-01 20:59:17 +00:00
|
|
|
static void fuzz_ganesh(Fuzz* fuzz, GrDirectContext* context) {
|
2017-03-21 18:11:44 +00:00
|
|
|
SkASSERT(context);
|
|
|
|
auto surface = SkSurface::MakeRenderTarget(
|
|
|
|
context,
|
|
|
|
SkBudgeted::kNo,
|
2019-09-30 19:12:27 +00:00
|
|
|
SkImageInfo::Make(kCanvasSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
|
2017-03-21 18:11:44 +00:00
|
|
|
SkASSERT(surface && surface->getCanvas());
|
|
|
|
fuzz_canvas(fuzz, surface->getCanvas());
|
|
|
|
}
|
|
|
|
|
2017-03-15 15:39:06 +00:00
|
|
|
DEF_FUZZ(NativeGLCanvas, fuzz) {
|
2018-01-05 21:59:53 +00:00
|
|
|
sk_gpu_test::GrContextFactory f;
|
2020-07-01 20:59:17 +00:00
|
|
|
auto context = f.get(sk_gpu_test::GrContextFactory::kGL_ContextType);
|
2017-03-20 12:54:16 +00:00
|
|
|
if (!context) {
|
2018-01-05 21:59:53 +00:00
|
|
|
context = f.get(sk_gpu_test::GrContextFactory::kGLES_ContextType);
|
2017-03-20 12:54:16 +00:00
|
|
|
}
|
2018-06-05 21:21:30 +00:00
|
|
|
if (FLAGS_gpuInfo) {
|
2018-06-07 14:33:11 +00:00
|
|
|
dump_GPU_info(context);
|
2018-06-05 21:21:30 +00:00
|
|
|
}
|
2017-03-21 18:11:44 +00:00
|
|
|
fuzz_ganesh(fuzz, context);
|
|
|
|
}
|
|
|
|
|
2018-04-03 16:30:32 +00:00
|
|
|
DEF_FUZZ(MockGPUCanvas, fuzz) {
|
2018-04-02 15:06:41 +00:00
|
|
|
sk_gpu_test::GrContextFactory f;
|
|
|
|
fuzz_ganesh(fuzz, f.get(sk_gpu_test::GrContextFactory::kMock_ContextType));
|
|
|
|
}
|
2017-03-15 15:39:06 +00:00
|
|
|
#endif
|
2017-02-14 18:35:14 +00:00
|
|
|
|
2017-03-01 15:42:45 +00:00
|
|
|
DEF_FUZZ(PDFCanvas, fuzz) {
|
2017-08-26 21:06:42 +00:00
|
|
|
SkNullWStream stream;
|
2018-09-07 18:33:14 +00:00
|
|
|
auto doc = SkPDF::MakeDocument(&stream);
|
2017-03-15 15:39:06 +00:00
|
|
|
fuzz_canvas(fuzz, doc->beginPage(SkIntToScalar(kCanvasSize.width()),
|
|
|
|
SkIntToScalar(kCanvasSize.height())));
|
2017-03-01 15:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// not a "real" thing to fuzz, used to debug errors found while fuzzing.
|
|
|
|
DEF_FUZZ(_DumpCanvas, fuzz) {
|
2019-03-20 16:59:00 +00:00
|
|
|
DebugCanvas debugCanvas(kCanvasSize.width(), kCanvasSize.height());
|
2017-03-01 15:42:45 +00:00
|
|
|
fuzz_canvas(fuzz, &debugCanvas);
|
|
|
|
std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
|
|
|
|
UrlDataManager dataManager(SkString("data"));
|
2019-01-28 18:41:19 +00:00
|
|
|
SkDynamicMemoryWStream stream;
|
|
|
|
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
|
|
|
|
writer.beginObject(); // root
|
2019-12-13 18:51:14 +00:00
|
|
|
debugCanvas.toJSON(writer, dataManager, nullCanvas.get());
|
2019-01-28 18:41:19 +00:00
|
|
|
writer.endObject(); // root
|
|
|
|
writer.flush();
|
|
|
|
sk_sp<SkData> json = stream.detachAsData();
|
|
|
|
fwrite(json->data(), json->size(), 1, stdout);
|
2017-03-01 15:42:45 +00:00
|
|
|
}
|
2020-07-01 13:21:03 +00:00
|
|
|
|
|
|
|
DEF_FUZZ(SVGCanvas, fuzz) {
|
|
|
|
SkNullWStream stream;
|
|
|
|
SkRect bounds = SkRect::MakeIWH(150, 150);
|
|
|
|
std::unique_ptr<SkCanvas> canvas = SkSVGCanvas::Make(bounds, &stream);
|
|
|
|
fuzz_canvas(fuzz, canvas.get());
|
|
|
|
}
|