/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "Sample.h"
#include "SkCanvas.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkMatrix.h"
#include "SkColor.h"
#include "SkRandom.h"
static void set2x3(SkMatrix* m, float a, float b, float c, float d, float e, float f) {
m->reset();
m->set(0, a);
m->set(1, b);
m->set(2, c);
m->set(3, d);
m->set(4, e);
m->set(5, f);
}
static SkRandom gRand;
static bool return_large;
static bool return_undef;
static bool quick;
static bool scale_large;
static int scval = 1;
static float transval = 0;
static int R(float x) {
return (int)floor(SkScalarToFloat(gRand.nextUScalar1()) * x);
}
#if defined _WIN32
#pragma warning ( push )
// we are intentionally causing an overflow here
// (warning C4756: overflow in constant arithmetic)
#pragma warning ( disable : 4756 )
#endif
static float huge() {
double d = 1e100;
float f = (float)d;
return f;
}
#if defined _WIN32
#pragma warning ( pop )
#endif
static float make_number() {
float v = 0;
int sel;
if (return_large == true && R(3) == 1) {
sel = R(6);
} else {
sel = R(4);
}
if (return_undef == false && sel == 0) {
sel = 1;
}
if (R(2) == 1) {
v = (float)R(100);
} else {
switch (sel) {
case 0: break;
case 1: v = 0; break;
case 2: v = 0.000001f; break;
case 3: v = 10000; break;
case 4: v = 2000000000; break;
case 5: v = huge(); break;
}
}
if (R(4) == 1) {
v = -v;
}
return v;
}
static SkColor make_color() {
if (R(2) == 1) return 0xFFC0F0A0; else return 0xFF000090;
}
static SkColor make_fill() {
#if 0
int sel;
if (quick == true) sel = 0; else sel = R(6);
switch (sel) {
case 0:
case 1:
case 2:
return make_color();
break;
case 3:
var r = ctx.createLinearGradient(make_number(),make_number(),make_number(),make_number());
for (i=0;i<4;i++)
r.addColorStop(make_number(),make_color());
return r;
break;
case 4:
var r = ctx.createRadialGradient(make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
for (i=0;i<4;i++)
r.addColorStop(make_number(),make_color());
return r;
break;
case 5:
var r = ctx.createPattern(imgObj,"repeat");
if (R(6) == 0)
r.addColorStop(make_number(),make_color());
return r;
break;
}
#else
return make_color();
#endif
}
static void do_fuzz(SkCanvas* canvas) {
SkPath path;
SkPaint paint;
paint.setAntiAlias(true);
for (int i=0;i<100;i++) {
switch (R(33)) {
case 0:
paint.setColor(make_fill());
break;
case 1:
paint.setAlpha(gRand.nextU() & 0xFF);
break;
case 2: {
SkBlendMode mode;
switch (R(3)) {
case 0: mode = SkBlendMode::kSrc; break;
case 1: mode = SkBlendMode::kXor; break;
case 2:
default: // silence warning
mode = SkBlendMode::kSrcOver; break;
}
paint.setBlendMode(mode);
}
break;
case 3:
switch (R(2)) {
case 0: paint.setStrokeCap(SkPaint::kRound_Cap); break;
case 1: paint.setStrokeCap(SkPaint::kButt_Cap); break;
}
break;
case 4:
switch (R(2)) {
case 0: paint.setStrokeJoin(SkPaint::kRound_Join); break;
case 1: paint.setStrokeJoin(SkPaint::kMiter_Join); break;
}
break;
case 5:
paint.setStrokeWidth(make_number());
break;
case 6:
paint.setStrokeMiter(make_number());
break;
case 7:
if (quick == true) break;
paint.setMaskFilter(SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, make_number()));
break;
case 8:
if (quick == true) break;
//ctx.shadowColor = make_fill();
break;
case 9:
if (quick == true) break;
//ctx.shadowOffsetX = make_number();
//ctx.shadowOffsetY = make_number();
break;
case 10:
canvas->restore();
break;
case 11:
canvas->rotate(make_number());
break;
case 12:
canvas->save();
break;
case 13:
canvas->scale(-1,-1);
break;
case 14:
if (quick == true) break;
if (transval == 0) {
transval = make_number();
canvas->translate(transval,0);
} else {
canvas->translate(-transval,0);
transval = 0;
}
break;
case 15: {
SkRect r;
r.set(make_number(),make_number(),make_number(),make_number());
SkPaint::Style s = paint.getStyle();
paint.setStyle(SkPaint::kFill_Style);
canvas->drawRect(r, paint);
paint.setStyle(s);
// clearrect
} break;
case 16:
if (quick == true) break;
// ctx.drawImage(imgObj,make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
break;
case 17: {
SkRect r;
r.set(make_number(),make_number(),make_number(),make_number());
SkPaint::Style s = paint.getStyle();
paint.setStyle(SkPaint::kFill_Style);
canvas->drawRect(r, paint);
paint.setStyle(s);
} break;
case 18:
path.reset();
break;
case 19:
// ctx.clip() is evil.
break;
case 20:
path.close();
break;
case 21: {
SkPaint::Style s = paint.getStyle();
paint.setStyle(SkPaint::kFill_Style);
canvas->drawPath(path, paint);
paint.setStyle(s);
} break;
case 22: {
SkPaint::Style s = paint.getStyle();
paint.setStyle(SkPaint::kFill_Style);
canvas->drawPath(path, paint);
paint.setStyle(s);
} break;
case 23: {
SkRect r;
r.set(make_number(),make_number(),make_number(),make_number());
SkPaint::Style s = paint.getStyle();
paint.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(r, paint);
paint.setStyle(s);
} break;
case 24:
if (quick == true) break;
//ctx.arc(make_number(),make_number(),make_number(),make_number(),make_number(),true);
break;
case 25:
if (quick == true) break;
//ctx.arcTo(make_number(),make_number(),make_number(),make_number(),make_number());
break;
case 26:
if (quick == true) break;
//ctx.bezierCurveTo(make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
break;
case 27:
path.lineTo(make_number(),make_number());
break;
case 28:
path.moveTo(make_number(),make_number());
break;
case 29:
if (quick == true) break;
path.quadTo(make_number(),make_number(),make_number(),make_number());
break;
case 30: {
if (quick == true) break;
SkMatrix matrix;
set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
canvas->concat(matrix);
} break;
case 31: {
if (quick == true) break;
SkMatrix matrix;
set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number());
canvas->setMatrix(matrix);
} break;
case 32:
if (scale_large == true) {
switch (scval) {
case 0: canvas->scale(-1000000000,1);
canvas->scale(-1000000000,1);
scval = 1; break;
case 1: canvas->scale(-.000000001f,1); scval = 2; break;
case 2: canvas->scale(-.000000001f,1); scval = 0; break;
}
}
break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
class FuzzView : public Sample {
public:
FuzzView() {
this->setBGColor(0xFFDDDDDD);
}
protected:
virtual bool onQuery(Sample::Event* evt) {
if (Sample::TitleQ(*evt)) {
Sample::TitleR(evt, "Fuzzer");
return true;
}
return this->INHERITED::onQuery(evt);
}
void drawBG(SkCanvas* canvas) {
canvas->drawColor(0xFFDDDDDD);
}
virtual void onDrawContent(SkCanvas* canvas) {
do_fuzz(canvas);
}
private:
typedef Sample INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
DEF_SAMPLE( return new FuzzView(); )