Coverage Report

Created: 2024-05-20 07:14

/src/skia/fuzz/FuzzGradients.cpp
Line
Count
Source (jump to first uncovered line)
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/Fuzz.h"
9
#include "include/core/SkCanvas.h"
10
#include "include/core/SkSurface.h"
11
#include "include/effects/SkGradientShader.h"
12
#include "src/base/SkTLazy.h"
13
#include "src/core/SkDebugUtils.h"
14
#include "tools/flags/CommandLineFlags.h"
15
16
#include <algorithm>
17
#include <vector>
18
19
static DEFINE_bool2(verbose, v, false, "log verbose linear gradient description");
20
21
const int MAX_COUNT = 400;
22
23
453
void makeMatrix(Fuzz* fuzz, SkMatrix* m) {
24
453
    SkScalar mat[9];
25
453
    fuzz->nextN(mat, 9);
26
453
    m->set9(mat);
27
453
}
28
29
void initGradientParams(Fuzz* fuzz, std::vector<SkColor>* colors,
30
912
                        std::vector<SkScalar>* pos, SkTileMode* mode) {
31
912
    int count;
32
912
    fuzz->nextRange(&count, 0, MAX_COUNT);
33
34
    // Use a uint8_t to conserve bytes.  This makes our "fuzzed bytes footprint"
35
    // smaller, which leads to more efficient fuzzing.
36
912
    uint8_t m;
37
912
    fuzz->nextRange(&m, 0, 2);
38
912
    *mode = static_cast<SkTileMode>(m);
39
40
912
    colors->clear();
41
912
    pos   ->clear();
42
87.7k
    for (int i = 0; i < count; i++) {
43
86.8k
        SkColor c;
44
86.8k
        SkScalar s;
45
86.8k
        fuzz->next(&c, &s);
46
86.8k
        colors->push_back(c);
47
86.8k
        pos   ->push_back(s);
48
86.8k
    }
49
912
    if (count) {
50
842
        std::sort(pos->begin(), pos->end());
51
        // The order matters.  If count == 1, we want pos == 0.
52
842
        (*pos)[count - 1] = 1;
53
842
        (*pos)[0]         = 0;
54
842
    }
55
912
}
56
57
0
static void logOptionalMatrix(const char* label, const SkMatrix* m) {
58
0
    if (!m) {
59
0
        return;
60
0
    }
61
62
0
    SkDEBUGF("  %s: [ ", label);
63
0
    for (int i = 0; i < 9; ++i) {
64
0
        SkDEBUGF("%.9g ", m->get(i));
65
0
    }
66
0
    SkDEBUGF("]\n");
67
0
}
68
69
static void logLinearGradient(const SkPoint pts[2],
70
                              const std::vector<SkColor>& colors,
71
                              const std::vector<SkScalar>& pos,
72
                              SkTileMode mode,
73
                              uint32_t flags,
74
                              const SkMatrix* localMatrix,
75
151
                              const SkMatrix* globalMatrix) {
76
151
    if (!FLAGS_verbose) {
77
151
        return;
78
151
    }
79
80
0
    SkDebugf("--- fuzzLinearGradient ---\n");
81
0
    SkDebugf("  pts:\t\t[ (%.9g %.9g) (%.9g %.9g) ]\n",
82
0
             pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y());
83
0
    SkDebugf("  colors:\t[ ");
84
0
    for (auto color : colors) {
85
0
        SkDebugf("0x%x ", color);
86
0
    }
87
88
0
    SkDebugf("]\n  pos:\t\t");
89
0
    if (pos.empty()) {
90
0
        SkDebugf("nullptr");
91
0
    } else {
92
0
        SkDebugf("[ ");
93
0
        for (auto p : pos) {
94
0
            SkDebugf("%f ", p);
95
0
        }
96
0
    }
97
0
    SkDebugf("]\n");
98
99
0
    SkDebugf("  mode:\t\t%s\n", SkTileModeToStr(mode));
100
0
    SkDebugf("  flags:\t0x%x\n", flags);
101
0
    logOptionalMatrix("local matrix", localMatrix);
102
0
    logOptionalMatrix("global matrix", globalMatrix);
103
0
}
104
105
151
void fuzzLinearGradient(Fuzz* fuzz) {
106
151
    SkPoint pts[2];
107
151
    fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
108
151
    bool useLocalMatrix, useGlobalMatrix;
109
151
    fuzz->next(&useLocalMatrix, &useGlobalMatrix);
110
111
151
    std::vector<SkColor> colors;
112
151
    std::vector<SkScalar> pos;
113
151
    SkTileMode mode;
114
151
    initGradientParams(fuzz, &colors, &pos, &mode);
115
116
151
    SkPaint p;
117
151
    uint32_t flags;
118
151
    fuzz->next(&flags);
119
120
151
    SkTLazy<SkMatrix> localMatrix;
121
151
    if (useLocalMatrix) {
122
12
        makeMatrix(fuzz, localMatrix.init());
123
12
    }
124
151
    p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
125
151
        colors.size(), mode, flags, localMatrix.getMaybeNull()));
126
127
151
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
128
151
    if (useGlobalMatrix) {
129
28
        SkMatrix gm;
130
28
        makeMatrix(fuzz, &gm);
131
28
        logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
132
28
        SkCanvas* c = surface->getCanvas();
133
28
        c->setMatrix(gm);
134
28
        c->drawPaint(p);
135
123
    } else {
136
123
        logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
137
123
        surface->getCanvas()->drawPaint(p);
138
123
    }
139
151
}
140
141
89
void fuzzRadialGradient(Fuzz* fuzz) {
142
89
    SkPoint center;
143
89
    fuzz->next(&center.fX, &center.fY);
144
89
    SkScalar radius;
145
89
    bool useLocalMatrix, useGlobalMatrix;
146
89
    fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
147
148
149
89
    std::vector<SkColor> colors;
150
89
    std::vector<SkScalar> pos;
151
89
    SkTileMode mode;
152
89
    initGradientParams(fuzz, &colors, &pos, &mode);
153
154
89
    SkPaint p;
155
89
    uint32_t flags;
156
89
    fuzz->next(&flags);
157
158
89
    SkTLazy<SkMatrix> localMatrix;
159
89
    if (useLocalMatrix) {
160
8
        makeMatrix(fuzz, localMatrix.init());
161
8
    }
162
89
    p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
163
89
        pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
164
165
89
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
166
89
    if (useGlobalMatrix) {
167
9
        SkMatrix gm;
168
9
        makeMatrix(fuzz, &gm);
169
9
        SkCanvas* c = surface->getCanvas();
170
9
        c->setMatrix(gm);
171
9
        c->drawPaint(p);
172
80
    } else {
173
80
        surface->getCanvas()->drawPaint(p);
174
80
    }
175
89
}
176
177
282
void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
178
282
    SkPoint start;
179
282
    fuzz->next(&start.fX, &start.fY);
180
282
    SkPoint end;
181
282
    fuzz->next(&end.fX, &end.fY);
182
282
    SkScalar startRadius, endRadius;
183
282
    bool useLocalMatrix, useGlobalMatrix;
184
282
    fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
185
186
282
    std::vector<SkColor> colors;
187
282
    std::vector<SkScalar> pos;
188
282
    SkTileMode mode;
189
282
    initGradientParams(fuzz, &colors, &pos, &mode);
190
191
282
    SkPaint p;
192
282
    uint32_t flags;
193
282
    fuzz->next(&flags);
194
195
282
    SkTLazy<SkMatrix> localMatrix;
196
282
    if (useLocalMatrix) {
197
17
        makeMatrix(fuzz, localMatrix.init());
198
17
    }
199
282
    p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
200
282
        end, endRadius, colors.data(), pos.data(), colors.size(), mode,
201
282
        flags, localMatrix.getMaybeNull()));
202
203
282
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
204
282
    if (useGlobalMatrix) {
205
78
        SkMatrix gm;
206
78
        makeMatrix(fuzz, &gm);
207
78
        SkCanvas* c = surface->getCanvas();
208
78
        c->setMatrix(gm);
209
78
        c->drawPaint(p);
210
204
    } else {
211
204
        surface->getCanvas()->drawPaint(p);
212
204
    }
213
282
}
214
215
390
void fuzzSweepGradient(Fuzz* fuzz) {
216
390
    SkScalar cx, cy;
217
390
    bool useLocalMatrix, useGlobalMatrix;
218
390
    fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
219
220
390
    std::vector<SkColor> colors;
221
390
    std::vector<SkScalar> pos;
222
390
    SkTileMode mode;
223
390
    initGradientParams(fuzz, &colors, &pos, &mode);
224
225
390
    SkPaint p;
226
390
    if (useLocalMatrix) {
227
171
        SkMatrix m;
228
171
        makeMatrix(fuzz, &m);
229
171
        uint32_t flags;
230
171
        fuzz->next(&flags);
231
232
171
        p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
233
171
            pos.data(), colors.size(), flags, &m));
234
219
    } else {
235
219
        p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
236
219
            pos.data(), colors.size()));
237
219
    }
238
239
390
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
240
390
    if (useGlobalMatrix) {
241
130
        SkMatrix gm;
242
130
        makeMatrix(fuzz, &gm);
243
130
        SkCanvas* c = surface->getCanvas();
244
130
        c->setMatrix(gm);
245
130
        c->drawPaint(p);
246
260
    } else {
247
260
        surface->getCanvas()->drawPaint(p);
248
260
    }
249
390
}
250
251
912
DEF_FUZZ(Gradients, fuzz) {
252
912
    uint8_t i;
253
912
    fuzz->next(&i);
254
255
912
    switch(i) {
256
151
        case 0:
257
151
            SkDEBUGF("LinearGradient\n");
258
151
            fuzzLinearGradient(fuzz);
259
151
            return;
260
89
        case 1:
261
89
            SkDEBUGF("RadialGradient\n");
262
89
            fuzzRadialGradient(fuzz);
263
89
            return;
264
282
        case 2:
265
282
            SkDEBUGF("TwoPointConicalGradient\n");
266
282
            fuzzTwoPointConicalGradient(fuzz);
267
282
            return;
268
912
    }
269
390
    SkDEBUGF("SweepGradient\n");
270
390
    fuzzSweepGradient(fuzz);
271
390
    return;
272
912
}