blob: 5029ebe967931a07944fd9870b2b6639107bac7d [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"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050012#include "SkPath.h"
13#include "SkSurface.h"
14#include "SkTypeface.h"
Mike Reedebfce6d2016-12-12 10:02:12 -050015#include "SkClipOpPriv.h"
Kevin Lubickfec1dea2016-11-22 13:57:18 -050016
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);
Kevin Lubick5d5601c2017-02-21 16:06:19 -050073 // ColorType needs to match what the system configuration is.
74 if (colorType == kRGBA_8888_SkColorType || colorType == kBGRA_8888_SkColorType) {
75 colorType = kN32_SkColorType;
76 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050077 bool b;
78 fuzz->next(&b);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050079 SkImageInfo info = SkImageInfo::Make(kBmpSize,
80 kBmpSize,
81 (SkColorType)colorType,
Kevin Lubick8c8b6182017-02-17 10:27:30 -050082 b ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050083 if (!bmp->tryAllocPixels(info)) {
84 SkDebugf("Bitmap not allocated\n");
85 }
Kevin Lubick8c8b6182017-02-17 10:27:30 -050086 SkColor c;
87 fuzz->next(&c);
88 bmp->eraseColor(c);
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050089
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050090 fuzz->next(&b);
91 SkPaint p;
92 if (b) {
93 init_paint(fuzz, &p);
94 }
95 else {
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050096 fuzz->next(&c);
97 p.setColor(c);
98 }
Kevin Lubickcdb4d3c2016-11-29 11:14:39 -050099}
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500100
101static void init_surface(Fuzz* fuzz, sk_sp<SkSurface>* s) {
102 uint8_t x, y;
103 fuzz->nextRange(&x, 1, kMaxX);
104 fuzz->nextRange(&y, 1, kMaxY);
105 *s = SkSurface::MakeRasterN32Premul(x, y);
106}
107
108
109static void fuzz_drawText(Fuzz* fuzz, sk_sp<SkTypeface> font) {
110 SkPaint p;
111 init_paint(fuzz, &p);
112 sk_sp<SkSurface> surface;
113 init_surface(fuzz, &surface);
114
115 char text[kTxtLen];
116 init_string(fuzz, text, kTxtLen);
117
118 SkScalar x, y;
119 fuzz->next(&x, &y);
120 // populate pts array
121 SkPoint pts[kPtsLen];
122 for (uint8_t i = 0; i < kPtsLen; ++i) {
123 pts[i].set(x, y);
124 x += p.getTextSize();
125 }
126
127 p.setTypeface(font);
128 // set text related attributes
129 bool b;
130 fuzz->next(&b);
131 p.setAutohinted(b);
132 fuzz->next(&b);
133 p.setDevKernText(b);
134 fuzz->next(&b);
135 p.setEmbeddedBitmapText(b);
136 fuzz->next(&b);
137 p.setFakeBoldText(b);
138 fuzz->next(&b);
139 p.setLCDRenderText(b);
140 fuzz->next(&b);
141 p.setLinearText(b);
142 fuzz->next(&b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500143 p.setSubpixelText(b);
144 fuzz->next(&x);
145 p.setTextScaleX(x);
146 fuzz->next(&x);
147 p.setTextSkewX(x);
148 fuzz->next(&x);
149 p.setTextSize(x);
150 fuzz->next(&b);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500151 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);
Mike Reedc1f77742016-12-09 09:00:50 -0500201 cnv->clipRect(r, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500202}
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);
Mike Reedc1f77742016-12-09 09:00:50 -0500252 cnv->clipPath(path, kIntersect_SkClipOp, bl);
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500253}
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
Kevin Lubickfec1dea2016-11-22 13:57:18 -0500302 surface->getCanvas()->drawPaint(p);
303}
304
305DEF_FUZZ(DrawFunctions, fuzz) {
306 uint8_t i;
307 fuzz->next(&i);
308
309 switch(i) {
310 case 0: {
311 sk_sp<SkTypeface> f = SkTypeface::MakeDefault();
312 if (f == nullptr) {
313 SkDebugf("Could not initialize font.\n");
314 fuzz->signalBug();
315 }
316 SkDebugf("Fuzz DrawText\n");
317 fuzz_drawText(fuzz, f);
318 return;
319 }
320 case 1:
321 SkDebugf("Fuzz DrawRect\n");
322 fuzz_drawRect(fuzz);
323 return;
324 case 2:
325 SkDebugf("Fuzz DrawCircle\n");
326 fuzz_drawCircle(fuzz);
327 return;
328 case 3:
329 SkDebugf("Fuzz DrawLine\n");
330 fuzz_drawLine(fuzz);
331 return;
332 case 4:
333 SkDebugf("Fuzz DrawPath\n");
334 fuzz_drawPath(fuzz);
335 return;
336 case 5:
337 SkDebugf("Fuzz DrawImage/DrawImageRect\n");
338 fuzz_drawImage(fuzz);
339 return;
340 case 6:
341 SkDebugf("Fuzz DrawBitmap\n");
342 fuzz_drawBitmap(fuzz);
343 return;
344 case 7:
345 SkDebugf("Fuzz DrawPaint\n");
346 fuzz_drawPaint(fuzz);
347 return;
348 }
349}