FuzzGradients.cpp revision 2f535cecd0e5a19a3dfb76649b1d90c7e158e24c
1/*
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>
15#include <vector>
16
17const int MAX_COUNT = 400;
18
19void 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>());
23}
24
25void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
26                        std::vector<SkScalar>* pos, SkShader::TileMode* mode) {
27    int count = fuzz->nextRange(0, MAX_COUNT);
28
29    *mode = static_cast<SkShader::TileMode>(fuzz->nextRange(0, 2));
30
31    colors->clear();
32    pos   ->clear();
33    for (int i = 0; i < count; i++) {
34        colors->push_back(fuzz->next<SkColor>());
35        pos   ->push_back(fuzz->next<SkScalar>());
36    }
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    }
43}
44
45void fuzzLinearGradient(Fuzz* fuzz) {
46    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>();
50
51    std::vector<SkColor> colors;
52    std::vector<SkScalar> pos;
53    SkShader::TileMode mode;
54    initGradientParams(fuzz, &colors, &pos, &mode);
55
56    SkPaint p;
57    uint32_t flags = fuzz->next<uint32_t>();
58
59    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()));
65
66    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    }
76}
77
78void fuzzRadialGradient(Fuzz* fuzz) {
79    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>();
83
84
85    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    }
111}
112
113void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
114    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>();
120
121    std::vector<SkColor> colors;
122    std::vector<SkScalar> pos;
123    SkShader::TileMode mode;
124    initGradientParams(fuzz, &colors, &pos, &mode);
125
126    SkPaint p;
127    uint32_t flags = fuzz->next<uint32_t>();
128
129    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()));
136
137    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    }
147}
148
149void fuzzSweepGradient(Fuzz* fuzz) {
150    SkScalar cx = fuzz->next<SkScalar>();
151    SkScalar cy = fuzz->next<SkScalar>();
152    bool useLocalMatrix  = fuzz->next<bool>();
153    bool useGlobalMatrix = fuzz->next<bool>();
154
155    std::vector<SkColor> colors;
156    std::vector<SkScalar> pos;
157    SkShader::TileMode mode;
158    initGradientParams(fuzz, &colors, &pos, &mode);
159
160    SkPaint p;
161    if (useLocalMatrix) {
162        SkMatrix m;
163        makeMatrix(fuzz, &m);
164        uint32_t flags = fuzz->next<uint32_t>();
165
166        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    }
172
173    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    }
183}
184
185DEF_FUZZ(Gradients, fuzz) {
186    uint8_t i = fuzz->next<uint8_t>();
187
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}
206