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