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

Unified Diff: src/pathops/SkPathOpsOp.cpp

Issue 1394503003: fix some pathops bugs found in 1M skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: init to avoid warning Created 5 years, 2 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 | « src/pathops/SkPathOpsDebug.cpp ('k') | src/pathops/SkPathOpsSimplify.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/pathops/SkPathOpsOp.cpp
diff --git a/src/pathops/SkPathOpsOp.cpp b/src/pathops/SkPathOpsOp.cpp
index be7fae7a8f48a84119e1d4da845d0d97c83701bb..b5e00908fdb858b7457d752e6d0bcf7205d0904c 100644
--- a/src/pathops/SkPathOpsOp.cpp
+++ b/src/pathops/SkPathOpsOp.cpp
@@ -222,6 +222,23 @@ static void dump_op(const SkPath& one, const SkPath& two, SkPathOp op) {
}
#endif
+
+#if DEBUG_T_SECT_LOOP_COUNT
+
+#include "SkMutex.h"
+
+SK_DECLARE_STATIC_MUTEX(debugWorstLoop);
+
+SkOpGlobalState debugWorstState(nullptr, nullptr SkDEBUGPARAMS(nullptr));
+
+void ReportPathOpsDebugging() {
+ debugWorstState.debugLoopReport();
+}
+
+extern void (*gVerboseFinalize)();
+
+#endif
+
bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
bool expectSuccess SkDEBUGPARAMS(const char* testName)) {
SkChunkAlloc allocator(4096); // FIXME: add a constant expression here, tune
@@ -263,7 +280,7 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
return false;
}
#if DEBUG_DUMP_SEGMENTS
- contour.dumpSegments(op);
+ contourList->dumpSegments("seg", op);
#endif
const int xorOpMask = builder.xorMask();
@@ -287,6 +304,9 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
if (!HandleCoincidence(contourList, &coincidence, &allocator)) {
return false;
}
+#if DEBUG_ALIGNMENT
+ contourList->dumpSegments("aligned");
+#endif
// construct closed contours
result->reset();
result->setFillType(fillType);
@@ -300,9 +320,134 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result,
*result = *assembled.nativePath();
result->setFillType(fillType);
}
+#if DEBUG_T_SECT_LOOP_COUNT
+ {
+ SkAutoMutexAcquire autoM(debugWorstLoop);
+ if (!gVerboseFinalize) {
+ gVerboseFinalize = &ReportPathOpsDebugging;
+ }
+ debugWorstState.debugDoYourWorst(&globalState);
+ }
+#endif
return true;
}
+#define DEBUG_VERIFY 0
+
+#if DEBUG_VERIFY
+#include "SkBitmap.h"
+#include "SkCanvas.h"
+#include "SkPaint.h"
+
+const int bitWidth = 64;
+const int bitHeight = 64;
+
+static void debug_scale_matrix(const SkPath& one, const SkPath& two, SkMatrix& scale) {
+ SkRect larger = one.getBounds();
+ larger.join(two.getBounds());
+ SkScalar largerWidth = larger.width();
+ if (largerWidth < 4) {
+ largerWidth = 4;
+ }
+ SkScalar largerHeight = larger.height();
+ if (largerHeight < 4) {
+ largerHeight = 4;
+ }
+ SkScalar hScale = (bitWidth - 2) / largerWidth;
+ SkScalar vScale = (bitHeight - 2) / largerHeight;
+ scale.reset();
+ scale.preScale(hScale, vScale);
+ larger.fLeft *= hScale;
+ larger.fRight *= hScale;
+ larger.fTop *= vScale;
+ larger.fBottom *= vScale;
+ SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft
+ : 16000 < larger.fRight ? 16000 - larger.fRight : 0;
+ SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop
+ : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0;
+ scale.preTranslate(dx, dy);
+}
+
+static int debug_paths_draw_the_same(const SkPath& one, const SkPath& two, SkBitmap& bits) {
+ if (bits.width() == 0) {
+ bits.allocN32Pixels(bitWidth * 2, bitHeight);
+ }
+ SkCanvas canvas(bits);
+ canvas.drawColor(SK_ColorWHITE);
+ SkPaint paint;
+ canvas.save();
+ const SkRect& bounds1 = one.getBounds();
+ canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
+ canvas.drawPath(one, paint);
+ canvas.restore();
+ canvas.save();
+ canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
+ canvas.drawPath(two, paint);
+ canvas.restore();
+ int errors = 0;
+ for (int y = 0; y < bitHeight - 1; ++y) {
+ uint32_t* addr1 = bits.getAddr32(0, y);
+ uint32_t* addr2 = bits.getAddr32(0, y + 1);
+ uint32_t* addr3 = bits.getAddr32(bitWidth, y);
+ uint32_t* addr4 = bits.getAddr32(bitWidth, y + 1);
+ for (int x = 0; x < bitWidth - 1; ++x) {
+ // count 2x2 blocks
+ bool err = addr1[x] != addr3[x];
+ if (err) {
+ errors += addr1[x + 1] != addr3[x + 1]
+ && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
+ }
+ }
+ }
+ return errors;
+}
+
+#endif
+
bool Op(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result) {
+#if DEBUG_VERIFY
+ if (!OpDebug(one, two, op, result, true SkDEBUGPARAMS(nullptr))) {
+ SkDebugf("%s did not expect failure\none: fill=%d\n", __FUNCTION__, one.getFillType());
+ one.dumpHex();
+ SkDebugf("two: fill=%d\n", two.getFillType());
+ two.dumpHex();
+ SkASSERT(0);
+ return false;
+ }
+ SkPath pathOut, scaledPathOut;
+ SkRegion rgnA, rgnB, openClip, rgnOut;
+ openClip.setRect(-16000, -16000, 16000, 16000);
+ rgnA.setPath(one, openClip);
+ rgnB.setPath(two, openClip);
+ rgnOut.op(rgnA, rgnB, (SkRegion::Op) op);
+ rgnOut.getBoundaryPath(&pathOut);
+ SkMatrix scale;
+ debug_scale_matrix(one, two, scale);
+ SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
+ SkPath scaledA, scaledB;
+ scaledA.addPath(one, scale);
+ scaledA.setFillType(one.getFillType());
+ scaledB.addPath(two, scale);
+ scaledB.setFillType(two.getFillType());
+ scaledRgnA.setPath(scaledA, openClip);
+ scaledRgnB.setPath(scaledB, openClip);
+ scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) op);
+ scaledRgnOut.getBoundaryPath(&scaledPathOut);
+ SkBitmap bitmap;
+ SkPath scaledOut;
+ scaledOut.addPath(*result, scale);
+ scaledOut.setFillType(result->getFillType());
+ int errors = debug_paths_draw_the_same(scaledPathOut, scaledOut, bitmap);
+ const int MAX_ERRORS = 9;
+ if (errors > MAX_ERRORS) {
+ SkDebugf("%s did not expect failure\none: fill=%d\n", __FUNCTION__, one.getFillType());
+ one.dumpHex();
+ SkDebugf("two: fill=%d\n", two.getFillType());
+ two.dumpHex();
+ SkASSERT(0);
+ }
+ return true;
+#else
return OpDebug(one, two, op, result, true SkDEBUGPARAMS(nullptr));
+#endif
}
« no previous file with comments | « src/pathops/SkPathOpsDebug.cpp ('k') | src/pathops/SkPathOpsSimplify.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698