123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include "fuzz/Fuzz.h"
- #include "include/core/SkCanvas.h"
- #include "include/core/SkSurface.h"
- #include "include/effects/SkGradientShader.h"
- #include "src/core/SkTLazy.h"
- #include "tools/flags/CommandLineFlags.h"
- #include <algorithm>
- #include <vector>
- static DEFINE_bool2(verbose, v, false, "log verbose linear gradient description");
- const int MAX_COUNT = 400;
- void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
- SkScalar mat[9];
- fuzz->nextN(mat, 9);
- m->set9(mat);
- }
- void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
- std::vector<SkScalar>* pos, SkTileMode* mode) {
- int count;
- fuzz->nextRange(&count, 0, MAX_COUNT);
- // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
- // smaller, which leads to more efficient fuzzing.
- uint8_t m;
- fuzz->nextRange(&m, 0, 2);
- *mode = static_cast<SkTileMode>(m);
- colors->clear();
- pos ->clear();
- for (int i = 0; i < count; i++) {
- SkColor c;
- SkScalar s;
- fuzz->next(&c, &s);
- colors->push_back(c);
- pos ->push_back(s);
- }
- if (count) {
- std::sort(pos->begin(), pos->end());
- // The order matters. If count == 1, we want pos == 0.
- (*pos)[count - 1] = 1;
- (*pos)[0] = 0;
- }
- }
- static void logOptionalMatrix(const char* label, const SkMatrix* m) {
- if (!m) {
- return;
- }
- SkDEBUGF(" %s: [ ", label);
- for (int i = 0; i < 9; ++i) {
- SkDEBUGF("%.9g ", m->get(i));
- }
- SkDEBUGF("]\n");
- }
- static void logLinearGradient(const SkPoint pts[2],
- const std::vector<SkColor>& colors,
- const std::vector<SkScalar> pos,
- SkTileMode mode,
- uint32_t flags,
- const SkMatrix* localMatrix,
- const SkMatrix* globalMatrix) {
- if (!FLAGS_verbose) {
- return;
- }
- SkDebugf("--- fuzzLinearGradient ---\n");
- SkDebugf(" pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
- pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
- SkDebugf(" colors:\t[ ");
- for (auto color : colors) {
- SkDebugf("0x%x ", color);
- }
- SkDebugf("]\n pos:\t\t");
- if (pos.empty()) {
- SkDebugf("nullptr");
- } else {
- SkDebugf("[ ");
- for (auto p : pos) {
- SkDebugf("%f ", p);
- }
- }
- SkDebugf("]\n");
- static const char* gModeName[] = {
- "kClamp_TileMode", "kRepeat_TileMode", "kMirror_TileMode", "kDecal_TileMode"
- };
- SkASSERT((unsigned)mode < SK_ARRAY_COUNT(gModeName));
- SkDebugf(" mode:\t\t%s\n", gModeName[(unsigned)mode]);
- SkDebugf(" flags:\t0x%x\n", flags);
- logOptionalMatrix("local matrix", localMatrix);
- logOptionalMatrix("global matrix", globalMatrix);
- }
- void fuzzLinearGradient(Fuzz* fuzz) {
- SkPoint pts[2];
- fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&useLocalMatrix, &useGlobalMatrix);
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkTileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
- colors.size(), mode, flags, localMatrix.getMaybeNull()));
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
- surface->getCanvas()->drawPaint(p);
- }
- }
- void fuzzRadialGradient(Fuzz* fuzz) {
- SkPoint center;
- fuzz->next(¢er.fX, ¢er.fY);
- SkScalar radius;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkTileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
- pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
- }
- void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
- SkPoint start;
- fuzz->next(&start.fX, &start.fY);
- SkPoint end;
- fuzz->next(&end.fX, &end.fY);
- SkScalar startRadius, endRadius;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkTileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
- SkPaint p;
- uint32_t flags;
- fuzz->next(&flags);
- SkTLazy<SkMatrix> localMatrix;
- if (useLocalMatrix) {
- makeMatrix(fuzz, localMatrix.init());
- }
- p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
- end, endRadius, colors.data(), pos.data(), colors.size(), mode,
- flags, localMatrix.getMaybeNull()));
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
- }
- void fuzzSweepGradient(Fuzz* fuzz) {
- SkScalar cx, cy;
- bool useLocalMatrix, useGlobalMatrix;
- fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
- std::vector<SkColor> colors;
- std::vector<SkScalar> pos;
- SkTileMode mode;
- initGradientParams(fuzz, &colors, &pos, &mode);
- SkPaint p;
- if (useLocalMatrix) {
- SkMatrix m;
- makeMatrix(fuzz, &m);
- uint32_t flags;
- fuzz->next(&flags);
- p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
- pos.data(), colors.size(), flags, &m));
- } else {
- p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
- pos.data(), colors.size()));
- }
- sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
- if (useGlobalMatrix) {
- SkMatrix gm;
- makeMatrix(fuzz, &gm);
- SkCanvas* c = surface->getCanvas();
- c->setMatrix(gm);
- c->drawPaint(p);
- } else {
- surface->getCanvas()->drawPaint(p);
- }
- }
- DEF_FUZZ(Gradients, fuzz) {
- uint8_t i;
- fuzz->next(&i);
- switch(i) {
- case 0:
- SkDEBUGF("LinearGradient\n");
- fuzzLinearGradient(fuzz);
- return;
- case 1:
- SkDEBUGF("RadialGradient\n");
- fuzzRadialGradient(fuzz);
- return;
- case 2:
- SkDEBUGF("TwoPointConicalGradient\n");
- fuzzTwoPointConicalGradient(fuzz);
- return;
- }
- SkDEBUGF("SweepGradient\n");
- fuzzSweepGradient(fuzz);
- return;
- }
|