295 lines
8.5 KiB
C++
295 lines
8.5 KiB
C++
|
/*
|
||
|
* 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.h"
|
||
|
#include "SkCanvas.h"
|
||
|
#include "SkGradientShader.h"
|
||
|
#include "SkSurface.h"
|
||
|
#include "SkTLazy.h"
|
||
|
|
||
|
#include <algorithm>
|
||
|
|
||
|
const int MAX_COUNT = 400;
|
||
|
|
||
|
bool makeMatrix(Fuzz* fuzz, SkMatrix* m) {
|
||
|
SkScalar scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2;
|
||
|
if (!fuzz->next<SkScalar>(&scaleX) ||
|
||
|
!fuzz->next<SkScalar>(&skewX) ||
|
||
|
!fuzz->next<SkScalar>(&transX) ||
|
||
|
!fuzz->next<SkScalar>(&skewY) ||
|
||
|
!fuzz->next<SkScalar>(&scaleY) ||
|
||
|
!fuzz->next<SkScalar>(&transY) ||
|
||
|
!fuzz->next<SkScalar>(&persp0) ||
|
||
|
!fuzz->next<SkScalar>(&persp1) ||
|
||
|
!fuzz->next<SkScalar>(&persp2)) {
|
||
|
return false;
|
||
|
}
|
||
|
m->setAll(scaleX, skewX, transX, skewY, scaleY, transY, persp0, persp1, persp2);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool initGradientParams(Fuzz* fuzz, uint32_t* count, SkColor** colors, SkScalar** pos,
|
||
|
SkShader::TileMode* mode) {
|
||
|
if (fuzz->remaining() < sizeof(uint32_t)) {
|
||
|
return false;
|
||
|
}
|
||
|
uint32_t t_count;
|
||
|
SkColor* t_colors;
|
||
|
SkScalar* t_pos;
|
||
|
|
||
|
t_count = fuzz->nextRangeU(0, MAX_COUNT);
|
||
|
if (t_count == 1) {
|
||
|
t_count = 2;
|
||
|
}
|
||
|
|
||
|
if (fuzz->remaining() < (1 + t_count * (sizeof(SkColor) + sizeof(SkScalar)))) {
|
||
|
return false;
|
||
|
}
|
||
|
t_colors = new SkColor[t_count];
|
||
|
t_pos = new SkScalar[t_count];
|
||
|
for (uint32_t i = 0; i < t_count; i++) {
|
||
|
fuzz->next<SkColor>(&t_colors[i]);
|
||
|
fuzz->next<SkScalar>(&t_pos[i]);
|
||
|
}
|
||
|
|
||
|
if (t_count == 0) {
|
||
|
*count = 0;
|
||
|
*colors = NULL;
|
||
|
*pos = NULL;
|
||
|
} else {
|
||
|
std::sort(t_pos, t_pos + t_count);
|
||
|
t_pos[0] = 0;
|
||
|
t_pos[t_count - 1] = 1;
|
||
|
*count = t_count;
|
||
|
*colors = t_colors;
|
||
|
*pos = t_pos;
|
||
|
}
|
||
|
|
||
|
*mode = static_cast<SkShader::TileMode>(fuzz->nextRangeU(0, 3));
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void fuzzLinearGradient(Fuzz* fuzz) {
|
||
|
SkScalar a, b, c, d;
|
||
|
bool useLocalMatrix, useGlobalMatrix;
|
||
|
if (!fuzz->next<SkScalar>(&a) ||
|
||
|
!fuzz->next<SkScalar>(&b) ||
|
||
|
!fuzz->next<SkScalar>(&c) ||
|
||
|
!fuzz->next<SkScalar>(&d) ||
|
||
|
!fuzz->next<bool>(&useLocalMatrix) ||
|
||
|
!fuzz->next<bool>(&useGlobalMatrix)) {
|
||
|
return;
|
||
|
}
|
||
|
SkPoint pts[2] = {SkPoint::Make(a,b), SkPoint::Make(c, d)};
|
||
|
|
||
|
uint32_t count;
|
||
|
SkColor* colors;
|
||
|
SkScalar* pos;
|
||
|
SkShader::TileMode mode;
|
||
|
if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkPaint p;
|
||
|
uint32_t flags;
|
||
|
if (!fuzz->next(&flags)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkTLazy<SkMatrix> localMatrix;
|
||
|
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
|
||
|
return;
|
||
|
}
|
||
|
p.setShader(SkGradientShader::MakeLinear(pts, colors, pos, count, mode,
|
||
|
flags, localMatrix.getMaybeNull()));
|
||
|
|
||
|
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
|
||
|
if (useGlobalMatrix) {
|
||
|
SkMatrix gm;
|
||
|
if (!makeMatrix(fuzz, &gm)) {
|
||
|
return;
|
||
|
}
|
||
|
SkCanvas* c = surface->getCanvas();
|
||
|
c->setMatrix(gm);
|
||
|
c->drawPaint(p);
|
||
|
} else {
|
||
|
surface->getCanvas()->drawPaint(p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void fuzzRadialGradient(Fuzz* fuzz) {
|
||
|
SkScalar a, b, radius;
|
||
|
bool useLocalMatrix, useGlobalMatrix;
|
||
|
if (!fuzz->next<SkScalar>(&a) ||
|
||
|
!fuzz->next<SkScalar>(&b) ||
|
||
|
!fuzz->next<SkScalar>(&radius) ||
|
||
|
!fuzz->next<bool>(&useLocalMatrix) ||
|
||
|
!fuzz->next<bool>(&useGlobalMatrix)) {
|
||
|
return;
|
||
|
}
|
||
|
SkPoint center = SkPoint::Make(a,b);
|
||
|
|
||
|
uint32_t count;
|
||
|
SkColor* colors;
|
||
|
SkScalar* pos;
|
||
|
SkShader::TileMode mode;
|
||
|
if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkPaint p;
|
||
|
uint32_t flags;
|
||
|
if (!fuzz->next(&flags)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkTLazy<SkMatrix> localMatrix;
|
||
|
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
|
||
|
return;
|
||
|
}
|
||
|
p.setShader(SkGradientShader::MakeRadial(center, radius, colors, pos,
|
||
|
count, mode, flags, localMatrix.getMaybeNull()));
|
||
|
|
||
|
|
||
|
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
|
||
|
if (useGlobalMatrix) {
|
||
|
SkMatrix gm;
|
||
|
if (!makeMatrix(fuzz, &gm)) {
|
||
|
return;
|
||
|
}
|
||
|
SkCanvas* c = surface->getCanvas();
|
||
|
c->setMatrix(gm);
|
||
|
c->drawPaint(p);
|
||
|
} else {
|
||
|
surface->getCanvas()->drawPaint(p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
|
||
|
SkScalar a, b, startRadius, c, d, endRadius;
|
||
|
bool useLocalMatrix, useGlobalMatrix;
|
||
|
if (!fuzz->next<SkScalar>(&a) ||
|
||
|
!fuzz->next<SkScalar>(&b) ||
|
||
|
!fuzz->next<SkScalar>(&startRadius) ||
|
||
|
!fuzz->next<SkScalar>(&c) ||
|
||
|
!fuzz->next<SkScalar>(&d) ||
|
||
|
!fuzz->next<SkScalar>(&endRadius) ||
|
||
|
!fuzz->next<bool>(&useLocalMatrix) ||
|
||
|
!fuzz->next<bool>(&useGlobalMatrix)) {
|
||
|
return;
|
||
|
}
|
||
|
SkPoint start = SkPoint::Make(a, b);
|
||
|
SkPoint end = SkPoint::Make(c, d);
|
||
|
|
||
|
uint32_t count;
|
||
|
SkColor* colors;
|
||
|
SkScalar* pos;
|
||
|
SkShader::TileMode mode;
|
||
|
if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkPaint p;
|
||
|
uint32_t flags;
|
||
|
if (!fuzz->next(&flags)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkTLazy<SkMatrix> localMatrix;
|
||
|
if (useLocalMatrix && !makeMatrix(fuzz, localMatrix.init())) {
|
||
|
return;
|
||
|
}
|
||
|
p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius, end,
|
||
|
endRadius, colors, pos, count, mode, flags, localMatrix.getMaybeNull()));
|
||
|
|
||
|
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
|
||
|
if (useGlobalMatrix) {
|
||
|
SkMatrix gm;
|
||
|
if (!makeMatrix(fuzz, &gm)) {
|
||
|
return;
|
||
|
}
|
||
|
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;
|
||
|
if (!fuzz->next<SkScalar>(&cx) ||
|
||
|
!fuzz->next<SkScalar>(&cy) ||
|
||
|
!fuzz->next<bool>(&useLocalMatrix) ||
|
||
|
!fuzz->next<bool>(&useGlobalMatrix)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
uint32_t count;
|
||
|
SkColor* colors;
|
||
|
SkScalar* pos;
|
||
|
SkShader::TileMode mode;
|
||
|
if (!initGradientParams(fuzz, &count, &colors, &pos, &mode)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SkPaint p;
|
||
|
if (useLocalMatrix) {
|
||
|
SkMatrix m;
|
||
|
if (!makeMatrix(fuzz, &m)) {
|
||
|
return;
|
||
|
}
|
||
|
uint32_t flags;
|
||
|
if (!fuzz->next(&flags)) {
|
||
|
return;
|
||
|
}
|
||
|
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors, pos, count, flags, &m));
|
||
|
} else {
|
||
|
p.setShader(SkGradientShader::MakeSweep(cx, cy, colors, pos, count));
|
||
|
}
|
||
|
|
||
|
|
||
|
sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
|
||
|
if (useGlobalMatrix) {
|
||
|
SkMatrix gm;
|
||
|
if (!makeMatrix(fuzz, &gm)) {
|
||
|
return;
|
||
|
}
|
||
|
SkCanvas* c = surface->getCanvas();
|
||
|
c->setMatrix(gm);
|
||
|
c->drawPaint(p);
|
||
|
} else {
|
||
|
surface->getCanvas()->drawPaint(p);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEF_FUZZ(Gradients, fuzz) {
|
||
|
uint8_t i;
|
||
|
if (!fuzz->next<uint8_t>(&i)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|