Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Unified Diff: samplecode/SamplePathFuzz.cpp

Issue 953383002: fuzzer fixes (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix up width and height in initializer Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « samplecode/SamplePathEffects.cpp ('k') | samplecode/SampleStrokePath.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: samplecode/SamplePathFuzz.cpp
diff --git a/samplecode/SamplePathFuzz.cpp b/samplecode/SamplePathFuzz.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d6b11c5971012ad51158ab21e6c896a2ba4677e1
--- /dev/null
+++ b/samplecode/SamplePathFuzz.cpp
@@ -0,0 +1,651 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SampleCode.h"
+#include "SkView.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkPath.h"
+#include "SkMatrix.h"
+#include "SkColor.h"
+#include "SkTDArray.h"
+#include "SkRandom.h"
+
+enum RandomAddPath {
+ kMoveToPath,
+ kRMoveToPath,
+ kLineToPath,
+ kRLineToPath,
+ kQuadToPath,
+ kRQuadToPath,
+ kConicToPath,
+ kRConicToPath,
+ kCubicToPath,
+ kRCubicToPath,
+ kArcToPath,
+ kArcTo2Path,
+ kClosePath,
+ kAddArc,
+ kAddRoundRect1,
+ kAddRoundRect2,
+ kAddRRect,
+ kAddPoly,
+ kAddPath1,
+ kAddPath2,
+ kAddPath3,
+ kReverseAddPath,
+};
+
+const int kRandomAddPath_Last = kReverseAddPath;
+
+const char* gRandomAddPathNames[] = {
+ "kMoveToPath",
+ "kRMoveToPath",
+ "kLineToPath",
+ "kRLineToPath",
+ "kQuadToPath",
+ "kRQuadToPath",
+ "kConicToPath",
+ "kRConicToPath",
+ "kCubicToPath",
+ "kRCubicToPath",
+ "kArcToPath",
+ "kArcTo2Path",
+ "kClosePath",
+ "kAddArc",
+ "kAddRoundRect1",
+ "kAddRoundRect2",
+ "kAddRRect",
+ "kAddPoly",
+ "kAddPath1",
+ "kAddPath2",
+ "kAddPath3",
+ "kReverseAddPath",
+};
+
+enum RandomSetRRect {
+ kSetEmpty,
+ kSetRect,
+ kSetOval,
+ kSetRectXY,
+ kSetNinePatch,
+ kSetRectRadii,
+};
+
+const char* gRandomSetRRectNames[] = {
+ "kSetEmpty",
+ "kSetRect",
+ "kSetOval",
+ "kSetRectXY",
+ "kSetNinePatch",
+ "kSetRectRadii",
+};
+
+int kRandomSetRRect_Last = kSetRectRadii;
+
+enum RandomSetMatrix {
+ kSetIdentity,
+ kSetTranslate,
+ kSetTranslateX,
+ kSetTranslateY,
+ kSetScale,
+ kSetScaleTranslate,
+ kSetScaleX,
+ kSetScaleY,
+ kSetSkew,
+ kSetSkewTranslate,
+ kSetSkewX,
+ kSetSkewY,
+ kSetRotate,
+ kSetRotateTranslate,
+ kSetPerspectiveX,
+ kSetPerspectiveY,
+ kSetAll,
+};
+
+int kRandomSetMatrix_Last = kSetAll;
+
+const char* gRandomSetMatrixNames[] = {
+ "kSetIdentity",
+ "kSetTranslate",
+ "kSetTranslateX",
+ "kSetTranslateY",
+ "kSetScale",
+ "kSetScaleTranslate",
+ "kSetScaleX",
+ "kSetScaleY",
+ "kSetSkew",
+ "kSetSkewTranslate",
+ "kSetSkewX",
+ "kSetSkewY",
+ "kSetRotate",
+ "kSetRotateTranslate",
+ "kSetPerspectiveX",
+ "kSetPerspectiveY",
+ "kSetAll",
+};
+
+class FuzzPath {
+public:
+ FuzzPath()
+ : fFloatMin(0)
+ , fFloatMax(800)
+ , fAddCount(0)
+ , fPrintName(false)
+ , fValidate(false)
+ {
+ fTab = " ";
+ }
+ void randomize() {
+ fPathDepth = 0;
+ fPathDepthLimit = fRand.nextRangeU(1, 2);
+ fPathContourCount = fRand.nextRangeU(1, 4);
+ fPathSegmentLimit = fRand.nextRangeU(1, 8);
+ fClip = makePath();
+ SkASSERT(!fPathDepth);
+ fMatrix = makeMatrix();
+ fPaint = makePaint();
+ fPathDepthLimit = fRand.nextRangeU(1, 3);
+ fPathContourCount = fRand.nextRangeU(1, 6);
+ fPathSegmentLimit = fRand.nextRangeU(1, 16);
+ fPath = makePath();
+ SkASSERT(!fPathDepth);
+ }
+
+ const SkPath& getClip() const {
+ return fClip;
+ }
+
+ const SkMatrix& getMatrix() const {
+ return fMatrix;
+ }
+
+ const SkPaint& getPaint() const {
+ return fPaint;
+ }
+
+ const SkPath& getPath() const {
+ return fPath;
+ }
+
+private:
+
+SkPath::AddPathMode makeAddPathMode() {
+ return (SkPath::AddPathMode) fRand.nextRangeU(SkPath::kAppend_AddPathMode,
+ SkPath::kExtend_AddPathMode);
+}
+
+RandomAddPath makeAddPathType() {
+ return (RandomAddPath) fRand.nextRangeU(0, kRandomAddPath_Last);
+}
+
+SkScalar makeAngle() {
+ SkScalar angle;
+ angle = fRand.nextF();
+ return angle;
+}
+
+bool makeBool() {
+ return fRand.nextBool();
+}
+
+SkPath::Direction makeDirection() {
+ return (SkPath::Direction) fRand.nextRangeU(SkPath::kCW_Direction, SkPath::kCCW_Direction);
+}
+
+SkMatrix makeMatrix() {
+ SkMatrix matrix;
+ matrix.reset();
+ RandomSetMatrix setMatrix = (RandomSetMatrix) fRand.nextRangeU(0, kRandomSetMatrix_Last);
+ if (fPrintName) {
+ SkDebugf("%.*s%s\n", fPathDepth * 3, fTab, gRandomSetMatrixNames[setMatrix]);
+ }
+ switch (setMatrix) {
+ case kSetIdentity:
+ break;
+ case kSetTranslateX:
+ matrix.setTranslateX(makeScalar());
+ break;
+ case kSetTranslateY:
+ matrix.setTranslateY(makeScalar());
+ break;
+ case kSetTranslate:
+ matrix.setTranslate(makeScalar(), makeScalar());
+ break;
+ case kSetScaleX:
+ matrix.setScaleX(makeScalar());
+ break;
+ case kSetScaleY:
+ matrix.setScaleY(makeScalar());
+ break;
+ case kSetScale:
+ matrix.setScale(makeScalar(), makeScalar());
+ break;
+ case kSetScaleTranslate:
+ matrix.setScale(makeScalar(), makeScalar(), makeScalar(), makeScalar());
+ break;
+ case kSetSkewX:
+ matrix.setSkewX(makeScalar());
+ break;
+ case kSetSkewY:
+ matrix.setSkewY(makeScalar());
+ break;
+ case kSetSkew:
+ matrix.setSkew(makeScalar(), makeScalar());
+ break;
+ case kSetSkewTranslate:
+ matrix.setSkew(makeScalar(), makeScalar(), makeScalar(), makeScalar());
+ break;
+ case kSetRotate:
+ matrix.setRotate(makeScalar());
+ break;
+ case kSetRotateTranslate:
+ matrix.setRotate(makeScalar(), makeScalar(), makeScalar());
+ break;
+ case kSetPerspectiveX:
+ matrix.setPerspX(makeScalar());
+ break;
+ case kSetPerspectiveY:
+ matrix.setPerspY(makeScalar());
+ break;
+ case kSetAll:
+ matrix.setAll(makeScalar(), makeScalar(), makeScalar(),
+ makeScalar(), makeScalar(), makeScalar(),
+ makeScalar(), makeScalar(), makeScalar());
+ break;
+ }
+ return matrix;
+}
+
+SkPaint makePaint() {
+ SkPaint paint;
+ bool antiAlias = fRand.nextBool();
+ paint.setAntiAlias(antiAlias);
+ SkPaint::Style style = (SkPaint::Style) fRand.nextRangeU(SkPaint::kFill_Style,
+ SkPaint::kStrokeAndFill_Style);
+ paint.setStyle(style);
+ SkColor color = (SkColor) fRand.nextU();
+ paint.setColor(color);
+ SkScalar width = fRand.nextF();
+ paint.setStrokeWidth(width);
+ SkScalar miter = fRand.nextF();
+ paint.setStrokeMiter(miter);
+ SkPaint::Cap cap = (SkPaint::Cap) fRand.nextRangeU(SkPaint::kButt_Cap, SkPaint::kSquare_Cap);
+ paint.setStrokeCap(cap);
+ SkPaint::Join join = (SkPaint::Join) fRand.nextRangeU(SkPaint::kMiter_Join,
+ SkPaint::kBevel_Join);
+ paint.setStrokeJoin(join);
+ return paint;
+}
+
+SkPoint makePoint() {
+ SkPoint result;
+ makeScalarArray(2, &result.fX);
+ return result;
+}
+
+void makePointArray(size_t arrayCount, SkPoint* points) {
+ for (size_t index = 0; index < arrayCount; ++index) {
+ points[index] = makePoint();
+ }
+}
+
+void makePointArray(SkTDArray<SkPoint>* points) {
+ size_t arrayCount = fRand.nextRangeU(1, 10);
+ for (size_t index = 0; index < arrayCount; ++index) {
+ *points->append() = makePoint();
+ }
+}
+
+SkRect makeRect() {
+ SkRect result;
+ makeScalarArray(4, &result.fLeft);
+ return result;
+}
+
+SkRRect makeRRect() {
+ SkRRect rrect;
+ RandomSetRRect rrectType = makeSetRRectType();
+ if (fPrintName) {
+ SkDebugf("%.*s%s\n", fPathDepth * 3, fTab, gRandomSetRRectNames[rrectType]);
+ }
+ switch (rrectType) {
+ case kSetEmpty:
+ rrect.setEmpty();
+ break;
+ case kSetRect: {
+ SkRect rect = makeRect();
+ rrect.setRect(rect);
+ } break;
+ case kSetOval: {
+ SkRect oval = makeRect();
+ rrect.setOval(oval);
+ } break;
+ case kSetRectXY: {
+ SkRect rect = makeRect();
+ SkScalar xRad = makeScalar();
+ SkScalar yRad = makeScalar();
+ rrect.setRectXY(rect, xRad, yRad);
+ } break;
+ case kSetNinePatch: {
+ SkRect rect = makeRect();
+ SkScalar leftRad = makeScalar();
+ SkScalar topRad = makeScalar();
+ SkScalar rightRad = makeScalar();
+ SkScalar bottomRad = makeScalar();
+ rrect.setNinePatch(rect, leftRad, topRad, rightRad, bottomRad);
+ SkDebugf(""); // keep locals in scope
+ } break;
+ case kSetRectRadii: {
+ SkRect rect = makeRect();
+ SkVector radii[4];
+ makeVectorArray(SK_ARRAY_COUNT(radii), radii);
+ rrect.setRectRadii(rect, radii);
+ } break;
+ }
+ return rrect;
+}
+
+SkPath makePath() {
+ SkPath path;
+ for (uint32_t cIndex = 0; cIndex < fPathContourCount; ++cIndex) {
+ uint32_t segments = makeSegmentCount();
+ for (uint32_t sIndex = 0; sIndex < segments; ++sIndex) {
+ RandomAddPath addPathType = makeAddPathType();
+ ++fAddCount;
+ if (fPrintName) {
+ SkDebugf("%.*s%s\n", fPathDepth * 3, fTab,
+ gRandomAddPathNames[addPathType]);
+ }
+ switch (addPathType) {
+ case kAddArc: {
+ SkRect oval = makeRect();
+ SkScalar startAngle = makeAngle();
+ SkScalar sweepAngle = makeAngle();
+ path.addArc(oval, startAngle, sweepAngle);
+ validate(path);
+ } break;
+ case kAddRoundRect1: {
+ SkRect rect = makeRect();
+ SkScalar rx = makeScalar(), ry = makeScalar();
+ SkPath::Direction dir = makeDirection();
+ path.addRoundRect(rect, rx, ry, dir);
+ validate(path);
+ } break;
+ case kAddRoundRect2: {
+ SkRect rect = makeRect();
+ SkScalar radii[8];
+ makeScalarArray(SK_ARRAY_COUNT(radii), radii);
+ SkPath::Direction dir = makeDirection();
+ path.addRoundRect(rect, radii, dir);
+ validate(path);
+ } break;
+ case kAddRRect: {
+ SkRRect rrect = makeRRect();
+ SkPath::Direction dir = makeDirection();
+ path.addRRect(rrect, dir);
+ validate(path);
+ } break;
+ case kAddPoly: {
+ SkTDArray<SkPoint> points;
+ makePointArray(&points);
+ bool close = makeBool();
+ path.addPoly(&points[0], points.count(), close);
+ validate(path);
+ } break;
+ case kAddPath1:
+ if (fPathDepth < fPathDepthLimit) {
+ ++fPathDepth;
+ SkPath src = makePath();
+ validate(src);
+ SkScalar dx = makeScalar();
+ SkScalar dy = makeScalar();
+ SkPath::AddPathMode mode = makeAddPathMode();
+ path.addPath(src, dx, dy, mode);
+ --fPathDepth;
+ validate(path);
+ }
+ break;
+ case kAddPath2:
+ if (fPathDepth < fPathDepthLimit) {
+ ++fPathDepth;
+ SkPath src = makePath();
+ validate(src);
+ SkPath::AddPathMode mode = makeAddPathMode();
+ path.addPath(src, mode);
+ --fPathDepth;
+ validate(path);
+ }
+ break;
+ case kAddPath3:
+ if (fPathDepth < fPathDepthLimit) {
+ ++fPathDepth;
+ SkPath src = makePath();
+ validate(src);
+ SkMatrix matrix = makeMatrix();
+ SkPath::AddPathMode mode = makeAddPathMode();
+ path.addPath(src, matrix, mode);
+ --fPathDepth;
+ validate(path);
+ }
+ break;
+ case kReverseAddPath:
+ if (fPathDepth < fPathDepthLimit) {
+ ++fPathDepth;
+ SkPath src = makePath();
+ validate(src);
+ path.reverseAddPath(src);
+ --fPathDepth;
+ validate(path);
+ }
+ break;
+ case kMoveToPath: {
+ SkScalar x = makeScalar();
+ SkScalar y = makeScalar();
+ path.moveTo(x, y);
+ validate(path);
+ } break;
+ case kRMoveToPath: {
+ SkScalar x = makeScalar();
+ SkScalar y = makeScalar();
+ path.rMoveTo(x, y);
+ validate(path);
+ } break;
+ case kLineToPath: {
+ SkScalar x = makeScalar();
+ SkScalar y = makeScalar();
+ path.lineTo(x, y);
+ validate(path);
+ } break;
+ case kRLineToPath: {
+ SkScalar x = makeScalar();
+ SkScalar y = makeScalar();
+ path.rLineTo(x, y);
+ validate(path);
+ } break;
+ case kQuadToPath: {
+ SkPoint pt[2];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ path.quadTo(pt[0], pt[1]);
+ validate(path);
+ } break;
+ case kRQuadToPath: {
+ SkPoint pt[2];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ path.rQuadTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY);
+ validate(path);
+ } break;
+ case kConicToPath: {
+ SkPoint pt[2];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ SkScalar weight = makeScalar();
+ path.conicTo(pt[0], pt[1], weight);
+ validate(path);
+ } break;
+ case kRConicToPath: {
+ SkPoint pt[2];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ SkScalar weight = makeScalar();
+ path.rConicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, weight);
+ validate(path);
+ } break;
+ case kCubicToPath: {
+ SkPoint pt[3];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ path.cubicTo(pt[0], pt[1], pt[2]);
+ validate(path);
+ } break;
+ case kRCubicToPath: {
+ SkPoint pt[3];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ path.rCubicTo(pt[0].fX, pt[0].fY, pt[1].fX, pt[1].fY, pt[2].fX, pt[2].fY);
+ validate(path);
+ } break;
+ case kArcToPath: {
+ SkPoint pt[2];
+ makePointArray(SK_ARRAY_COUNT(pt), pt);
+ SkScalar radius = makeScalar();
+ path.arcTo(pt[0], pt[1], radius);
+ validate(path);
+ } break;
+ case kArcTo2Path: {
+ SkRect oval = makeRect();
+ SkScalar startAngle = makeAngle();
+ SkScalar sweepAngle = makeAngle();
+ bool forceMoveTo = makeBool();
+ path.arcTo(oval, startAngle, sweepAngle, forceMoveTo);
+ validate(path);
+ } break;
+ case kClosePath:
+ path.close();
+ validate(path);
+ break;
+ }
+ }
+ }
+ return path;
+}
+
+uint32_t makeSegmentCount() {
+ return fRand.nextRangeU(1, fPathSegmentLimit);
+}
+
+RandomSetRRect makeSetRRectType() {
+ return (RandomSetRRect) fRand.nextRangeU(0, kRandomSetRRect_Last);
+}
+
+SkScalar makeScalar() {
+ SkScalar scalar;
+ scalar = fRand.nextRangeF(fFloatMin, fFloatMax);
+ return scalar;
+}
+
+void makeScalarArray(size_t arrayCount, SkScalar* array) {
+ for (size_t index = 0; index < arrayCount; ++index) {
+ array[index] = makeScalar();
+ }
+}
+
+void makeVectorArray(size_t arrayCount, SkVector* array) {
+ for (size_t index = 0; index < arrayCount; ++index) {
+ array[index] = makeVector();
+ }
+}
+
+SkVector makeVector() {
+ SkVector result;
+ makeScalarArray(2, &result.fX);
+ return result;
+}
+
+void validate(const SkPath& path) {
+ if (fValidate) {
+ SkDEBUGCODE(path.experimentalValidateRef());
+ }
+}
+
+SkRandom fRand;
+SkMatrix fMatrix;
+SkPath fClip;
+SkPaint fPaint;
+SkPath fPath;
+SkScalar fFloatMin;
+SkScalar fFloatMax;
+uint32_t fPathContourCount;
+int fPathDepth;
+int fPathDepthLimit;
+uint32_t fPathSegmentLimit;
+int fAddCount;
+bool fPrintName;
+bool fValidate;
+const char* fTab;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+static bool contains_only_moveTo(const SkPath& path) {
+ int verbCount = path.countVerbs();
+ if (verbCount == 0) {
+ return true;
+ }
+ SkTDArray<uint8_t> verbs;
+ verbs.setCount(verbCount);
+ SkDEBUGCODE(int getVerbResult = ) path.getVerbs(verbs.begin(), verbCount);
+ SkASSERT(getVerbResult == verbCount);
+ for (int index = 0; index < verbCount; ++index) {
+ if (verbs[index] != SkPath::kMove_Verb) {
+ return false;
+ }
+ }
+ return true;
+}
+
+class PathFuzzView : public SampleView {
+public:
+ PathFuzzView() {
+ fDots = 0;
+ }
+protected:
+ // overrides from SkEventSink
+ virtual bool onQuery(SkEvent* evt) {
+ if (SampleCode::TitleQ(*evt)) {
+ SampleCode::TitleR(evt, "PathFuzzer");
+ return true;
+ }
+ return this->INHERITED::onQuery(evt);
+ }
+
+ virtual void onDrawContent(SkCanvas* canvas) {
+ fuzzPath.randomize();
+ const SkPath& path = fuzzPath.getPath();
+ const SkPaint& paint = fuzzPath.getPaint();
+ const SkPath& clip = fuzzPath.getClip();
+ const SkMatrix& matrix = fuzzPath.getMatrix();
+ if (!contains_only_moveTo(clip)) {
+ canvas->clipPath(clip);
+ }
+ canvas->setMatrix(matrix);
+ canvas->drawPath(path, paint);
+ this->inval(NULL);
+ if (++fDots == 8000) {
+ SkDebugf("\n");
+ fDots = 0;
+ }
+ if ((fDots % 100) == 99) {
+ SkDebugf(".");
+ }
+ }
+
+private:
+ FuzzPath fuzzPath;
+ int fDots;
+ typedef SkView INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static SkView* MyFactory() { return new PathFuzzView; }
+static SkViewRegister reg(MyFactory);
« no previous file with comments | « samplecode/SamplePathEffects.cpp ('k') | samplecode/SampleStrokePath.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698