xref: /aosp_15_r20/external/skia/fuzz/FuzzCommon.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2018 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "fuzz/Fuzz.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "fuzz/FuzzCommon.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorFilter.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkBlenders.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkPathPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker 
15*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker // We don't always want to test NaNs and infinities.
fuzz_nice_float(Fuzz * fuzz,float * f)18*c8dee2aaSAndroid Build Coastguard Worker static void fuzz_nice_float(Fuzz* fuzz, float* f) {
19*c8dee2aaSAndroid Build Coastguard Worker     float v;
20*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&v);
21*c8dee2aaSAndroid Build Coastguard Worker     constexpr float kLimit = 1.0e35f;  // FLT_MAX?
22*c8dee2aaSAndroid Build Coastguard Worker     *f = (v == v && v <= kLimit && v >= -kLimit) ? v : 0.0f;
23*c8dee2aaSAndroid Build Coastguard Worker }
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker template <typename... Args>
fuzz_nice_float(Fuzz * fuzz,float * f,Args...rest)26*c8dee2aaSAndroid Build Coastguard Worker static void fuzz_nice_float(Fuzz* fuzz, float* f, Args... rest) {
27*c8dee2aaSAndroid Build Coastguard Worker     fuzz_nice_float(fuzz, f);
28*c8dee2aaSAndroid Build Coastguard Worker     fuzz_nice_float(fuzz, rest...);
29*c8dee2aaSAndroid Build Coastguard Worker }
30*c8dee2aaSAndroid Build Coastguard Worker 
fuzz_nice_rect(Fuzz * fuzz,SkRect * r)31*c8dee2aaSAndroid Build Coastguard Worker static void fuzz_nice_rect(Fuzz* fuzz, SkRect* r) {
32*c8dee2aaSAndroid Build Coastguard Worker     fuzz_nice_float(fuzz, &r->fLeft, &r->fTop, &r->fRight, &r->fBottom);
33*c8dee2aaSAndroid Build Coastguard Worker     r->sort();
34*c8dee2aaSAndroid Build Coastguard Worker }
35*c8dee2aaSAndroid Build Coastguard Worker 
36*c8dee2aaSAndroid Build Coastguard Worker // allows some float values for path points
FuzzNicePath(Fuzz * fuzz,SkPath * path,int maxOps)37*c8dee2aaSAndroid Build Coastguard Worker void FuzzNicePath(Fuzz* fuzz, SkPath* path, int maxOps) {
38*c8dee2aaSAndroid Build Coastguard Worker     if (maxOps <= 0 || fuzz->exhausted() || path->countPoints() > 100000) {
39*c8dee2aaSAndroid Build Coastguard Worker         return;
40*c8dee2aaSAndroid Build Coastguard Worker     }
41*c8dee2aaSAndroid Build Coastguard Worker     uint8_t fillType;
42*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&fillType, 0, (uint8_t)SkPathFillType::kInverseEvenOdd);
43*c8dee2aaSAndroid Build Coastguard Worker     path->setFillType((SkPathFillType)fillType);
44*c8dee2aaSAndroid Build Coastguard Worker     uint8_t numOps;
45*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&numOps, 0, maxOps);
46*c8dee2aaSAndroid Build Coastguard Worker     for (uint8_t i = 0; i < numOps; ++i) {
47*c8dee2aaSAndroid Build Coastguard Worker         // When we start adding the path to itself, the fuzzer can make an
48*c8dee2aaSAndroid Build Coastguard Worker         // exponentially long path, which causes timeouts.
49*c8dee2aaSAndroid Build Coastguard Worker         if (path->countPoints() > 100000) {
50*c8dee2aaSAndroid Build Coastguard Worker             return;
51*c8dee2aaSAndroid Build Coastguard Worker         }
52*c8dee2aaSAndroid Build Coastguard Worker         // How many items in the switch statement below.
53*c8dee2aaSAndroid Build Coastguard Worker         constexpr uint8_t MAX_PATH_OPERATION = 32;
54*c8dee2aaSAndroid Build Coastguard Worker         uint8_t op;
55*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&op, 0, MAX_PATH_OPERATION);
56*c8dee2aaSAndroid Build Coastguard Worker         bool test;
57*c8dee2aaSAndroid Build Coastguard Worker         SkPath p;
58*c8dee2aaSAndroid Build Coastguard Worker         SkMatrix m;
59*c8dee2aaSAndroid Build Coastguard Worker         SkRRect rr;
60*c8dee2aaSAndroid Build Coastguard Worker         SkRect r;
61*c8dee2aaSAndroid Build Coastguard Worker         SkPathDirection dir;
62*c8dee2aaSAndroid Build Coastguard Worker         unsigned int ui;
63*c8dee2aaSAndroid Build Coastguard Worker         SkScalar a, b, c, d, e, f;
64*c8dee2aaSAndroid Build Coastguard Worker         switch (op) {
65*c8dee2aaSAndroid Build Coastguard Worker             case 0:
66*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
67*c8dee2aaSAndroid Build Coastguard Worker                 path->moveTo(a, b);
68*c8dee2aaSAndroid Build Coastguard Worker                 break;
69*c8dee2aaSAndroid Build Coastguard Worker             case 1:
70*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
71*c8dee2aaSAndroid Build Coastguard Worker                 path->rMoveTo(a, b);
72*c8dee2aaSAndroid Build Coastguard Worker                 break;
73*c8dee2aaSAndroid Build Coastguard Worker             case 2:
74*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
75*c8dee2aaSAndroid Build Coastguard Worker                 path->lineTo(a, b);
76*c8dee2aaSAndroid Build Coastguard Worker                 break;
77*c8dee2aaSAndroid Build Coastguard Worker             case 3:
78*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
79*c8dee2aaSAndroid Build Coastguard Worker                 path->rLineTo(a, b);
80*c8dee2aaSAndroid Build Coastguard Worker                 break;
81*c8dee2aaSAndroid Build Coastguard Worker             case 4:
82*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d);
83*c8dee2aaSAndroid Build Coastguard Worker                 path->quadTo(a, b, c, d);
84*c8dee2aaSAndroid Build Coastguard Worker                 break;
85*c8dee2aaSAndroid Build Coastguard Worker             case 5:
86*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d);
87*c8dee2aaSAndroid Build Coastguard Worker                 path->rQuadTo(a, b, c, d);
88*c8dee2aaSAndroid Build Coastguard Worker                 break;
89*c8dee2aaSAndroid Build Coastguard Worker             case 6:
90*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
91*c8dee2aaSAndroid Build Coastguard Worker                 path->conicTo(a, b, c, d, e);
92*c8dee2aaSAndroid Build Coastguard Worker                 break;
93*c8dee2aaSAndroid Build Coastguard Worker             case 7:
94*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
95*c8dee2aaSAndroid Build Coastguard Worker                 path->rConicTo(a, b, c, d, e);
96*c8dee2aaSAndroid Build Coastguard Worker                 break;
97*c8dee2aaSAndroid Build Coastguard Worker             case 8:
98*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
99*c8dee2aaSAndroid Build Coastguard Worker                 path->cubicTo(a, b, c, d, e, f);
100*c8dee2aaSAndroid Build Coastguard Worker                 break;
101*c8dee2aaSAndroid Build Coastguard Worker             case 9:
102*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e, &f);
103*c8dee2aaSAndroid Build Coastguard Worker                 path->rCubicTo(a, b, c, d, e, f);
104*c8dee2aaSAndroid Build Coastguard Worker                 break;
105*c8dee2aaSAndroid Build Coastguard Worker             case 10:
106*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c, &d, &e);
107*c8dee2aaSAndroid Build Coastguard Worker                 path->arcTo(a, b, c, d, e);
108*c8dee2aaSAndroid Build Coastguard Worker                 break;
109*c8dee2aaSAndroid Build Coastguard Worker             case 11:
110*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
111*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
112*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->next(&test);
113*c8dee2aaSAndroid Build Coastguard Worker                 path->arcTo(r, a, b, test);
114*c8dee2aaSAndroid Build Coastguard Worker                 break;
115*c8dee2aaSAndroid Build Coastguard Worker             case 12:
116*c8dee2aaSAndroid Build Coastguard Worker                 path->close();
117*c8dee2aaSAndroid Build Coastguard Worker                 break;
118*c8dee2aaSAndroid Build Coastguard Worker             case 13:
119*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
120*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
121*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
122*c8dee2aaSAndroid Build Coastguard Worker                 path->addRect(r, dir);
123*c8dee2aaSAndroid Build Coastguard Worker                 break;
124*c8dee2aaSAndroid Build Coastguard Worker             case 14:
125*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
126*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
127*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
128*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->next(&ui);
129*c8dee2aaSAndroid Build Coastguard Worker                 path->addRect(r, dir, ui);
130*c8dee2aaSAndroid Build Coastguard Worker                 break;
131*c8dee2aaSAndroid Build Coastguard Worker             case 15:
132*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
133*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
134*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
135*c8dee2aaSAndroid Build Coastguard Worker                 path->addOval(r, dir);
136*c8dee2aaSAndroid Build Coastguard Worker                 break;
137*c8dee2aaSAndroid Build Coastguard Worker             case 16:
138*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
139*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
140*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
141*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->next(&ui);
142*c8dee2aaSAndroid Build Coastguard Worker                 path->addOval(r, dir, ui);
143*c8dee2aaSAndroid Build Coastguard Worker                 break;
144*c8dee2aaSAndroid Build Coastguard Worker             case 17:
145*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
146*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
147*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b, &c);
148*c8dee2aaSAndroid Build Coastguard Worker                 path->addCircle(a, b, c, dir);
149*c8dee2aaSAndroid Build Coastguard Worker                 break;
150*c8dee2aaSAndroid Build Coastguard Worker             case 18:
151*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
152*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
153*c8dee2aaSAndroid Build Coastguard Worker                 path->addArc(r, a, b);
154*c8dee2aaSAndroid Build Coastguard Worker                 break;
155*c8dee2aaSAndroid Build Coastguard Worker             case 19:
156*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
157*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_rect(fuzz, &r);
158*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
159*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
160*c8dee2aaSAndroid Build Coastguard Worker                 path->addRoundRect(r, a, b, dir);
161*c8dee2aaSAndroid Build Coastguard Worker                 break;
162*c8dee2aaSAndroid Build Coastguard Worker             case 20:
163*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNiceRRect(fuzz, &rr);
164*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
165*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
166*c8dee2aaSAndroid Build Coastguard Worker                 path->addRRect(rr, dir);
167*c8dee2aaSAndroid Build Coastguard Worker                 break;
168*c8dee2aaSAndroid Build Coastguard Worker             case 21:
169*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
170*c8dee2aaSAndroid Build Coastguard Worker                 dir = static_cast<SkPathDirection>(ui);
171*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNiceRRect(fuzz, &rr);
172*c8dee2aaSAndroid Build Coastguard Worker                 path->addRRect(rr, dir, ui);
173*c8dee2aaSAndroid Build Coastguard Worker                 break;
174*c8dee2aaSAndroid Build Coastguard Worker             case 22: {
175*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
176*c8dee2aaSAndroid Build Coastguard Worker                 SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
177*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNiceMatrix(fuzz, &m);
178*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNicePath(fuzz, &p, maxOps-1);
179*c8dee2aaSAndroid Build Coastguard Worker                 path->addPath(p, m, mode);
180*c8dee2aaSAndroid Build Coastguard Worker                 break;
181*c8dee2aaSAndroid Build Coastguard Worker             }
182*c8dee2aaSAndroid Build Coastguard Worker             case 23: {
183*c8dee2aaSAndroid Build Coastguard Worker                 fuzz->nextRange(&ui, 0, 1);
184*c8dee2aaSAndroid Build Coastguard Worker                 SkPath::AddPathMode mode = static_cast<SkPath::AddPathMode>(ui);
185*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNiceMatrix(fuzz, &m);
186*c8dee2aaSAndroid Build Coastguard Worker                 path->addPath(*path, m, mode);
187*c8dee2aaSAndroid Build Coastguard Worker                 break;
188*c8dee2aaSAndroid Build Coastguard Worker             }
189*c8dee2aaSAndroid Build Coastguard Worker             case 24:
190*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNicePath(fuzz, &p, maxOps-1);
191*c8dee2aaSAndroid Build Coastguard Worker                 path->reverseAddPath(p);
192*c8dee2aaSAndroid Build Coastguard Worker                 break;
193*c8dee2aaSAndroid Build Coastguard Worker             case 25:
194*c8dee2aaSAndroid Build Coastguard Worker                 path->addPath(*path);
195*c8dee2aaSAndroid Build Coastguard Worker                 break;
196*c8dee2aaSAndroid Build Coastguard Worker             case 26:
197*c8dee2aaSAndroid Build Coastguard Worker                 path->reverseAddPath(*path);
198*c8dee2aaSAndroid Build Coastguard Worker                 break;
199*c8dee2aaSAndroid Build Coastguard Worker             case 27:
200*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
201*c8dee2aaSAndroid Build Coastguard Worker                 path->offset(a, b, path);
202*c8dee2aaSAndroid Build Coastguard Worker                 break;
203*c8dee2aaSAndroid Build Coastguard Worker             case 28:
204*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNicePath(fuzz, &p, maxOps-1);
205*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
206*c8dee2aaSAndroid Build Coastguard Worker                 p.offset(a, b, path);
207*c8dee2aaSAndroid Build Coastguard Worker                 break;
208*c8dee2aaSAndroid Build Coastguard Worker             case 29:
209*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNiceMatrix(fuzz, &m);
210*c8dee2aaSAndroid Build Coastguard Worker                 path->transform(m, path);
211*c8dee2aaSAndroid Build Coastguard Worker                 break;
212*c8dee2aaSAndroid Build Coastguard Worker             case 30:
213*c8dee2aaSAndroid Build Coastguard Worker                 FuzzNicePath(fuzz, &p, maxOps-1);
214*c8dee2aaSAndroid Build Coastguard Worker                 // transform can explode path sizes so skip this op if p too big
215*c8dee2aaSAndroid Build Coastguard Worker                 if (p.countPoints() <= 100000) {
216*c8dee2aaSAndroid Build Coastguard Worker                     FuzzNiceMatrix(fuzz, &m);
217*c8dee2aaSAndroid Build Coastguard Worker                     p.transform(m, path);
218*c8dee2aaSAndroid Build Coastguard Worker                 }
219*c8dee2aaSAndroid Build Coastguard Worker                 break;
220*c8dee2aaSAndroid Build Coastguard Worker             case 31:
221*c8dee2aaSAndroid Build Coastguard Worker                 fuzz_nice_float(fuzz, &a, &b);
222*c8dee2aaSAndroid Build Coastguard Worker                 path->setLastPt(a, b);
223*c8dee2aaSAndroid Build Coastguard Worker                 break;
224*c8dee2aaSAndroid Build Coastguard Worker             case MAX_PATH_OPERATION:
225*c8dee2aaSAndroid Build Coastguard Worker                 SkPathPriv::ShrinkToFit(path);
226*c8dee2aaSAndroid Build Coastguard Worker                 break;
227*c8dee2aaSAndroid Build Coastguard Worker 
228*c8dee2aaSAndroid Build Coastguard Worker             default:
229*c8dee2aaSAndroid Build Coastguard Worker                 SkASSERT(false);
230*c8dee2aaSAndroid Build Coastguard Worker                 break;
231*c8dee2aaSAndroid Build Coastguard Worker         }
232*c8dee2aaSAndroid Build Coastguard Worker         SkASSERTF(       path->isValid(),        "path->isValid() failed at op %d, case %d", i, op);
233*c8dee2aaSAndroid Build Coastguard Worker     }
234*c8dee2aaSAndroid Build Coastguard Worker }
235*c8dee2aaSAndroid Build Coastguard Worker 
236*c8dee2aaSAndroid Build Coastguard Worker // allows all float values for path points
FuzzEvilPath(Fuzz * fuzz,SkPath * path,int last_verb)237*c8dee2aaSAndroid Build Coastguard Worker void FuzzEvilPath(Fuzz* fuzz, SkPath* path, int last_verb) {
238*c8dee2aaSAndroid Build Coastguard Worker   while (!fuzz->exhausted()) {
239*c8dee2aaSAndroid Build Coastguard Worker     // Use a uint8_t to conserve bytes.  This makes our "fuzzed bytes footprint"
240*c8dee2aaSAndroid Build Coastguard Worker     // smaller, which leads to more efficient fuzzing.
241*c8dee2aaSAndroid Build Coastguard Worker     uint8_t operation;
242*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&operation);
243*c8dee2aaSAndroid Build Coastguard Worker     SkScalar a,b,c,d,e,f;
244*c8dee2aaSAndroid Build Coastguard Worker 
245*c8dee2aaSAndroid Build Coastguard Worker     switch (operation % (last_verb + 1)) {
246*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kMove_Verb:
247*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&a, &b);
248*c8dee2aaSAndroid Build Coastguard Worker         path->moveTo(a, b);
249*c8dee2aaSAndroid Build Coastguard Worker         break;
250*c8dee2aaSAndroid Build Coastguard Worker 
251*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kLine_Verb:
252*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&a, &b);
253*c8dee2aaSAndroid Build Coastguard Worker         path->lineTo(a, b);
254*c8dee2aaSAndroid Build Coastguard Worker         break;
255*c8dee2aaSAndroid Build Coastguard Worker 
256*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kQuad_Verb:
257*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&a, &b, &c, &d);
258*c8dee2aaSAndroid Build Coastguard Worker         path->quadTo(a, b, c, d);
259*c8dee2aaSAndroid Build Coastguard Worker         break;
260*c8dee2aaSAndroid Build Coastguard Worker 
261*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kConic_Verb:
262*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&a, &b, &c, &d, &e);
263*c8dee2aaSAndroid Build Coastguard Worker         path->conicTo(a, b, c, d, e);
264*c8dee2aaSAndroid Build Coastguard Worker         break;
265*c8dee2aaSAndroid Build Coastguard Worker 
266*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kCubic_Verb:
267*c8dee2aaSAndroid Build Coastguard Worker         fuzz->next(&a, &b, &c, &d, &e, &f);
268*c8dee2aaSAndroid Build Coastguard Worker         path->cubicTo(a, b, c, d, e, f);
269*c8dee2aaSAndroid Build Coastguard Worker         break;
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kClose_Verb:
272*c8dee2aaSAndroid Build Coastguard Worker         path->close();
273*c8dee2aaSAndroid Build Coastguard Worker         break;
274*c8dee2aaSAndroid Build Coastguard Worker 
275*c8dee2aaSAndroid Build Coastguard Worker       case SkPath::Verb::kDone_Verb:
276*c8dee2aaSAndroid Build Coastguard Worker         // In this case, simply exit.
277*c8dee2aaSAndroid Build Coastguard Worker         return;
278*c8dee2aaSAndroid Build Coastguard Worker     }
279*c8dee2aaSAndroid Build Coastguard Worker   }
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker 
FuzzNiceRRect(Fuzz * fuzz,SkRRect * rr)282*c8dee2aaSAndroid Build Coastguard Worker void FuzzNiceRRect(Fuzz* fuzz, SkRRect* rr) {
283*c8dee2aaSAndroid Build Coastguard Worker     SkRect r;
284*c8dee2aaSAndroid Build Coastguard Worker     fuzz_nice_rect(fuzz, &r);
285*c8dee2aaSAndroid Build Coastguard Worker 
286*c8dee2aaSAndroid Build Coastguard Worker     SkVector radii[4];
287*c8dee2aaSAndroid Build Coastguard Worker     for (SkVector& vec : radii) {
288*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&vec.fX, 0.0f, 1.0f);
289*c8dee2aaSAndroid Build Coastguard Worker         vec.fX *= 0.5f * r.width();
290*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&vec.fY, 0.0f, 1.0f);
291*c8dee2aaSAndroid Build Coastguard Worker         vec.fY *= 0.5f * r.height();
292*c8dee2aaSAndroid Build Coastguard Worker     }
293*c8dee2aaSAndroid Build Coastguard Worker     rr->setRectRadii(r, radii);
294*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(rr->isValid());
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker 
FuzzNiceMatrix(Fuzz * fuzz,SkMatrix * m)297*c8dee2aaSAndroid Build Coastguard Worker void FuzzNiceMatrix(Fuzz* fuzz, SkMatrix* m) {
298*c8dee2aaSAndroid Build Coastguard Worker     constexpr int kArrayLength = 9;
299*c8dee2aaSAndroid Build Coastguard Worker     SkScalar buffer[kArrayLength];
300*c8dee2aaSAndroid Build Coastguard Worker     int matrixType;
301*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&matrixType, 0, 4);
302*c8dee2aaSAndroid Build Coastguard Worker     switch (matrixType) {
303*c8dee2aaSAndroid Build Coastguard Worker         case 0:  // identity
304*c8dee2aaSAndroid Build Coastguard Worker             *m = SkMatrix::I();
305*c8dee2aaSAndroid Build Coastguard Worker             return;
306*c8dee2aaSAndroid Build Coastguard Worker         case 1:  // translate
307*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[0], -4000.0f, 4000.0f);
308*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[1], -4000.0f, 4000.0f);
309*c8dee2aaSAndroid Build Coastguard Worker             *m = SkMatrix::Translate(buffer[0], buffer[1]);
310*c8dee2aaSAndroid Build Coastguard Worker             return;
311*c8dee2aaSAndroid Build Coastguard Worker         case 2:  // translate + scale
312*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[0], -400.0f, 400.0f);
313*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[1], -400.0f, 400.0f);
314*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[2], -4000.0f, 4000.0f);
315*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextRange(&buffer[3], -4000.0f, 4000.0f);
316*c8dee2aaSAndroid Build Coastguard Worker             *m = SkMatrix::Scale(buffer[0], buffer[1]);
317*c8dee2aaSAndroid Build Coastguard Worker             m->postTranslate(buffer[2], buffer[3]);
318*c8dee2aaSAndroid Build Coastguard Worker             return;
319*c8dee2aaSAndroid Build Coastguard Worker         case 3:  // affine
320*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextN(buffer, 6);
321*c8dee2aaSAndroid Build Coastguard Worker             m->setAffine(buffer);
322*c8dee2aaSAndroid Build Coastguard Worker             return;
323*c8dee2aaSAndroid Build Coastguard Worker         case 4:  // perspective
324*c8dee2aaSAndroid Build Coastguard Worker             fuzz->nextN(buffer, kArrayLength);
325*c8dee2aaSAndroid Build Coastguard Worker             m->set9(buffer);
326*c8dee2aaSAndroid Build Coastguard Worker             return;
327*c8dee2aaSAndroid Build Coastguard Worker         default:
328*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(false);
329*c8dee2aaSAndroid Build Coastguard Worker             return;
330*c8dee2aaSAndroid Build Coastguard Worker     }
331*c8dee2aaSAndroid Build Coastguard Worker }
332*c8dee2aaSAndroid Build Coastguard Worker 
FuzzNiceRegion(Fuzz * fuzz,SkRegion * region,int maxN)333*c8dee2aaSAndroid Build Coastguard Worker void FuzzNiceRegion(Fuzz* fuzz, SkRegion* region, int maxN) {
334*c8dee2aaSAndroid Build Coastguard Worker     uint8_t N;
335*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&N, 0, maxN);
336*c8dee2aaSAndroid Build Coastguard Worker     for (uint8_t i = 0; i < N; ++i) {
337*c8dee2aaSAndroid Build Coastguard Worker         SkIRect r;
338*c8dee2aaSAndroid Build Coastguard Worker         SkRegion::Op op;
339*c8dee2aaSAndroid Build Coastguard Worker         // Avoid the sentinel value used by Region.
340*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&r.fLeft,   -2147483646, 2147483646);
341*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&r.fTop,    -2147483646, 2147483646);
342*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&r.fRight,  -2147483646, 2147483646);
343*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextRange(&r.fBottom, -2147483646, 2147483646);
344*c8dee2aaSAndroid Build Coastguard Worker         r.sort();
345*c8dee2aaSAndroid Build Coastguard Worker         fuzz->nextEnum(&op, SkRegion::kLastOp);
346*c8dee2aaSAndroid Build Coastguard Worker         if (!region->op(r, op)) {
347*c8dee2aaSAndroid Build Coastguard Worker             return;
348*c8dee2aaSAndroid Build Coastguard Worker         }
349*c8dee2aaSAndroid Build Coastguard Worker     }
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker 
FuzzCreateValidInputsForRuntimeEffect(SkRuntimeEffect * effect,sk_sp<SkData> & uniformBytes,TArray<SkRuntimeEffect::ChildPtr> & children)352*c8dee2aaSAndroid Build Coastguard Worker void FuzzCreateValidInputsForRuntimeEffect(SkRuntimeEffect* effect,
353*c8dee2aaSAndroid Build Coastguard Worker                                            sk_sp<SkData>& uniformBytes,
354*c8dee2aaSAndroid Build Coastguard Worker                                            TArray<SkRuntimeEffect::ChildPtr>& children) {
355*c8dee2aaSAndroid Build Coastguard Worker     // Create storage for our uniforms.
356*c8dee2aaSAndroid Build Coastguard Worker     uniformBytes = SkData::MakeZeroInitialized(effect->uniformSize());
357*c8dee2aaSAndroid Build Coastguard Worker     void* uniformData = uniformBytes->writable_data();
358*c8dee2aaSAndroid Build Coastguard Worker 
359*c8dee2aaSAndroid Build Coastguard Worker     for (const SkRuntimeEffect::Uniform& u : effect->uniforms()) {
360*c8dee2aaSAndroid Build Coastguard Worker         // We treat scalars, vectors, matrices and arrays the same. We just figure out how many
361*c8dee2aaSAndroid Build Coastguard Worker         // uniform slots need to be filled, and write consecutive numbers into those slots.
362*c8dee2aaSAndroid Build Coastguard Worker         static_assert(sizeof(int) == 4 && sizeof(float) == 4);
363*c8dee2aaSAndroid Build Coastguard Worker         size_t numFields = u.sizeInBytes() / 4;
364*c8dee2aaSAndroid Build Coastguard Worker 
365*c8dee2aaSAndroid Build Coastguard Worker         if (u.type == SkRuntimeEffect::Uniform::Type::kInt ||
366*c8dee2aaSAndroid Build Coastguard Worker             u.type == SkRuntimeEffect::Uniform::Type::kInt2 ||
367*c8dee2aaSAndroid Build Coastguard Worker             u.type == SkRuntimeEffect::Uniform::Type::kInt3 ||
368*c8dee2aaSAndroid Build Coastguard Worker             u.type == SkRuntimeEffect::Uniform::Type::kInt4) {
369*c8dee2aaSAndroid Build Coastguard Worker             int intVal = 0;
370*c8dee2aaSAndroid Build Coastguard Worker             while (numFields--) {
371*c8dee2aaSAndroid Build Coastguard Worker                 // Assign increasing integer values to each slot (0, 1, 2, ...).
372*c8dee2aaSAndroid Build Coastguard Worker                 *static_cast<int*>(uniformData) = intVal++;
373*c8dee2aaSAndroid Build Coastguard Worker                 uniformData = static_cast<int*>(uniformData) + 1;
374*c8dee2aaSAndroid Build Coastguard Worker             }
375*c8dee2aaSAndroid Build Coastguard Worker         } else {
376*c8dee2aaSAndroid Build Coastguard Worker             float floatVal = 0.0f;
377*c8dee2aaSAndroid Build Coastguard Worker             while (numFields--) {
378*c8dee2aaSAndroid Build Coastguard Worker                 // Assign increasing float values to each slot (0.0, 1.0, 2.0, ...).
379*c8dee2aaSAndroid Build Coastguard Worker                 *static_cast<float*>(uniformData) = floatVal++;
380*c8dee2aaSAndroid Build Coastguard Worker                 uniformData = static_cast<float*>(uniformData) + 1;
381*c8dee2aaSAndroid Build Coastguard Worker             }
382*c8dee2aaSAndroid Build Coastguard Worker         }
383*c8dee2aaSAndroid Build Coastguard Worker     }
384*c8dee2aaSAndroid Build Coastguard Worker 
385*c8dee2aaSAndroid Build Coastguard Worker     // Create valid children for any requested child effects.
386*c8dee2aaSAndroid Build Coastguard Worker     children.clear();
387*c8dee2aaSAndroid Build Coastguard Worker     children.reserve(effect->children().size());
388*c8dee2aaSAndroid Build Coastguard Worker     for (const SkRuntimeEffect::Child& c : effect->children()) {
389*c8dee2aaSAndroid Build Coastguard Worker         switch (c.type) {
390*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::ChildType::kShader:
391*c8dee2aaSAndroid Build Coastguard Worker                 children.push_back(SkShaders::Color(SK_ColorRED));
392*c8dee2aaSAndroid Build Coastguard Worker                 break;
393*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::ChildType::kColorFilter:
394*c8dee2aaSAndroid Build Coastguard Worker                 children.push_back(SkColorFilters::Blend(SK_ColorBLUE, SkBlendMode::kModulate));
395*c8dee2aaSAndroid Build Coastguard Worker                 break;
396*c8dee2aaSAndroid Build Coastguard Worker             case SkRuntimeEffect::ChildType::kBlender:
397*c8dee2aaSAndroid Build Coastguard Worker                 children.push_back(SkBlenders::Arithmetic(0.50f, 0.25f, 0.10f, 0.05f, false));
398*c8dee2aaSAndroid Build Coastguard Worker                 break;
399*c8dee2aaSAndroid Build Coastguard Worker         }
400*c8dee2aaSAndroid Build Coastguard Worker     }
401*c8dee2aaSAndroid Build Coastguard Worker }
402