shape ops work in progress

git-svn-id: http://skia.googlecode.com/svn/trunk@4815 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
caryclark@google.com 2012-07-27 18:26:38 +00:00
parent be8cefcc07
commit 27c449af06
6 changed files with 244 additions and 86 deletions

View File

@ -26,6 +26,7 @@ struct State4 {
int b; int b;
int c; int c;
int d; int d;
int testsRun;
char filename[256]; char filename[256];
pthread_t threadID; pthread_t threadID;
SkCanvas* canvas; SkCanvas* canvas;

View File

@ -50,7 +50,7 @@ const bool gRunTestsInOneThread = true;
#define DEBUG_ACTIVE_SPANS 1 #define DEBUG_ACTIVE_SPANS 1
#define DEBUG_ADD_INTERSECTING_TS 0 #define DEBUG_ADD_INTERSECTING_TS 0
#define DEBUG_ADD_T_PAIR 0 #define DEBUG_ADD_T_PAIR 0
#define DEBUG_CONCIDENT 01 #define DEBUG_CONCIDENT 0
#define DEBUG_CROSS 1 #define DEBUG_CROSS 1
#define DEBUG_DUMP 1 #define DEBUG_DUMP 1
#define DEBUG_MARK_DONE 1 #define DEBUG_MARK_DONE 1
@ -656,7 +656,7 @@ struct Bounds : public SkRect {
struct Span { struct Span {
Segment* fOther; Segment* fOther;
mutable SkPoint const* fPt; // lazily computed as needed mutable SkPoint fPt; // lazily computed as needed
double fT; double fT;
double fOtherT; // value at fOther[fOtherIndex].fT double fOtherT; // value at fOther[fOtherIndex].fT
int fOtherIndex; // can't be used during intersection int fOtherIndex; // can't be used during intersection
@ -792,10 +792,10 @@ public:
#if DEBUG_CONCIDENT #if DEBUG_CONCIDENT
SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
__FUNCTION__, fID, other.fID, tIndexStart - 1, __FUNCTION__, fID, other.fID, tIndexStart - 1,
fTs[tIndexStart - 1].fT, xyAtT(tIndexStart - 1).fX, fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
xyAtT(tIndexStart - 1).fY); xyAtT(tIndexStart).fY);
#endif #endif
SkASSERT(0); // incomplete addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT);
} }
if (nextT < 1 && fTs[tIndex].fWindValue) { if (nextT < 1 && fTs[tIndex].fWindValue) {
#if DEBUG_CONCIDENT #if DEBUG_CONCIDENT
@ -812,10 +812,10 @@ public:
#if DEBUG_CONCIDENT #if DEBUG_CONCIDENT
SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n", SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
__FUNCTION__, fID, other.fID, oIndexStart - 1, __FUNCTION__, fID, other.fID, oIndexStart - 1,
other.fTs[oIndexStart - 1].fT, other.xyAtT(oIndexStart - 1).fX, other.fTs[oIndexStart].fT, other.xyAtT(oIndexStart).fX,
other.xyAtT(oIndexStart - 1).fY); other.xyAtT(oIndexStart).fY);
other.debugAddTPair(other.fTs[oIndexStart].fT, *this, fTs[tIndex].fT);
#endif #endif
SkASSERT(0); // incomplete
} }
if (oNextT < 1 && other.fTs[oIndex].fWindValue) { if (oNextT < 1 && other.fTs[oIndex].fWindValue) {
#if DEBUG_CONCIDENT #if DEBUG_CONCIDENT
@ -965,7 +965,7 @@ public:
} }
span->fT = newT; span->fT = newT;
span->fOther = other; span->fOther = other;
span->fPt = NULL; span->fPt.fX = SK_ScalarNaN;
span->fWindSum = SK_MinS32; span->fWindSum = SK_MinS32;
span->fWindValue = 1; span->fWindValue = 1;
if ((span->fDone = newT == 1)) { if ((span->fDone = newT == 1)) {
@ -1068,7 +1068,7 @@ public:
do { do {
if (transfer) { if (transfer) {
if (decrementOther) { if (decrementOther) {
SkASSERT(abs(end->fWindValue) < gDebugMaxWindValue); SkASSERT(abs(end->fWindValue) <= gDebugMaxWindValue);
++(end->fWindValue); ++(end->fWindValue);
} else if (decrementSpan(end)) { } else if (decrementSpan(end)) {
TrackOutside(outsideTs, end->fT, oStartT); TrackOutside(outsideTs, end->fT, oStartT);
@ -1085,7 +1085,7 @@ public:
do { do {
if (transfer) { if (transfer) {
if (!decrementOther) { if (!decrementOther) {
SkASSERT(abs(oEnd->fWindValue) < gDebugMaxWindValue); SkASSERT(abs(oEnd->fWindValue) <= gDebugMaxWindValue);
++(oEnd->fWindValue); ++(oEnd->fWindValue);
} else if (other.decrementSpan(oEnd)) { } else if (other.decrementSpan(oEnd)) {
TrackOutside(oOutsideTs, oEnd->fT, startT); TrackOutside(oOutsideTs, oEnd->fT, startT);
@ -1320,28 +1320,21 @@ public:
// it is guaranteed to have an end which describes a non-zero length (?) // it is guaranteed to have an end which describes a non-zero length (?)
// winding -1 means ccw, 1 means cw // winding -1 means ccw, 1 means cw
// firstFind allows coincident edges to be treated differently // firstFind allows coincident edges to be treated differently
Segment* findNext(SkTDArray<Span*>& chase, int winding, Segment* findNext(SkTDArray<Span*>& chase, bool firstFind, bool active,
int contourWinding, bool firstFind, bool active,
const int startIndex, const int endIndex, int& nextStart, const int startIndex, const int endIndex, int& nextStart,
int& nextEnd, int& spanWinding) { int& nextEnd, int& winding, int& spanWinding) {
start here;
// winding is a mess
// try to simplify what we got
int flipped = 1;
int sumWinding = winding + spanWinding; int sumWinding = winding + spanWinding;
if (sumWinding == 0 || (false && contourWinding && !firstFind)) { if (sumWinding == 0) {
sumWinding = spanWinding; sumWinding = spanWinding;
} }
bool insideContour = contourWinding && contourWinding * sumWinding < 0; bool insideContour = active && winding && winding * sumWinding < 0;
if (insideContour && (true || !firstFind)) { if (insideContour) {
sumWinding = contourWinding; sumWinding = winding;
} }
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("%s winding=%d contourWinding=%d spanWinding=%d sumWinding=%d\n", SkDebugf("%s winding=%d spanWinding=%d sumWinding=%d\n",
__FUNCTION__, winding, contourWinding, spanWinding, sumWinding); __FUNCTION__, winding, spanWinding, sumWinding);
#endif #endif
SkASSERT(startIndex != endIndex); SkASSERT(startIndex != endIndex);
int count = fTs.count(); int count = fTs.count();
@ -1378,7 +1371,7 @@ public:
int firstIndex = findStartingEdge(sorted, startIndex, end); int firstIndex = findStartingEdge(sorted, startIndex, end);
SkASSERT(firstIndex >= 0); SkASSERT(firstIndex >= 0);
#if DEBUG_SORT #if DEBUG_SORT
debugShowSort(sorted, firstIndex, contourWinding, sumWinding); debugShowSort(sorted, firstIndex, winding, sumWinding);
#endif #endif
bool doBump = sorted[firstIndex]->firstBump(sumWinding); bool doBump = sorted[firstIndex]->firstBump(sumWinding);
#if DEBUG_WINDING #if DEBUG_WINDING
@ -1396,8 +1389,9 @@ public:
const Angle* foundAngle = NULL; const Angle* foundAngle = NULL;
bool foundDone = false; bool foundDone = false;
// iterate through the angle, and compute everyone's winding // iterate through the angle, and compute everyone's winding
bool firstEdge = true; bool toggleWinding = false;
bool flopped = false; bool flipFound = false;
int flipped = 1;
Segment* nextSegment; Segment* nextSegment;
do { do {
if (nextIndex == angleCount) { if (nextIndex == angleCount) {
@ -1413,13 +1407,12 @@ public:
maxWinding, sumWinding, nextAngle->sign()); maxWinding, sumWinding, nextAngle->sign());
#endif #endif
if (maxWinding * sumWinding < 0) { if (maxWinding * sumWinding < 0) {
flipped = -flipped; flipFound ^= true;
flopped = true;
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("flipped sign %d %d\n", maxWinding, sumWinding); SkDebugf("flipFound maxWinding=%d sumWinding=%d\n",
maxWinding, sumWinding);
#endif #endif
} }
firstEdge = false;
if (!sumWinding) { if (!sumWinding) {
if (!active) { if (!active) {
markDone(SkMin32(startIndex, endIndex), startWinding); markDone(SkMin32(startIndex, endIndex), startWinding);
@ -1433,10 +1426,11 @@ public:
if (!foundAngle || foundDone) { if (!foundAngle || foundDone) {
foundAngle = nextAngle; foundAngle = nextAngle;
foundDone = nextSegment->done(*nextAngle); foundDone = nextSegment->done(*nextAngle);
if (!flopped && maxWinding * startWinding < 0) { if (flipFound || (maxWinding * startWinding < 0)) {
flipped = -flipped; flipped = -flipped;
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("flopped sign %d %d\n", maxWinding, startWinding); SkDebugf("flipped flipFound=%d maxWinding=%d startWinding=%d\n",
flipFound, maxWinding, startWinding);
#endif #endif
} }
} }
@ -1444,10 +1438,20 @@ public:
} }
if (!maxWinding && innerSwap && !foundAngle) { if (!maxWinding && innerSwap && !foundAngle) {
if (sumWinding * startWinding < 0 && flipped > 0) { if (sumWinding * startWinding < 0 && flipped > 0) {
SkDebugf("%s flip?\n"); #if DEBUG_WINDING
// flipped = -flipped; SkDebugf("%s toggleWinding\n");
#endif
toggleWinding = true;
} else if (startWinding != sumWinding) {
winding = sumWinding;
} }
foundAngle = nextAngle; foundAngle = nextAngle;
if (flipFound) {
flipped = -1;
#if DEBUG_WINDING
SkDebugf("flipped flipFound=%d\n", flipFound);
#endif
}
} }
if (nextSegment->done()) { if (nextSegment->done()) {
continue; continue;
@ -1481,6 +1485,20 @@ public:
nextSegment = foundAngle->segment(); nextSegment = foundAngle->segment();
spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue( spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue(
SkMin32(nextStart, nextEnd)); SkMin32(nextStart, nextEnd));
if (toggleWinding) {
if (winding) {
winding = 0;
} else {
winding = -startWinding;
}
}
#if 0
int min = SkMin32(nextStart, nextEnd);
int sign = foundAngle->sign();
int windSum = nextSegment->windSum(min);
int windValue = nextSegment->windValue(min);
SkASSERT(winding + sign * windValue == windSum);
#endif
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("%s spanWinding=%d\n", __FUNCTION__, spanWinding); SkDebugf("%s spanWinding=%d\n", __FUNCTION__, spanWinding);
#endif #endif
@ -2013,18 +2031,16 @@ public:
} }
const SkPoint& xyAtT(const Span* span) const { const SkPoint& xyAtT(const Span* span) const {
if (!span->fPt) { if (SkScalarIsNaN(span->fPt.fX)) {
if (span->fT == 0) { if (span->fT == 0) {
span->fPt = &fPts[0]; span->fPt = fPts[0];
} else if (span->fT == 1) { } else if (span->fT == 1) {
span->fPt = &fPts[fVerb]; span->fPt = fPts[fVerb];
} else { } else {
SkPoint* pt = fIntersections.append(); (*SegmentXYAtT[fVerb])(fPts, span->fT, &span->fPt);
(*SegmentXYAtT[fVerb])(fPts, span->fT, pt);
span->fPt = pt;
} }
} }
return *span->fPt; return span->fPt;
} }
SkScalar yAtT(int index) const { SkScalar yAtT(int index) const {
@ -2153,10 +2169,6 @@ private:
SkPath::Verb fVerb; SkPath::Verb fVerb;
Bounds fBounds; Bounds fBounds;
SkTDArray<Span> fTs; // two or more (always includes t=0 t=1) SkTDArray<Span> fTs; // two or more (always includes t=0 t=1)
// OPTIMIZATION:if intersections array is a pointer, the it could only
// be allocated as needed instead of always initialized -- though maybe
// the initialization is lightweight enough that it hardly matters
mutable SkTDArray<SkPoint> fIntersections;
int fDoneSpans; // used for quick check that segment is finished int fDoneSpans; // used for quick check that segment is finished
#if DEBUG_DUMP #if DEBUG_DUMP
int fID; int fID;
@ -3250,6 +3262,11 @@ static void debugShowActiveSpans(SkTDArray<Contour*>& contourList) {
} }
#endif #endif
static bool windingIsActive(int winding, int spanWinding) {
return winding * spanWinding <= 0 && abs(winding) <= abs(spanWinding)
&& (!winding || !spanWinding || winding == -spanWinding);
}
// Each segment may have an inside or an outside. Segments contained within // Each segment may have an inside or an outside. Segments contained within
// winding may have insides on either side, and form a contour that should be // winding may have insides on either side, and form a contour that should be
// ignored. Segments that are coincident with opposing direction segments may // ignored. Segments that are coincident with opposing direction segments may
@ -3286,21 +3303,26 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
bool firstTime = true; bool firstTime = true;
int winding = contourWinding; int winding = contourWinding;
int spanWinding = current->spanSign(index, endIndex); int spanWinding = current->spanSign(index, endIndex);
// int firstWinding = contourWinding + spanWinding; int spanWindSum = current->windSum(SkMin32(index, endIndex));
if (spanWindSum != SK_MinS32) {
int calcWinding = spanWindSum;
if (spanWinding > 0) {
// calcWinding -= spanWinding;
}
SkDebugf("%s *** winding=%d calcWinding=%d\n", __FUNCTION__,
winding, calcWinding);
winding = calcWinding;
}
// FIXME: needs work. While it works in limited situations, it does // FIXME: needs work. While it works in limited situations, it does
// not always compute winding correctly. Active should be removed and instead // not always compute winding correctly. Active should be removed and instead
// the initial winding should be correctly passed in so that if the // the initial winding should be correctly passed in so that if the
// inner contour is wound the same way, it never finds an accumulated // inner contour is wound the same way, it never finds an accumulated
// winding of zero. Inside 'find next', we need to look for transitions // winding of zero. Inside 'find next', we need to look for transitions
// other than zero when resolving sorted angles. // other than zero when resolving sorted angles.
bool active = windingIsActive(winding, spanWinding);
SkTDArray<Span*> chaseArray; SkTDArray<Span*> chaseArray;
do { do {
bool active = winding * spanWinding <= 0
&& abs(winding) <= abs(spanWinding);
#if DEBUG_WINDING #if DEBUG_WINDING
if (abs(winding) > abs(spanWinding) && winding * spanWinding < 0) {
SkDebugf("%s *** unexpected active?\n", __FUNCTION__);
}
SkDebugf("%s active=%s winding=%d spanWinding=%d\n", SkDebugf("%s active=%s winding=%d spanWinding=%d\n",
__FUNCTION__, active ? "true" : "false", __FUNCTION__, active ? "true" : "false",
winding, spanWinding); winding, spanWinding);
@ -3309,9 +3331,9 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
do { do {
SkASSERT(!current->done()); SkASSERT(!current->done());
int nextStart, nextEnd; int nextStart, nextEnd;
Segment* next = current->findNext(chaseArray, winding, Segment* next = current->findNext(chaseArray,
contourWinding, firstTime, active, index, endIndex, firstTime, active, index, endIndex,
nextStart, nextEnd, spanWinding); nextStart, nextEnd, winding, spanWinding);
if (!next) { if (!next) {
break; break;
} }
@ -3341,30 +3363,27 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
spanWinding = current->windSum(lesser); spanWinding = current->windSum(lesser);
int spanValue = current->windValue(lesser); int spanValue = current->windValue(lesser);
SkASSERT(spanWinding != SK_MinS32); SkASSERT(spanWinding != SK_MinS32);
int spanSign = current->spanSign(index, endIndex);
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("%s spanWinding=%d spanSign=%d winding=%d spanValue=%d\n", SkDebugf("%s spanWinding=%d winding=%d spanValue=%d\n",
__FUNCTION__, spanWinding, spanSign, winding, spanValue); __FUNCTION__, spanWinding, winding, spanValue);
#endif #endif
if (spanWinding * spanSign < 0) { if (abs(spanWinding) != spanValue) {
#if DEBUG_WINDING
SkDebugf("%s spanWinding * spanSign < 0\n", __FUNCTION__);
#endif
// SkTSwap<int>(index, endIndex);
}
if (abs(spanWinding) > spanValue) {
winding = spanWinding; winding = spanWinding;
spanWinding = spanValue * SkSign32(spanWinding); spanWinding = spanValue * SkSign32(spanWinding);
winding -= spanWinding; winding -= spanWinding;
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("%s spanWinding=%d winding=%d\n", __FUNCTION__, SkDebugf("%s != spanWinding=%d winding=%d\n", __FUNCTION__,
spanWinding, winding); spanWinding, winding);
#endif #endif
} else { active = windingIsActive(winding, spanWinding);
} else if (winding) {
#if DEBUG_WINDING #if DEBUG_WINDING
SkDebugf("%s ->0 contourWinding=%d winding=%d\n", __FUNCTION__, SkDebugf("%s ->0 contourWinding=%d winding=%d\n", __FUNCTION__,
contourWinding, winding); contourWinding, winding);
#endif #endif
// start here;
// set active=false if it was false when chase was created
active = abs(winding) <= abs(spanWinding);
winding = 0; winding = 0;
} }
} while (true); } while (true);

View File

@ -18,7 +18,7 @@ namespace SimplifyFindNextTest {
#include "Intersection_Tests.h" #include "Intersection_Tests.h"
static const SimplifyFindNextTest::Segment* testCommon( static const SimplifyFindNextTest::Segment* testCommon(
int winding, int startIndex, int endIndex, int contourWinding, int spanWinding, int startIndex, int endIndex,
SkTArray<SimplifyFindNextTest::Contour>& contours) { SkTArray<SimplifyFindNextTest::Contour>& contours) {
SkTDArray<SimplifyFindNextTest::Contour*> contourList; SkTDArray<SimplifyFindNextTest::Contour*> contourList;
makeContourList(contours, contourList); makeContourList(contours, contourList);
@ -34,8 +34,9 @@ static const SimplifyFindNextTest::Segment* testCommon(
pts[0] = segment.xyAtT(&segment.span(endIndex)); pts[0] = segment.xyAtT(&segment.span(endIndex));
int nextStart, nextEnd; int nextStart, nextEnd;
SkTDArray<SimplifyFindNextTest::Span*> chaseArray; SkTDArray<SimplifyFindNextTest::Span*> chaseArray;
SimplifyFindNextTest::Segment* next = segment.findNext(chaseArray, winding, SimplifyFindNextTest::Segment* next = segment.findNext(chaseArray,
0, true, true, startIndex, endIndex, nextStart, nextEnd, winding); true, true, startIndex, endIndex, nextStart, nextEnd,
contourWinding, spanWinding);
pts[1] = next->xyAtT(&next->span(nextStart)); pts[1] = next->xyAtT(&next->span(nextStart));
SkASSERT(pts[0] == pts[1]); SkASSERT(pts[0] == pts[1]);
return next; return next;
@ -44,17 +45,19 @@ static const SimplifyFindNextTest::Segment* testCommon(
static void test(const SkPath& path) { static void test(const SkPath& path) {
SkTArray<SimplifyFindNextTest::Contour> contours; SkTArray<SimplifyFindNextTest::Contour> contours;
SimplifyFindNextTest::EdgeBuilder builder(path, contours); SimplifyFindNextTest::EdgeBuilder builder(path, contours);
int winding = 0; int contourWinding = 0;
int spanWinding = 1;
int start = 0; int start = 0;
int end = 1; int end = 1;
testCommon(winding, start, end, contours); testCommon(contourWinding, spanWinding, start, end, contours);
} }
static void test(const SkPath& path, int start, int end) { static void test(const SkPath& path, int start, int end) {
SkTArray<SimplifyFindNextTest::Contour> contours; SkTArray<SimplifyFindNextTest::Contour> contours;
SimplifyFindNextTest::EdgeBuilder builder(path, contours); SimplifyFindNextTest::EdgeBuilder builder(path, contours);
int winding = 0; int contourWinding = 0;
testCommon(winding, start, end, contours); int spanWinding = 1;
testCommon(contourWinding, spanWinding, start, end, contours);
} }
static void testLine1() { static void testLine1() {

View File

@ -582,12 +582,78 @@ static void testLine59() {
testSimplifyx(path); testSimplifyx(path);
} }
static void (*firstTest)() = 0; static void testLine60() {
SkPath path, simple;
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(6, 12, 18, 18, (SkPath::Direction) 1);
path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
testSimplifyx(path);
}
static void testLine61() {
SkPath path, simple;
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(12, 0, 24, 24, (SkPath::Direction) 1);
path.addRect(12, 0, 21, 21, (SkPath::Direction) 1);
testSimplifyx(path);
}
static void testLine62() {
SkPath path, simple;
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
testSimplifyx(path);
}
static void testLine63() {
SkPath path, simple;
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
path.addRect(0, 6, 12, 12, (SkPath::Direction) 1);
path.addRect(0, 32, 9, 36, (SkPath::Direction) 1);
testSimplifyx(path);
}
static void testLine64() {
SkPath path, simple;
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
path.addRect(18, 6, 30, 30, (SkPath::Direction) 0);
testSimplifyx(path);
}
static void testLine65() {
SkPath path, simple;
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
path.addRect(24, 0, 36, 36, (SkPath::Direction) 0);
path.addRect(32, 6, 36, 41, (SkPath::Direction) 1);
testSimplifyx(path);
}
static void testLine66() {
SkPath path, simple;
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 30, 20, 20, (SkPath::Direction) 0);
path.addRect(12, 20, 24, 30, (SkPath::Direction) 0);
testSimplifyx(path);
}
static void (*firstTest)() = testLine66;
static struct { static struct {
void (*fun)(); void (*fun)();
const char* str; const char* str;
} tests[] = { } tests[] = {
TEST(testLine66),
TEST(testLine65),
TEST(testLine64),
TEST(testLine63),
TEST(testLine62),
TEST(testLine61),
TEST(testLine60),
TEST(testLine59), TEST(testLine59),
TEST(testLine58), TEST(testLine58),
TEST(testLine57), TEST(testLine57),
@ -661,8 +727,8 @@ void SimplifyNew_Test() {
return; return;
} }
#ifdef SK_DEBUG #ifdef SK_DEBUG
gDebugMaxWindSum = 3; gDebugMaxWindSum = 4;
gDebugMaxWindValue = 3; gDebugMaxWindValue = 4;
#endif #endif
size_t index = testCount - 1; size_t index = testCount - 1;
if (firstTest) { if (firstTest) {

View File

@ -11,6 +11,7 @@
#include "SkCanvas.h" #include "SkCanvas.h"
#include "SkStream.h" #include "SkStream.h"
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
@ -29,7 +30,11 @@ static const char marker[] =
"\n" "\n"
"var testDivs = [\n"; "var testDivs = [\n";
static const char testLineStr[] = " testLine"; static const char testLineStr[] = " testLine";
#if 0
static const char filename[] = "../../experimental/Intersection/debugXX.txt"; static const char filename[] = "../../experimental/Intersection/debugXX.txt";
#else
static const char filename[] = "/flash/debug/XX.txt";
#endif
static int testNumber; static int testNumber;
static void* testSimplify4x4RectsMain(void* data) static void* testSimplify4x4RectsMain(void* data)
@ -38,6 +43,7 @@ static void* testSimplify4x4RectsMain(void* data)
bzero(pathStr, sizeof(pathStr)); bzero(pathStr, sizeof(pathStr));
SkASSERT(data); SkASSERT(data);
State4& state = *(State4*) data; State4& state = *(State4*) data;
state.testsRun = 0;
int aShape = state.a & 0x03; int aShape = state.a & 0x03;
int aCW = state.a >> 2; int aCW = state.a >> 2;
int bShape = state.b & 0x03; int bShape = state.b & 0x03;
@ -179,6 +185,7 @@ static void* testSimplify4x4RectsMain(void* data)
getcwd(pwd, sizeof(pwd)); getcwd(pwd, sizeof(pwd));
SkDebugf("%s\n", pwd); SkDebugf("%s\n", pwd);
#endif #endif
#if 1
SkFILEWStream outFile(state.filename); SkFILEWStream outFile(state.filename);
if (!outFile.isValid()) { if (!outFile.isValid()) {
continue; continue;
@ -211,8 +218,10 @@ static void* testSimplify4x4RectsMain(void* data)
outFile.writeDecAsText(testNumber); outFile.writeDecAsText(testNumber);
outFile.writeText("),\n"); outFile.writeText("),\n");
outFile.flush(); outFile.flush();
#endif
} }
testSimplifyx(path, out, state.bitmap, state.canvas); testSimplifyx(path, out, state.bitmap, state.canvas);
state.testsRun++;
} }
} }
} }
@ -229,15 +238,16 @@ const int maxThreadsAllocated = 32;
void Simplify4x4RectsThreaded_Test() void Simplify4x4RectsThreaded_Test()
{ {
#ifdef SK_DEBUG #ifdef SK_DEBUG
gDebugMaxWindSum = 3; gDebugMaxWindSum = 4;
gDebugMaxWindValue = 3; gDebugMaxWindValue = 4;
#endif #endif
int maxThreads = 1; int maxThreads = 1;
if (!gRunTestsInOneThread) { if (!gRunTestsInOneThread) {
size_t size;
int threads = -1; int threads = -1;
size_t size = sizeof(threads);
sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0); sysctlbyname("hw.logicalcpu_max", &threads, &size, NULL, 0);
SkDebugf("%s size=%d processors=%d\n", __FUNCTION__, size, threads); SkDebugf("%s errno=%d size=%d processors=%d\n", __FUNCTION__,
errno, size, threads);
if (threads > 0) { if (threads > 0) {
maxThreads = threads; maxThreads = threads;
} else { } else {
@ -272,6 +282,7 @@ void Simplify4x4RectsThreaded_Test()
statePtr->filename[sizeof(filename) - 6] = '0' + threadIndex % 10; statePtr->filename[sizeof(filename) - 6] = '0' + threadIndex % 10;
} }
threadIndex = 0; threadIndex = 0;
int testsRun = 0;
for (int a = 0; a < 8; ++a) { // outermost for (int a = 0; a < 8; ++a) { // outermost
for (int b = a ; b < 8; ++b) { for (int b = a ; b < 8; ++b) {
for (int c = b ; c < 8; ++c) { for (int c = b ; c < 8; ++c) {
@ -285,6 +296,9 @@ void Simplify4x4RectsThreaded_Test()
createThread(statePtr, testSimplify4x4RectsMain); createThread(statePtr, testSimplify4x4RectsMain);
if (++threadIndex >= maxThreads) { if (++threadIndex >= maxThreads) {
waitForCompletion(threadState, threadIndex); waitForCompletion(threadState, threadIndex);
for (int index = 0; index < maxThreads; ++index) {
testsRun += threadState[index].testsRun;
}
} }
} else { } else {
testSimplify4x4RectsMain(statePtr); testSimplify4x4RectsMain(statePtr);
@ -298,6 +312,9 @@ void Simplify4x4RectsThreaded_Test()
if (!gRunTestsInOneThread) SkDebugf("\n\n%d", a); if (!gRunTestsInOneThread) SkDebugf("\n\n%d", a);
} }
waitForCompletion(threadState, threadIndex); waitForCompletion(threadState, threadIndex);
for (int index = 0; index < maxThreads; ++index) {
testsRun += threadState[index].testsRun;
}
#ifdef SK_DEBUG #ifdef SK_DEBUG
gDebugMaxWindSum = SK_MaxS32; gDebugMaxWindSum = SK_MaxS32;
gDebugMaxWindValue = SK_MaxS32; gDebugMaxWindValue = SK_MaxS32;

View File

@ -587,11 +587,63 @@ path.close();
path.addRect(4, 4, 13, 13, (SkPath::Direction) 1); path.addRect(4, 4, 13, 13, (SkPath::Direction) 1);
</div> </div>
<div id="testLine60">
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(6, 12, 18, 18, (SkPath::Direction) 1);
path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
</div>
<div id="testLine61">
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(12, 0, 24, 24, (SkPath::Direction) 1);
path.addRect(12, 0, 21, 21, (SkPath::Direction) 1);
</div>
<div id="testLine62">
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 0, 20, 20, (SkPath::Direction) 0);
path.addRect(0, 12, 12, 12, (SkPath::Direction) 0);
path.addRect(4, 12, 13, 13, (SkPath::Direction) 1);
</div>
<div id="testLine63">
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 10, 20, 20, (SkPath::Direction) 0);
path.addRect(0, 6, 12, 12, (SkPath::Direction) 1);
path.addRect(0, 32, 9, 36, (SkPath::Direction) 1);
</div>
<div id="testLine64">
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(10, 40, 30, 30, (SkPath::Direction) 0);
path.addRect(18, 6, 30, 30, (SkPath::Direction) 0);
</div>
<div id="testLine65">
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(10, 0, 30, 30, (SkPath::Direction) 0);
path.addRect(24, 0, 36, 36, (SkPath::Direction) 0);
path.addRect(32, 6, 36, 41, (SkPath::Direction) 1);
</div>
<div id="testLine66">
path.addRect(0, 0, 60, 60, (SkPath::Direction) 0);
path.addRect(0, 30, 20, 20, (SkPath::Direction) 0);
path.addRect(12, 20, 24, 30, (SkPath::Direction) 0);
</div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var testDivs = [ var testDivs = [
testLine66,
testLine65,
testLine64,
testLine63,
testLine62,
testLine61,
testLine60,
testLine59, testLine59,
testLine58, testLine58,
testLine57, testLine57,