xref: /aosp_15_r20/external/skia/fuzz/FuzzDrawFunctions.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2016 Mozilla Foundation
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/SkBitmap.h"
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkFont.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkPath.h"
14 #include "include/core/SkSurface.h"
15 #include "include/core/SkTextBlob.h"
16 #include "include/core/SkTypeface.h"
17 #include "src/core/SkPaintPriv.h"
18 #include "tools/fonts/FontToolUtils.h"
19 
20 static const int kBmpSize = 24;
21 static const int kMaxX = 250;
22 static const int kMaxY = 250;
23 static const int kPtsLen = 10;
24 static const int kTxtLen = 5;
25 
init_string(Fuzz * fuzz,char * str,size_t bufSize)26 static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
27     for (size_t i = 0; i < bufSize-1; ++i) {
28         fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
29     }
30     str[bufSize-1] = '\0';
31 }
32 
33 // make_paint mostly borrowed from FilterFuzz.cpp
init_paint(Fuzz * fuzz,SkPaint * p)34 static void init_paint(Fuzz* fuzz, SkPaint* p) {
35     bool b;
36     fuzz->next(&b);
37     p->setAntiAlias(b);
38 
39     uint8_t tmp_u8;
40     fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
41     p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
42 
43     SkColor co;
44     fuzz->next(&co);
45     p->setColor(co);
46 
47     fuzz->next(&b);
48     p->setDither(b);
49 
50     fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
51     p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
52 
53     fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
54     p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
55 
56     SkScalar sc;
57     fuzz->next(&sc);
58     p->setStrokeMiter(sc);
59 
60     fuzz->next(&sc);
61     p->setStrokeWidth(sc);
62 
63     fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
64     p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
65 }
66 
init_bitmap(Fuzz * fuzz,SkBitmap * bmp)67 static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
68     uint8_t colorType;
69     fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
70     // ColorType needs to match what the system configuration is.
71     if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
72         colorType = kN32_SkColorType;
73     }
74     bool b;
75     fuzz->next(&b);
76     SkImageInfo info = SkImageInfo::Make(kBmpSize,
77                                          kBmpSize,
78                                          (SkColorType)colorType,
79                                          b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
80     if (!bmp->tryAllocPixels(info)) {
81         SkDEBUGF("Bitmap not allocated\n");
82     }
83     SkColor c;
84     fuzz->next(&c);
85     bmp->eraseColor(c);
86 
87     fuzz->next(&b);
88     SkPaint p;
89     if (b) {
90         init_paint(fuzz, &p);
91     }
92     else {
93         fuzz->next(&c);
94         p.setColor(c);
95     }
96 }
97 
init_surface(Fuzz * fuzz,sk_sp<SkSurface> * s)98 static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
99     uint8_t x, y;
100     fuzz->nextRange(&x, 1, kMaxX);
101     fuzz->nextRange(&y, 1, kMaxY);
102     *s = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(x, y));
103 
104     if (!*s) {
105         // Was possibly too big for the memory constrained fuzzing environments
106         *s = SkSurfaces::Null(x, y);
107     }
108 }
109 
110 
fuzz_drawText(Fuzz * fuzz,sk_sp<SkTypeface> typeface)111 static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> typeface) {
112     SkFont font(std::move(typeface));
113     SkPaint p;
114     init_paint(fuzz, &p);
115     sk_sp<SkSurface> surface;
116     init_surface(fuzz, &surface);
117 
118     char text[kTxtLen];
119     init_string(fuzz, text, kTxtLen);
120 
121     SkScalar x, y;
122     fuzz->next(&x, &y);
123     // populate pts array
124     SkPoint pts[kPtsLen];
125     for (uint8_t i = 0; i < kPtsLen; ++i) {
126         pts[i].set(x, y);
127         x += font.getSize();
128     }
129 
130     bool b;
131     fuzz->next(&b);
132     font.setForceAutoHinting(b);
133     fuzz->next(&b);
134     font.setEmbeddedBitmaps(b);
135     fuzz->next(&b);
136     font.setEmbolden(b);
137     fuzz->next(&b);
138     font.setEdging(b ? SkFont::Edging::kAntiAlias : SkFont::Edging::kSubpixelAntiAlias);
139     fuzz->next(&b);
140     font.setLinearMetrics(b);
141     fuzz->next(&b);
142     font.setSubpixel(b);
143     fuzz->next(&x);
144     font.setScaleX(x);
145     fuzz->next(&x);
146     font.setSkewX(x);
147     fuzz->next(&x);
148     font.setSize(x);
149 
150     SkCanvas* cnv = surface->getCanvas();
151     fuzz->next(&x);
152     fuzz->next(&y);
153     cnv->drawTextBlob(SkTextBlob::MakeFromPosText(text, kTxtLen-1, pts, font), x, y, p);
154 }
155 
fuzz_drawCircle(Fuzz * fuzz)156 static void fuzz_drawCircle(Fuzz* fuzz) {
157     SkPaint p;
158     init_paint(fuzz, &p);
159     sk_sp<SkSurface> surface;
160     init_surface(fuzz, &surface);
161 
162     SkScalar a, b, c;
163     fuzz->next(&a, &b, &c);
164     surface->getCanvas()->drawCircle(a, b, c, p);
165 }
166 
fuzz_drawLine(Fuzz * fuzz)167 static void fuzz_drawLine(Fuzz* fuzz) {
168     SkPaint p;
169     init_paint(fuzz, &p);
170     sk_sp<SkSurface> surface;
171     init_surface(fuzz, &surface);
172 
173     SkScalar a, b, c, d;
174     fuzz->next(&a, &b, &c, &d);
175     surface->getCanvas()->drawLine(a, b, c, d, p);
176 }
177 
fuzz_drawRect(Fuzz * fuzz)178 static void fuzz_drawRect(Fuzz* fuzz) {
179     SkPaint p;
180     init_paint(fuzz, &p);
181     sk_sp<SkSurface> surface;
182     init_surface(fuzz, &surface);
183 
184     SkScalar a, b, c, d;
185     fuzz->next(&a, &b, &c, &d);
186     SkRect r;
187     r = SkRect::MakeXYWH(a, b, c, d);
188 
189     SkCanvas* cnv = surface->getCanvas();
190     cnv->drawRect(r, p);
191 
192     bool bl;
193     fuzz->next(&bl);
194     fuzz->next(&a, &b, &c, &d);
195     r = SkRect::MakeXYWH(a, b, c, d);
196     cnv->clipRect(r, SkClipOp::kIntersect, bl);
197 }
198 
fuzz_drawPath(Fuzz * fuzz)199 static void fuzz_drawPath(Fuzz* fuzz) {
200     SkPaint p;
201     init_paint(fuzz, &p);
202     sk_sp<SkSurface> surface;
203     init_surface(fuzz, &surface);
204 
205     // TODO(kjlubick): put the ability to fuzz a path in shared file, with
206     // other common things (e.g. rects, lines)
207     uint8_t i, j;
208     fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
209     SkPath path;
210     SkScalar a, b, c, d, e, f;
211     for (int k = 0; k < i; ++k) {
212         fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
213         switch (j) {
214             case 0:
215                 fuzz->next(&a, &b);
216                 path.moveTo(a, b);
217                 break;
218             case 1:
219                 fuzz->next(&a, &b);
220                 path.lineTo(a, b);
221                 break;
222             case 2:
223                 fuzz->next(&a, &b, &c, &d);
224                 path.quadTo(a, b, c, d);
225                 break;
226             case 3:
227                 fuzz->next(&a, &b, &c, &d, &e);
228                 path.conicTo(a, b, c, d, e);
229                 break;
230             case 4:
231                 fuzz->next(&a, &b, &c, &d, &e, &f);
232                 path.cubicTo(a, b, c, d, e, f);
233                 break;
234             case 5:
235                 fuzz->next(&a, &b, &c, &d, &e);
236                 path.arcTo(a, b, c, d, e);
237                 break;
238         }
239     }
240     path.close();
241 
242     SkCanvas* cnv = surface->getCanvas();
243     cnv->drawPath(path, p);
244 
245     bool bl;
246     fuzz->next(&bl);
247     cnv->clipPath(path, SkClipOp::kIntersect, bl);
248 }
249 
fuzz_drawImage(Fuzz * fuzz)250 static void fuzz_drawImage(Fuzz* fuzz) {
251     SkPaint p;
252     init_paint(fuzz, &p);
253     sk_sp<SkSurface> surface;
254     init_surface(fuzz, &surface);
255     SkBitmap bmp;
256     init_bitmap(fuzz, &bmp);
257 
258     sk_sp<SkImage> image(bmp.asImage());
259 
260     bool bl;
261     fuzz->next(&bl);
262     SkScalar a, b;
263     fuzz->next(&a, &b);
264     if (bl) {
265         surface->getCanvas()->drawImage(image, a, b, SkSamplingOptions(), &p);
266     }
267     else {
268         SkRect dst = SkRect::MakeWH(a, b);
269         fuzz->next(&a, &b);
270         SkRect src = SkRect::MakeWH(a, b);
271         uint8_t x;
272         fuzz->nextRange(&x, 0, 1);
273         SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
274         surface->getCanvas()->drawImageRect(image.get(), src, dst, SkSamplingOptions(), &p, cst);
275     }
276 }
277 
fuzz_drawPaint(Fuzz * fuzz)278 static void fuzz_drawPaint(Fuzz* fuzz) {
279     SkPaint l, p;
280     init_paint(fuzz, &p);
281     sk_sp<SkSurface> surface;
282     init_surface(fuzz, &surface);
283 
284     surface->getCanvas()->drawPaint(p);
285 }
286 
DEF_FUZZ(DrawFunctions,fuzz)287 DEF_FUZZ(DrawFunctions, fuzz) {
288     uint8_t i;
289     fuzz->next(&i);
290 
291     switch(i) {
292         case 0: {
293             sk_sp<SkTypeface> f = ToolUtils::DefaultPortableTypeface();
294             if (f == nullptr) {
295               SkDebugf("Could not initialize font.\n");
296               fuzz->signalBug();
297             }
298             SkDEBUGF("Fuzz DrawText\n");
299             fuzz_drawText(fuzz, f);
300             return;
301         }
302         case 1:
303             SkDEBUGF("Fuzz DrawRect\n");
304             fuzz_drawRect(fuzz);
305             return;
306         case 2:
307             SkDEBUGF("Fuzz DrawCircle\n");
308             fuzz_drawCircle(fuzz);
309             return;
310         case 3:
311             SkDEBUGF("Fuzz DrawLine\n");
312             fuzz_drawLine(fuzz);
313             return;
314         case 4:
315             SkDEBUGF("Fuzz DrawPath\n");
316             fuzz_drawPath(fuzz);
317             return;
318         case 5:
319             SkDEBUGF("Fuzz DrawImage/DrawImageRect\n");
320             fuzz_drawImage(fuzz);
321             return;
322         case 6:
323             SkDEBUGF("Fuzz DrawPaint\n");
324             fuzz_drawPaint(fuzz);
325             return;
326     }
327 }
328