blob: 90d4066a8049aacc349dec06dd392aa5e8afb79c [file] [log] [blame]
kjlubick1eda1eb2016-08-12 06:26:03 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Fuzz.h"
9#include "SkCanvas.h"
10#include "SkGradientShader.h"
11#include "SkSurface.h"
12#include "SkTLazy.h"
13
14#include <algorithm>
Kevin Lubick2f535ce2016-11-01 15:01:12 -040015#include <vector>
kjlubick1eda1eb2016-08-12 06:26:03 -070016
17const int MAX_COUNT = 400;
18
Kevin Lubick2f535ce2016-11-01 15:01:12 -040019void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
Kevin Lubick416b2482016-11-10 16:17:49 -050020 SkScalar mat[9];
21 fuzz->nextN(mat, 9);
22 m->set9(mat);
kjlubick1eda1eb2016-08-12 06:26:03 -070023}
24
Kevin Lubick2f535ce2016-11-01 15:01:12 -040025void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
26 std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
Kevin Lubick416b2482016-11-10 16:17:49 -050027 int count;
28 fuzz->nextRange(&count, 0, MAX_COUNT);
kjlubick1eda1eb2016-08-12 06:26:03 -070029
Kevin Lubick416b2482016-11-10 16:17:49 -050030 // Use a uint8_t to conserve bytes. This makes our "fuzzed bytes footprint"
31 // smaller, which leads to more efficient fuzzing.
32 uint8_t m;
33 fuzz->nextRange(&m, 0, 2);
34 *mode = static_cast<SkShader::TileMode>(m);
kjlubick840f12a2016-10-25 06:11:05 -070035
36 colors->clear();
37 pos ->clear();
Kevin Lubick2f535ce2016-11-01 15:01:12 -040038 for (int i = 0; i < count; i++) {
Kevin Lubick416b2482016-11-10 16:17:49 -050039 SkColor c;
40 SkScalar s;
41 fuzz->next(&c, &s);
42 colors->push_back(c);
43 pos ->push_back(s);
kjlubick840f12a2016-10-25 06:11:05 -070044 }
45 if (count) {
46 std::sort(pos->begin(), pos->end());
47 // The order matters. If count == 1, we want pos == 0.
48 (*pos)[count - 1] = 1;
49 (*pos)[0] = 0;
50 }
kjlubick1eda1eb2016-08-12 06:26:03 -070051}
52
53void fuzzLinearGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -050054 SkPoint pts[2];
55 fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
56 bool useLocalMatrix, useGlobalMatrix;
57 fuzz->next(&useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -070058
Kevin Lubick2f535ce2016-11-01 15:01:12 -040059 std::vector<SkColor> colors;
60 std::vector<SkScalar> pos;
61 SkShader::TileMode mode;
62 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -070063
Kevin Lubick2f535ce2016-11-01 15:01:12 -040064 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -050065 uint32_t flags;
66 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -070067
Kevin Lubick2f535ce2016-11-01 15:01:12 -040068 SkTLazy<SkMatrix> localMatrix;
69 if (useLocalMatrix) {
70 makeMatrix(fuzz, localMatrix.init());
71 }
72 p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
73 colors.size(), mode, flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -070074
Kevin Lubick2f535ce2016-11-01 15:01:12 -040075 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
76 if (useGlobalMatrix) {
77 SkMatrix gm;
78 makeMatrix(fuzz, &gm);
79 SkCanvas* c = surface->getCanvas();
80 c->setMatrix(gm);
81 c->drawPaint(p);
82 } else {
83 surface->getCanvas()->drawPaint(p);
84 }
kjlubick1eda1eb2016-08-12 06:26:03 -070085}
86
87void fuzzRadialGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -050088 SkPoint center;
89 fuzz->next(&center.fX, &center.fY);
90 SkScalar radius;
91 bool useLocalMatrix, useGlobalMatrix;
92 fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -070093
94
Kevin Lubick2f535ce2016-11-01 15:01:12 -040095 std::vector<SkColor> colors;
96 std::vector<SkScalar> pos;
97 SkShader::TileMode mode;
98 initGradientParams(fuzz, &colors, &pos, &mode);
99
100 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500101 uint32_t flags;
102 fuzz->next(&flags);
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400103
104 SkTLazy<SkMatrix> localMatrix;
105 if (useLocalMatrix) {
106 makeMatrix(fuzz, localMatrix.init());
107 }
108 p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
109 pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
110
111
112 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
113 if (useGlobalMatrix) {
114 SkMatrix gm;
115 makeMatrix(fuzz, &gm);
116 SkCanvas* c = surface->getCanvas();
117 c->setMatrix(gm);
118 c->drawPaint(p);
119 } else {
120 surface->getCanvas()->drawPaint(p);
121 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700122}
123
124void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500125 SkPoint start;
126 fuzz->next(&start.fX, &start.fY);
127 SkPoint end;
128 fuzz->next(&end.fX, &end.fY);
129 SkScalar startRadius, endRadius;
130 bool useLocalMatrix, useGlobalMatrix;
131 fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700132
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400133 std::vector<SkColor> colors;
134 std::vector<SkScalar> pos;
135 SkShader::TileMode mode;
136 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700137
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400138 SkPaint p;
Kevin Lubick416b2482016-11-10 16:17:49 -0500139 uint32_t flags;
140 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700141
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400142 SkTLazy<SkMatrix> localMatrix;
143 if (useLocalMatrix) {
144 makeMatrix(fuzz, localMatrix.init());
145 }
146 p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
147 end, endRadius, colors.data(), pos.data(), colors.size(), mode,
148 flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700149
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400150 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
151 if (useGlobalMatrix) {
152 SkMatrix gm;
153 makeMatrix(fuzz, &gm);
154 SkCanvas* c = surface->getCanvas();
155 c->setMatrix(gm);
156 c->drawPaint(p);
157 } else {
158 surface->getCanvas()->drawPaint(p);
159 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700160}
161
162void fuzzSweepGradient(Fuzz* fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500163 SkScalar cx, cy;
164 bool useLocalMatrix, useGlobalMatrix;
165 fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
kjlubick1eda1eb2016-08-12 06:26:03 -0700166
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400167 std::vector<SkColor> colors;
168 std::vector<SkScalar> pos;
169 SkShader::TileMode mode;
170 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700171
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400172 SkPaint p;
173 if (useLocalMatrix) {
174 SkMatrix m;
175 makeMatrix(fuzz, &m);
Kevin Lubick416b2482016-11-10 16:17:49 -0500176 uint32_t flags;
177 fuzz->next(&flags);
kjlubick1eda1eb2016-08-12 06:26:03 -0700178
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400179 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
180 pos.data(), colors.size(), flags, &m));
181 } else {
182 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
183 pos.data(), colors.size()));
184 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700185
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400186 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
187 if (useGlobalMatrix) {
188 SkMatrix gm;
189 makeMatrix(fuzz, &gm);
190 SkCanvas* c = surface->getCanvas();
191 c->setMatrix(gm);
192 c->drawPaint(p);
193 } else {
194 surface->getCanvas()->drawPaint(p);
195 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700196}
197
198DEF_FUZZ(Gradients, fuzz) {
Kevin Lubick416b2482016-11-10 16:17:49 -0500199 uint8_t i;
200 fuzz->next(&i);
kjlubick1eda1eb2016-08-12 06:26:03 -0700201
202 switch(i) {
203 case 0:
204 SkDebugf("LinearGradient\n");
205 fuzzLinearGradient(fuzz);
206 return;
207 case 1:
208 SkDebugf("RadialGradient\n");
209 fuzzRadialGradient(fuzz);
210 return;
211 case 2:
212 SkDebugf("TwoPointConicalGradient\n");
213 fuzzTwoPointConicalGradient(fuzz);
214 return;
215 }
216 SkDebugf("SweepGradient\n");
217 fuzzSweepGradient(fuzz);
218 return;
219}