Coverage Report

Created: 2024-09-14 07:19

/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
877
                        std::vector<SkScalar>* pos, SkTileMode* mode) {
31
877
    int count;
32
877
    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
877
    uint8_t m;
37
877
    fuzz->nextRange(&m, 0, 2);
38
877
    *mode = static_cast<SkTileMode>(m);
39
40
877
    colors->clear();
41
877
    pos   ->clear();
42
133k
    for (int i = 0; i < count; i++) {
43
132k
        SkColor c;
44
132k
        SkScalar s;
45
132k
        fuzz->next(&c, &s);
46
132k
        colors->push_back(c);
47
132k
        pos   ->push_back(s);
48
132k
    }
49
877
    if (count) {
50
814
        std::sort(pos->begin(), pos->end());
51
        // The order matters.  If count == 1, we want pos == 0.
52
814
        (*pos)[count - 1] = 1;
53
814
        (*pos)[0]         = 0;
54
814
    }
55
877
}
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
125
                              const SkMatrix* globalMatrix) {
76
125
    if (!FLAGS_verbose) {
77
125
        return;
78
125
    }
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
125
void fuzzLinearGradient(Fuzz* fuzz) {
106
125
    SkPoint pts[2];
107
125
    fuzz->next(&pts[0].fX, &pts[0].fY, &pts[1].fX, &pts[1].fY);
108
125
    bool useLocalMatrix, useGlobalMatrix;
109
125
    fuzz->next(&useLocalMatrix, &useGlobalMatrix);
110
111
125
    std::vector<SkColor> colors;
112
125
    std::vector<SkScalar> pos;
113
125
    SkTileMode mode;
114
125
    initGradientParams(fuzz, &colors, &pos, &mode);
115
116
125
    SkPaint p;
117
125
    uint32_t flags;
118
125
    fuzz->next(&flags);
119
120
125
    SkTLazy<SkMatrix> localMatrix;
121
125
    if (useLocalMatrix) {
122
7
        makeMatrix(fuzz, localMatrix.init());
123
7
    }
124
125
    p.setShader(SkGradientShader::MakeLinear(pts, colors.data(), pos.data(),
125
125
        colors.size(), mode, flags, localMatrix.getMaybeNull()));
126
127
125
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
128
125
    if (useGlobalMatrix) {
129
38
        SkMatrix gm;
130
38
        makeMatrix(fuzz, &gm);
131
38
        logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), &gm);
132
38
        SkCanvas* c = surface->getCanvas();
133
38
        c->setMatrix(gm);
134
38
        c->drawPaint(p);
135
87
    } else {
136
87
        logLinearGradient(pts, colors, pos, mode, flags, localMatrix.getMaybeNull(), nullptr);
137
87
        surface->getCanvas()->drawPaint(p);
138
87
    }
139
125
}
140
141
86
void fuzzRadialGradient(Fuzz* fuzz) {
142
86
    SkPoint center;
143
86
    fuzz->next(&center.fX, &center.fY);
144
86
    SkScalar radius;
145
86
    bool useLocalMatrix, useGlobalMatrix;
146
86
    fuzz->next(&radius, &useLocalMatrix, &useGlobalMatrix);
147
148
149
86
    std::vector<SkColor> colors;
150
86
    std::vector<SkScalar> pos;
151
86
    SkTileMode mode;
152
86
    initGradientParams(fuzz, &colors, &pos, &mode);
153
154
86
    SkPaint p;
155
86
    uint32_t flags;
156
86
    fuzz->next(&flags);
157
158
86
    SkTLazy<SkMatrix> localMatrix;
159
86
    if (useLocalMatrix) {
160
8
        makeMatrix(fuzz, localMatrix.init());
161
8
    }
162
86
    p.setShader(SkGradientShader::MakeRadial(center, radius, colors.data(),
163
86
        pos.data(), colors.size(), mode, flags, localMatrix.getMaybeNull()));
164
165
86
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
166
86
    if (useGlobalMatrix) {
167
19
        SkMatrix gm;
168
19
        makeMatrix(fuzz, &gm);
169
19
        SkCanvas* c = surface->getCanvas();
170
19
        c->setMatrix(gm);
171
19
        c->drawPaint(p);
172
67
    } else {
173
67
        surface->getCanvas()->drawPaint(p);
174
67
    }
175
86
}
176
177
291
void fuzzTwoPointConicalGradient(Fuzz* fuzz) {
178
291
    SkPoint start;
179
291
    fuzz->next(&start.fX, &start.fY);
180
291
    SkPoint end;
181
291
    fuzz->next(&end.fX, &end.fY);
182
291
    SkScalar startRadius, endRadius;
183
291
    bool useLocalMatrix, useGlobalMatrix;
184
291
    fuzz->next(&startRadius, &endRadius, &useLocalMatrix, &useGlobalMatrix);
185
186
291
    std::vector<SkColor> colors;
187
291
    std::vector<SkScalar> pos;
188
291
    SkTileMode mode;
189
291
    initGradientParams(fuzz, &colors, &pos, &mode);
190
191
291
    SkPaint p;
192
291
    uint32_t flags;
193
291
    fuzz->next(&flags);
194
195
291
    SkTLazy<SkMatrix> localMatrix;
196
291
    if (useLocalMatrix) {
197
14
        makeMatrix(fuzz, localMatrix.init());
198
14
    }
199
291
    p.setShader(SkGradientShader::MakeTwoPointConical(start, startRadius,
200
291
        end, endRadius, colors.data(), pos.data(), colors.size(), mode,
201
291
        flags, localMatrix.getMaybeNull()));
202
203
291
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
204
291
    if (useGlobalMatrix) {
205
72
        SkMatrix gm;
206
72
        makeMatrix(fuzz, &gm);
207
72
        SkCanvas* c = surface->getCanvas();
208
72
        c->setMatrix(gm);
209
72
        c->drawPaint(p);
210
219
    } else {
211
219
        surface->getCanvas()->drawPaint(p);
212
219
    }
213
291
}
214
215
375
void fuzzSweepGradient(Fuzz* fuzz) {
216
375
    SkScalar cx, cy;
217
375
    bool useLocalMatrix, useGlobalMatrix;
218
375
    fuzz->next(&cx, &cy, &useLocalMatrix, &useGlobalMatrix);
219
220
375
    std::vector<SkColor> colors;
221
375
    std::vector<SkScalar> pos;
222
375
    SkTileMode mode;
223
375
    initGradientParams(fuzz, &colors, &pos, &mode);
224
225
375
    SkPaint p;
226
375
    if (useLocalMatrix) {
227
138
        SkMatrix m;
228
138
        makeMatrix(fuzz, &m);
229
138
        uint32_t flags;
230
138
        fuzz->next(&flags);
231
232
138
        p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
233
138
            pos.data(), colors.size(), flags, &m));
234
237
    } else {
235
237
        p.setShader(SkGradientShader::MakeSweep(cx, cy, colors.data(),
236
237
            pos.data(), colors.size()));
237
237
    }
238
239
375
    sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
240
375
    if (useGlobalMatrix) {
241
157
        SkMatrix gm;
242
157
        makeMatrix(fuzz, &gm);
243
157
        SkCanvas* c = surface->getCanvas();
244
157
        c->setMatrix(gm);
245
157
        c->drawPaint(p);
246
218
    } else {
247
218
        surface->getCanvas()->drawPaint(p);
248
218
    }
249
375
}
250
251
877
DEF_FUZZ(Gradients, fuzz) {
252
877
    uint8_t i;
253
877
    fuzz->next(&i);
254
255
877
    switch(i) {
256
125
        case 0:
257
125
            SkDEBUGF("LinearGradient\n");
258
125
            fuzzLinearGradient(fuzz);
259
125
            return;
260
86
        case 1:
261
86
            SkDEBUGF("RadialGradient\n");
262
86
            fuzzRadialGradient(fuzz);
263
86
            return;
264
291
        case 2:
265
291
            SkDEBUGF("TwoPointConicalGradient\n");
266
291
            fuzzTwoPointConicalGradient(fuzz);
267
291
            return;
268
877
    }
269
375
    SkDEBUGF("SweepGradient\n");
270
375
    fuzzSweepGradient(fuzz);
271
375
    return;
272
877
}