| Index: src/pathops/SkPathOpsOp.cpp
|
| diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
|
| index 72efb89d101409c24a858813df1c3b1bf607d139..f2b25c04ecb52ab303519752d2db61ccd29168d3 100644
|
| --- a/src/pathops/SkPathOpsOp.cpp
|
| +++ b/src/pathops/SkPathOpsOp.cpp
|
| @@ -45,22 +45,28 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e
|
| continue;
|
| }
|
| const SkOpAngle* firstAngle = angle;
|
| - SkDEBUGCODE(bool loop = false);
|
| - int winding;
|
| + bool loop = false;
|
| + int winding = SK_MinS32;
|
| do {
|
| angle = angle->next();
|
| - SkASSERT(angle != firstAngle || !loop);
|
| - SkDEBUGCODE(loop |= angle == firstAngle);
|
| + if (angle == firstAngle && loop) {
|
| + break; // if we get here, there's no winding, loop is unorderable
|
| + }
|
| + loop |= angle == firstAngle;
|
| segment = angle->segment();
|
| winding = segment->windSum(angle);
|
| } while (winding == SK_MinS32);
|
| + if (winding == SK_MinS32) {
|
| + continue;
|
| + }
|
| int sumMiWinding = segment->updateWindingReverse(angle);
|
| int sumSuWinding = segment->updateOppWindingReverse(angle);
|
| if (segment->operand()) {
|
| SkTSwap<int>(sumMiWinding, sumSuWinding);
|
| }
|
| SkOpSegment* first = NULL;
|
| - while ((angle = angle->next()) != firstAngle) {
|
| + bool badData = false;
|
| + while ((angle = angle->next()) != firstAngle && !badData) {
|
| segment = angle->segment();
|
| int start = angle->start();
|
| int end = angle->end();
|
| @@ -73,11 +79,19 @@ static SkOpSegment* findChaseOp(SkTDArray<SkOpSpan*>& chase, int* tIndex, int* e
|
| *tIndex = start;
|
| *endIndex = end;
|
| }
|
| + if (segment->inconsistentAngle(maxWinding, sumWinding, oppMaxWinding,
|
| + oppSumWinding, angle)) {
|
| + badData = true;
|
| + break;
|
| + }
|
| // OPTIMIZATION: should this also add to the chase?
|
| (void) segment->markAngle(maxWinding, sumWinding, oppMaxWinding,
|
| oppSumWinding, angle);
|
| }
|
| }
|
| + if (badData) {
|
| + continue;
|
| + }
|
| if (first) {
|
| #if TRY_ROTATE
|
| *chase.insert(0) = span;
|
| @@ -245,7 +259,47 @@ static const bool gOutInverse[kReverseDifference_PathOp + 1][2][2] = {
|
| {{ false, true }, { false, false }}, // rev diff
|
| };
|
|
|
| +#define DEBUGGING_PATHOPS_FROM_HOST 0 // enable to debug svg in chrome -- note path hardcoded below
|
| +#if DEBUGGING_PATHOPS_FROM_HOST
|
| +#include "SkData.h"
|
| +#include "SkStream.h"
|
| +
|
| +static void dump_path(FILE* file, const SkPath& path, bool force, bool dumpAsHex) {
|
| + SkDynamicMemoryWStream wStream;
|
| + path.dump(&wStream, force, dumpAsHex);
|
| + SkAutoDataUnref data(wStream.copyToData());
|
| + fprintf(file, "%.*s\n", (int) data->size(), data->data());
|
| +}
|
| +
|
| +static int dumpID = 0;
|
| +
|
| +static void dump_op(const SkPath& one, const SkPath& two, SkPathOp op) {
|
| +#if SK_BUILD_FOR_MAC
|
| + FILE* file = fopen("/Users/caryclark/Documents/svgop.txt", "w");
|
| +#else
|
| + FILE* file = fopen("/usr/local/google/home/caryclark/Documents/svgop.txt", "w");
|
| +#endif
|
| + fprintf(file,
|
| + "\nstatic void fuzz763_%d(skiatest::Reporter* reporter, const char* filename) {\n",
|
| + ++dumpID);
|
| + fprintf(file, " SkPath path;\n");
|
| + fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", one.getFillType());
|
| + dump_path(file, one, false, true);
|
| + fprintf(file, " SkPath path1(path);\n");
|
| + fprintf(file, " path.reset();\n");
|
| + fprintf(file, " path.setFillType((SkPath::FillType) %d);\n", two.getFillType());
|
| + dump_path(file, two, false, true);
|
| + fprintf(file, " SkPath path2(path);\n");
|
| + fprintf(file, " testPathOp(reporter, path1, path2, (SkPathOp) %d, filename);\n", op);
|
| + fprintf(file, "}\n");
|
| + fclose(file);
|
| +}
|
| +#endif
|
| +
|
| bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
|
| +#if DEBUGGING_PATHOPS_FROM_HOST
|
| + dump_op(one, two, op);
|
| +#endif
|
| #if DEBUG_SHOW_TEST_NAME
|
| char* debugName = DEBUG_FILENAME_STRING;
|
| if (debugName && debugName[0]) {
|
|
|