blob: c14b29a6e2568ccf881c7ad2bdb55065c2d7f955 [file] [log] [blame]
Kevin Lubickfec1dea2016-11-22 13:57:18 -05001/*
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.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
11#include "SkImage.h"
12#include "SkLayerRasterizer.h"
13#include "SkPath.h"
14#include "SkSurface.h"
15#include "SkTypeface.h"
16
17static const int kBmpSize = 24;
18static const int kMaxX = 250;
19static const int kMaxY = 250;
20static const int kPtsLen = 10;
21static const int kTxtLen = 5;
22
Kevin Lubickfec1dea2016-11-22 13:57:18 -050023static void init_string(Fuzz* fuzz, char* str, size_t bufSize) {
24 for (size_t i = 0; i < bufSize-1; ++i) {
25 fuzz->nextRange(&str[i], 0x20, 0x7E); // printable ASCII
26 }
27 str[bufSize-1] = '\0';
28}
29
30// make_paint mostly borrowed from FilterFuzz.cpp
31static void init_paint(Fuzz* fuzz, SkPaint* p) {
32 bool b;
33 fuzz->next(&b);
34 p->setAntiAlias(b);
35
36 uint8_t tmp_u8;
37 fuzz->nextRange(&tmp_u8, 0, (int)SkBlendMode::kLastMode);
38 p->setBlendMode(static_cast<SkBlendMode>(tmp_u8));
39
40 SkColor co;
41 fuzz->next(&co);
42 p->setColor(co);
43
44 fuzz->next(&b);
45 p->setDither(b);
46
47 fuzz->nextRange(&tmp_u8, 0, (int)kHigh_SkFilterQuality);
48 p->setFilterQuality(static_cast<SkFilterQuality>(tmp_u8));
49
50 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kFull_Hinting);
51 p->setHinting(static_cast<SkPaint::Hinting>(tmp_u8));
52
53 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Cap);
54 p->setStrokeCap(static_cast<SkPaint::Cap>(tmp_u8));
55
56 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kLast_Join);
57 p->setStrokeJoin(static_cast<SkPaint::Join>(tmp_u8));
58
59 SkScalar sc;
60 fuzz->next(&sc);
61 p->setStrokeMiter(sc);
62
63 fuzz->next(&sc);
64 p->setStrokeWidth(sc);
65
66 fuzz->nextRange(&tmp_u8, 0, (int)SkPaint::kStrokeAndFill_Style);
67 p->setStyle(static_cast<SkPaint::Style>(tmp_u8));
68}
69
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050070static void init_bitmap(Fuzz* fuzz, SkBitmap* bmp) {
71 uint8_t colorType;
72 fuzz->nextRange(&colorType, 0, (int)kLastEnum_SkColorType);
73 SkImageInfo info = SkImageInfo::Make(kBmpSize,
74 kBmpSize,
75 (SkColorType)colorType,
76 kPremul_SkAlphaType);
77 if (!bmp->tryAllocPixels(info)) {
78 SkDebugf("Bitmap not allocated\n");
79 }
80 SkCanvas canvas(*bmp);
81 canvas.clear(0);
82
83 bool b;
84 fuzz->next(&b);
85 SkPaint p;
86 if (b) {
87 init_paint(fuzz, &p);
88 }
89 else {
90 SkColor c;
91 fuzz->next(&c);
92 p.setColor(c);
93 }
94 canvas.drawRect(SkRect::MakeXYWH(0, 0, kBmpSize, kBmpSize), p);
95}
Kevin Lubickfec1dea2016-11-22 13:57:18 -050096
97static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
98 uint8_t x, y;
99 fuzz->nextRange(&x, 1, kMaxX);
100 fuzz->nextRange(&y, 1, kMaxY);
101 *s = SkSurface::MakeRasterN32Premul(x, y);
102}
103
104
105static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> font) {
106 SkPaint p;
107 init_paint(fuzz, &p);
108 sk_sp<SkSurface> surface;
109 init_surface(fuzz, &surface);
110
111 char text[kTxtLen];
112 init_string(fuzz, text, kTxtLen);
113
114 SkScalar x, y;
115 fuzz->next(&x, &y);
116 // populate pts array
117 SkPoint pts[kPtsLen];
118 for (uint8_t i = 0; i < kPtsLen; ++i) {
119 pts[i].set(x, y);
120 x += p.getTextSize();
121 }
122
123 p.setTypeface(font);
124 // set text related attributes
125 bool b;
126 fuzz->next(&b);
127 p.setAutohinted(b);
128 fuzz->next(&b);
129 p.setDevKernText(b);
130 fuzz->next(&b);
131 p.setEmbeddedBitmapText(b);
132 fuzz->next(&b);
133 p.setFakeBoldText(b);
134 fuzz->next(&b);
135 p.setLCDRenderText(b);
136 fuzz->next(&b);
137 p.setLinearText(b);
138 fuzz->next(&b);
139 p.setStrikeThruText(b);
140 fuzz->next(&b);
141 p.setSubpixelText(b);
142 fuzz->next(&x);
143 p.setTextScaleX(x);
144 fuzz->next(&x);
145 p.setTextSkewX(x);
146 fuzz->next(&x);
147 p.setTextSize(x);
148 fuzz->next(&b);
149 p.setUnderlineText(b);
150 fuzz->next(&b);
151 p.setVerticalText(b);
152
153 SkCanvas* cnv = surface->getCanvas();
154 cnv->drawPosText(text, (kTxtLen-1), pts, p);
155
156 fuzz->next(&x);
157 fuzz->next(&y);
158 cnv->drawText(text, (kTxtLen-1), x, y, p);
159}
160
161static void fuzz_drawCircle(Fuzz* fuzz) {
162 SkPaint p;
163 init_paint(fuzz, &p);
164 sk_sp<SkSurface> surface;
165 init_surface(fuzz, &surface);
166
167 SkScalar a, b, c;
168 fuzz->next(&a, &b, &c);
169 surface->getCanvas()->drawCircle(a, b, c, p);
170}
171
172static void fuzz_drawLine(Fuzz* fuzz) {
173 SkPaint p;
174 init_paint(fuzz, &p);
175 sk_sp<SkSurface> surface;
176 init_surface(fuzz, &surface);
177
178 SkScalar a, b, c, d;
179 fuzz->next(&a, &b, &c, &d);
180 surface->getCanvas()->drawLine(a, b, c, d, p);
181}
182
183static void fuzz_drawRect(Fuzz* fuzz) {
184 SkPaint p;
185 init_paint(fuzz, &p);
186 sk_sp<SkSurface> surface;
187 init_surface(fuzz, &surface);
188
189 SkScalar a, b, c, d;
190 fuzz->next(&a, &b, &c, &d);
191 SkRect r;
192 r = SkRect::MakeXYWH(a, b, c, d);
193
194 SkCanvas* cnv = surface->getCanvas();
195 cnv->drawRect(r, p);
196
197 bool bl;
198 fuzz->next(&bl);
199 fuzz->next(&a, &b, &c, &d);
200 r = SkRect::MakeXYWH(a, b, c, d);
201 cnv->clipRect(r, SkCanvas::kIntersect_Op, bl);
202}
203
204static void fuzz_drawPath(Fuzz* fuzz) {
205 SkPaint p;
206 init_paint(fuzz, &p);
207 sk_sp<SkSurface> surface;
208 init_surface(fuzz, &surface);
209
210 // TODO(kjlubick): put the ability to fuzz a path in shared file, with
211 // other common things (e.g. rects, lines)
212 uint8_t i, j;
213 fuzz->nextRange(&i, 0, 10); // set i to number of operations to perform
214 SkPath path;
215 SkScalar a, b, c, d, e, f;
216 for (int k = 0; k < i; ++k) {
217 fuzz->nextRange(&j, 0, 5); // set j to choose operation to perform
218 switch (j) {
219 case 0:
220 fuzz->next(&a, &b);
221 path.moveTo(a, b);
222 break;
223 case 1:
224 fuzz->next(&a, &b);
225 path.lineTo(a, b);
226 break;
227 case 2:
228 fuzz->next(&a, &b, &c, &d);
229 path.quadTo(a, b, c, d);
230 break;
231 case 3:
232 fuzz->next(&a, &b, &c, &d, &e);
233 path.conicTo(a, b, c, d, e);
234 break;
235 case 4:
236 fuzz->next(&a, &b, &c, &d, &e, &f);
237 path.cubicTo(a, b, c, d, e, f);
238 break;
239 case 5:
240 fuzz->next(&a, &b, &c, &d, &e);
241 path.arcTo(a, b, c, d, e);
242 break;
243 }
244 }
245 path.close();
246
247 SkCanvas* cnv = surface->getCanvas();
248 cnv->drawPath(path, p);
249
250 bool bl;
251 fuzz->next(&bl);
252 cnv->clipPath(path, SkCanvas::kIntersect_Op, bl);
253}
254
255static void fuzz_drawBitmap(Fuzz* fuzz) {
256 SkPaint p;
257 init_paint(fuzz, &p);
258 sk_sp<SkSurface> surface;
259 init_surface(fuzz, &surface);
260 SkBitmap bmp;
261 init_bitmap(fuzz, &bmp);
262
263 SkScalar a, b;
264 fuzz->next(&a, &b);
265 surface->getCanvas()->drawBitmap(bmp, a, b, &p);
266}
267
268static void fuzz_drawImage(Fuzz* fuzz) {
269 SkPaint p;
270 init_paint(fuzz, &p);
271 sk_sp<SkSurface> surface;
272 init_surface(fuzz, &surface);
273 SkBitmap bmp;
274 init_bitmap(fuzz, &bmp);
275
276 sk_sp<SkImage> image(SkImage::MakeFromBitmap(bmp));
277
278 bool bl;
279 fuzz->next(&bl);
280 SkScalar a, b;
281 fuzz->next(&a, &b);
282 if (bl) {
283 surface->getCanvas()->drawImage(image, a, b, &p);
284 }
285 else {
286 SkRect dst = SkRect::MakeWH(a, b);
287 fuzz->next(&a, &b);
288 SkRect src = SkRect::MakeWH(a, b);
289 uint8_t x;
290 fuzz->nextRange(&x, 0, 1);
291 SkCanvas::SrcRectConstraint cst = (SkCanvas::SrcRectConstraint)x;
292 surface->getCanvas()->drawImageRect(image, src, dst, &p, cst);
293 }
294}
295
296static void fuzz_drawPaint(Fuzz* fuzz) {
297 SkPaint l, p;
298 init_paint(fuzz, &p);
299 sk_sp<SkSurface> surface;
300 init_surface(fuzz, &surface);
301
302 // add layers
303 uint8_t x;
304 fuzz->nextRange(&x, 1, 3); // max 3 layers
305 SkLayerRasterizer::Builder builder;
306 for (int i = 0; i < x; i++) {
307 init_paint(fuzz, &l);
308 builder.addLayer(l);
309 }
310
311 sk_sp<SkLayerRasterizer> raster(builder.detach());
312 p.setRasterizer(raster);
313
314 surface->getCanvas()->drawPaint(p);
315}
316
317DEF_FUZZ(DrawFunctions, fuzz) {
318 uint8_t i;
319 fuzz->next(&i);
320
321 switch(i) {
322 case 0: {
323 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
324 if (f == nullptr) {
325 SkDebugf("Could not initialize font.\n");
326 fuzz->signalBug();
327 }
328 SkDebugf("Fuzz DrawText\n");
329 fuzz_drawText(fuzz, f);
330 return;
331 }
332 case 1:
333 SkDebugf("Fuzz DrawRect\n");
334 fuzz_drawRect(fuzz);
335 return;
336 case 2:
337 SkDebugf("Fuzz DrawCircle\n");
338 fuzz_drawCircle(fuzz);
339 return;
340 case 3:
341 SkDebugf("Fuzz DrawLine\n");
342 fuzz_drawLine(fuzz);
343 return;
344 case 4:
345 SkDebugf("Fuzz DrawPath\n");
346 fuzz_drawPath(fuzz);
347 return;
348 case 5:
349 SkDebugf("Fuzz DrawImage/DrawImageRect\n");
350 fuzz_drawImage(fuzz);
351 return;
352 case 6:
353 SkDebugf("Fuzz DrawBitmap\n");
354 fuzz_drawBitmap(fuzz);
355 return;
356 case 7:
357 SkDebugf("Fuzz DrawPaint\n");
358 fuzz_drawPaint(fuzz);
359 return;
360 }
361}