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