blob: df36c7ce8fc15dfb4932b7c31cf32b65e74e3118 [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) {
20 m->setAll(fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
21 fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>(),
22 fuzz->next<SkScalar>(), fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
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) {
27 int count = fuzz->nextRange(0, MAX_COUNT);
kjlubick1eda1eb2016-08-12 06:26:03 -070028
Kevin Lubick2f535ce2016-11-01 15:01:12 -040029 *mode = static_cast<SkShader::TileMode>(fuzz->nextRange(0, 2));
kjlubick840f12a2016-10-25 06:11:05 -070030
31 colors->clear();
32 pos ->clear();
Kevin Lubick2f535ce2016-11-01 15:01:12 -040033 for (int i = 0; i < count; i++) {
34 colors->push_back(fuzz->next<SkColor>());
35 pos ->push_back(fuzz->next<SkScalar>());
kjlubick840f12a2016-10-25 06:11:05 -070036 }
37 if (count) {
38 std::sort(pos->begin(), pos->end());
39 // The order matters. If count == 1, we want pos == 0.
40 (*pos)[count - 1] = 1;
41 (*pos)[0] = 0;
42 }
kjlubick1eda1eb2016-08-12 06:26:03 -070043}
44
45void fuzzLinearGradient(Fuzz* fuzz) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -040046 SkPoint pts[2] = {SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>()),
47 SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>())};
48 bool useLocalMatrix = fuzz->next<bool>();
49 bool useGlobalMatrix = fuzz->next<bool>();
kjlubick1eda1eb2016-08-12 06:26:03 -070050
Kevin Lubick2f535ce2016-11-01 15:01:12 -040051 std::vector<SkColor> colors;
52 std::vector<SkScalar> pos;
53 SkShader::TileMode mode;
54 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -070055
Kevin Lubick2f535ce2016-11-01 15:01:12 -040056 SkPaint p;
57 uint32_t flags = fuzz->next<uint32_t>();
kjlubick1eda1eb2016-08-12 06:26:03 -070058
Kevin Lubick2f535ce2016-11-01 15:01:12 -040059 SkTLazy<SkMatrix> localMatrix;
60 if (useLocalMatrix) {
61 makeMatrix(fuzz, localMatrix.init());
62 }
63 p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
64 colors.size(), mode, flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -070065
Kevin Lubick2f535ce2016-11-01 15:01:12 -040066 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
67 if (useGlobalMatrix) {
68 SkMatrix gm;
69 makeMatrix(fuzz, &gm);
70 SkCanvas* c = surface->getCanvas();
71 c->setMatrix(gm);
72 c->drawPaint(p);
73 } else {
74 surface->getCanvas()->drawPaint(p);
75 }
kjlubick1eda1eb2016-08-12 06:26:03 -070076}
77
78void fuzzRadialGradient(Fuzz* fuzz) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -040079 SkPoint center = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
80 SkScalar radius = fuzz->next<SkScalar>();
81 bool useLocalMatrix = fuzz->next<bool>();
82 bool useGlobalMatrix = fuzz->next<bool>();
kjlubick1eda1eb2016-08-12 06:26:03 -070083
84
Kevin Lubick2f535ce2016-11-01 15:01:12 -040085 std::vector<SkColor> colors;
86 std::vector<SkScalar> pos;
87 SkShader::TileMode mode;
88 initGradientParams(fuzz, &colors, &pos, &mode);
89
90 SkPaint p;
91 uint32_t flags = fuzz->next<uint32_t>();
92
93 SkTLazy<SkMatrix> localMatrix;
94 if (useLocalMatrix) {
95 makeMatrix(fuzz, localMatrix.init());
96 }
97 p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
98 pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
99
100
101 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
102 if (useGlobalMatrix) {
103 SkMatrix gm;
104 makeMatrix(fuzz, &gm);
105 SkCanvas* c = surface->getCanvas();
106 c->setMatrix(gm);
107 c->drawPaint(p);
108 } else {
109 surface->getCanvas()->drawPaint(p);
110 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700111}
112
113void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400114 SkPoint start = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
115 SkPoint end = SkPoint::Make(fuzz->next<SkScalar>(), fuzz->next<SkScalar>());
116 SkScalar startRadius = fuzz->next<SkScalar>();
117 SkScalar endRadius = fuzz->next<SkScalar>();
118 bool useLocalMatrix = fuzz->next<bool>();
119 bool useGlobalMatrix = fuzz->next<bool>();
kjlubick1eda1eb2016-08-12 06:26:03 -0700120
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400121 std::vector<SkColor> colors;
122 std::vector<SkScalar> pos;
123 SkShader::TileMode mode;
124 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700125
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400126 SkPaint p;
127 uint32_t flags = fuzz->next<uint32_t>();
kjlubick1eda1eb2016-08-12 06:26:03 -0700128
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400129 SkTLazy<SkMatrix> localMatrix;
130 if (useLocalMatrix) {
131 makeMatrix(fuzz, localMatrix.init());
132 }
133 p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
134 end, endRadius, colors.data(), pos.data(), colors.size(), mode,
135 flags, localMatrix.getMaybeNull()));
kjlubick1eda1eb2016-08-12 06:26:03 -0700136
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400137 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
138 if (useGlobalMatrix) {
139 SkMatrix gm;
140 makeMatrix(fuzz, &gm);
141 SkCanvas* c = surface->getCanvas();
142 c->setMatrix(gm);
143 c->drawPaint(p);
144 } else {
145 surface->getCanvas()->drawPaint(p);
146 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700147}
148
149void fuzzSweepGradient(Fuzz* fuzz) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400150 SkScalar cx = fuzz->next<SkScalar>();
151 SkScalar cy = fuzz->next<SkScalar>();
152 bool useLocalMatrix = fuzz->next<bool>();
153 bool useGlobalMatrix = fuzz->next<bool>();
kjlubick1eda1eb2016-08-12 06:26:03 -0700154
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400155 std::vector<SkColor> colors;
156 std::vector<SkScalar> pos;
157 SkShader::TileMode mode;
158 initGradientParams(fuzz, &colors, &pos, &mode);
kjlubick1eda1eb2016-08-12 06:26:03 -0700159
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400160 SkPaint p;
161 if (useLocalMatrix) {
162 SkMatrix m;
163 makeMatrix(fuzz, &m);
164 uint32_t flags = fuzz->next<uint32_t>();
kjlubick1eda1eb2016-08-12 06:26:03 -0700165
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400166 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
167 pos.data(), colors.size(), flags, &m));
168 } else {
169 p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
170 pos.data(), colors.size()));
171 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700172
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400173 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50));
174 if (useGlobalMatrix) {
175 SkMatrix gm;
176 makeMatrix(fuzz, &gm);
177 SkCanvas* c = surface->getCanvas();
178 c->setMatrix(gm);
179 c->drawPaint(p);
180 } else {
181 surface->getCanvas()->drawPaint(p);
182 }
kjlubick1eda1eb2016-08-12 06:26:03 -0700183}
184
185DEF_FUZZ(Gradients, fuzz) {
Kevin Lubick2f535ce2016-11-01 15:01:12 -0400186 uint8_t i = fuzz->next<uint8_t>();
kjlubick1eda1eb2016-08-12 06:26:03 -0700187
188 switch(i) {
189 case 0:
190 SkDebugf("LinearGradient\n");
191 fuzzLinearGradient(fuzz);
192 return;
193 case 1:
194 SkDebugf("RadialGradient\n");
195 fuzzRadialGradient(fuzz);
196 return;
197 case 2:
198 SkDebugf("TwoPointConicalGradient\n");
199 fuzzTwoPointConicalGradient(fuzz);
200 return;
201 }
202 SkDebugf("SweepGradient\n");
203 fuzzSweepGradient(fuzz);
204 return;
205}