diff options
author | 2013-02-22 21:50:07 +0000 | |
---|---|---|
committer | 2013-02-22 21:50:07 +0000 | |
commit | c83c70e911a38aea03db4af8dd9841d0d77bd129 (patch) | |
tree | c957cfecc8e073f178dc13aae8a16d9bd3653e8c /experimental/Intersection/Simplify.cpp | |
parent | f8d7d2731318cdf510ab68e6b3f5ec68ab22c8e2 (diff) |
shape ops work in progress
git-svn-id: http://skia.googlecode.com/svn/trunk@7836 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental/Intersection/Simplify.cpp')
-rw-r--r-- | experimental/Intersection/Simplify.cpp | 371 |
1 files changed, 229 insertions, 142 deletions
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp index 0db33fa77d..dfb36ff791 100644 --- a/experimental/Intersection/Simplify.cpp +++ b/experimental/Intersection/Simplify.cpp @@ -32,7 +32,7 @@ int gDebugMaxWindValue = SK_MaxS32; #define DEBUG_UNUSED 0 // set to expose unused functions -#define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging +#define FORCE_RELEASE 0 // set force release to 1 for multiple thread -- no debugging #if FORCE_RELEASE || defined SK_RELEASE @@ -51,7 +51,7 @@ const bool gRunTestsInOneThread = false; #define DEBUG_MARK_DONE 0 #define DEBUG_PATH_CONSTRUCTION 0 #define DEBUG_SHOW_WINDING 0 -#define DEBUG_SORT 1 +#define DEBUG_SORT 0 #define DEBUG_SWAP_TOP 0 #define DEBUG_UNSORTABLE 0 #define DEBUG_WIND_BUMP 0 @@ -94,6 +94,11 @@ static int gContourID; static int gSegmentID; #endif +#if DEBUG_SORT +static int gDebugSortCountDefault = 3; // SK_MaxS32; +static int gDebugSortCount; +#endif + #if DEBUG_ACTIVE_OP static const char* kShapeOpStr[] = {"diff", "sect", "union", "xor"}; #endif @@ -165,6 +170,11 @@ static int CubicIntersect(const SkPoint a[4], const SkPoint b[4], Intersections& return intersections.fUsed; } +static int CubicIntersect(const SkPoint a[4], Intersections& intersections) { + MAKE_CONST_CUBIC(aCubic, a); + return intersect(aCubic, intersections); +} + static int HLineIntersect(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y, bool flipped, Intersections& intersections) { MAKE_CONST_LINE(aLine, a); @@ -1039,16 +1049,17 @@ struct Bounds : public SkRect { // return outerWinding * innerWinding > 0 // || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0))) static bool useInnerWinding(int outerWinding, int innerWinding) { - // SkASSERT(outerWinding != innerWinding); + SkASSERT(outerWinding != SK_MaxS32); + SkASSERT(innerWinding != SK_MaxS32); int absOut = abs(outerWinding); int absIn = abs(innerWinding); bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn; - if (outerWinding * innerWinding < 0) { #if 0 && DEBUG_WINDING + if (outerWinding * innerWinding < 0) { SkDebugf("%s outer=%d inner=%d result=%s\n", __FUNCTION__, outerWinding, innerWinding, result ? "true" : "false"); -#endif } +#endif return result; } @@ -1553,7 +1564,7 @@ public: ePtr = fPts; } else { // OPTIMIZE? if not active, skip remainder and return xy_at_t(end) - (*SegmentSubDivide[fVerb])(fPts, fTs[start].fT, fTs[end].fT, edge); + subDivide(start, end, edge); ePtr = edge; } if (active) { @@ -1682,9 +1693,19 @@ public: span->fUnsortableEnd = false; int less = -1; while (&span[less + 1] - fTs.begin() > 0 && !span[less].fDone - && !precisely_negative(newT - span[less].fT) - // && approximately_negative(newT - span[less].fT) && xyAtT(&span[less]) == xyAtT(span)) { + double tInterval = newT - span[less].fT; + if (precisely_negative(tInterval)) { + break; + } + if (fVerb == SkPath::kCubic_Verb) { + double tMid = newT - tInterval / 2; + _Point midPt; + CubicXYAtT(fPts, tMid, &midPt); + if (!midPt.approximatelyEqual(xyAtT(span))) { + break; + } + } span[less].fTiny = true; span[less].fDone = true; if (approximately_negative(newT - span[less].fT)) { @@ -1702,9 +1723,19 @@ public: } int more = 1; while (fTs.end() - &span[more - 1] > 1 && !span[more - 1].fDone - && !precisely_negative(span[more].fT - newT) - // && approximately_negative(span[more].fT - newT) && xyAtT(&span[more]) == xyAtT(span)) { + double tEndInterval = span[more].fT - newT; + if (precisely_negative(tEndInterval)) { + break; + } + if (fVerb == SkPath::kCubic_Verb) { + double tMid = newT - tEndInterval / 2; + _Point midEndPt; + CubicXYAtT(fPts, tMid, &midEndPt); + if (!midEndPt.approximatelyEqual(xyAtT(span))) { + break; + } + } span[more - 1].fTiny = true; span[more - 1].fDone = true; if (approximately_negative(span[more].fT - newT)) { @@ -2831,18 +2862,19 @@ public: SkPoint dxyE = leftSegment->dxdy(endIndex); SkPoint dxyS = leftSegment->dxdy(tIndex); double cross = dxyE.cross(dxyS); - bool bumpCheck = bumpsUp && xyE.fY < xyS.fY; + bool bumpCheck = bumpsUp && xyE.fY < xyS.fY && dxyE.fX < 0; #if DEBUG_SWAP_TOP SkDebugf("%s xyE=(%1.9g,%1.9g) xyS=(%1.9g,%1.9g)\n", __FUNCTION__, xyE.fX, xyE.fY, xyS.fX, xyS.fY); - SkDebugf("%s dxyE=(%1.9g,%1.9g) dxyS=(%1.9g,%1.9g) cross=%1.9g bump=%s\n", __FUNCTION__, - dxyE.fX, dxyE.fY, dxyS.fX, dxyS.fY, cross, bumpCheck ? "true" : "false"); - #endif + SkDebugf("%s dxyE=(%1.9g,%1.9g) dxyS=(%1.9g,%1.9g) cross=%1.9g bumpsUp=%s\n", + __FUNCTION__, + dxyE.fX, dxyE.fY, dxyS.fX, dxyS.fY, cross, bumpsUp ? "true" : "false"); if ((cross > 0) ^ bumpCheck) { leftSegment->bumpsUp(tIndex, endIndex); SkDebugf("%s cross bump disagree\n", __FUNCTION__); } - if (bumpCheck) { + #endif + if (cross > 0 || bumpCheck) { #if DEBUG_SWAP_TOP SkDebugf("%s swap\n", __FUNCTION__); #endif @@ -3313,7 +3345,7 @@ the same winding is shared by both. bool bumpsUp(int tStart, int tEnd) const { SkPoint edge[4]; - (*SegmentSubDivide[fVerb])(fPts, fTs[tStart].fT, fTs[tEnd].fT, edge); + subDivide(tStart, tEnd, edge); switch (fVerb) { case SkPath::kLine_Verb: SkASSERT(0); // shouldn't call in for lines @@ -3664,6 +3696,23 @@ the same winding is shared by both. #endif return result; } + + void subDivide(int start, int end, SkPoint edge[4]) const { + edge[0] = fTs[start].fPt; + edge[fVerb] = fTs[end].fPt; + if (fVerb == SkPath::kQuad_Verb || fVerb == SkPath::kCubic_Verb) { + _Point sub[2] = {{ edge[0].fX, edge[0].fY}, {edge[fVerb].fX, edge[fVerb].fY }}; + if (fVerb == SkPath::kQuad_Verb) { + MAKE_CONST_QUAD(aQuad, fPts); + edge[1] = sub_divide(aQuad, sub[0], sub[1], fTs[start].fT, fTs[end].fT).asSkPoint(); + } else { + MAKE_CONST_CUBIC(aCubic, fPts); + sub_divide(aCubic, sub[0], sub[1], fTs[start].fT, fTs[end].fT, sub); + edge[1] = sub[0].asSkPoint(); + edge[2] = sub[1].asSkPoint(); + } + } + } // OPTIMIZATION: mark as debugging only if used solely by tests double t(int tIndex) const { @@ -3841,6 +3890,7 @@ the same winding is shared by both. const SkPoint& xyAtT(const Span* span) const { if (SkScalarIsNaN(span->fPt.fX)) { + SkASSERT(0); // make sure this path is never used if (span->fT == 0) { span->fPt = fPts[0]; } else if (span->fT == 1) { @@ -4119,6 +4169,9 @@ the same winding is shared by both. #if DEBUG_SORT void debugShowSort(const char* fun, const SkTDArray<Angle*>& angles, int first, const int contourWinding, const int oppContourWinding) const { + if (--gDebugSortCount < 0) { + return; + } SkASSERT(angles[first]->segment() == this); SkASSERT(angles.count() > 1); int lastSum = contourWinding; @@ -4127,8 +4180,12 @@ the same winding is shared by both. int windSum = lastSum - spanSign(firstAngle); int oppoSign = oppSign(firstAngle); int oppWindSum = oppLastSum - oppoSign; - SkDebugf("%s %s contourWinding=%d oppContourWinding=%d sign=%d\n", fun, __FUNCTION__, - contourWinding, oppContourWinding, spanSign(angles[first])); + #define WIND_AS_STRING(x) char x##Str[12]; if (!valid_wind(x)) strcpy(x##Str, "?"); \ + else snprintf(x##Str, sizeof(x##Str), "%d", x) + WIND_AS_STRING(contourWinding); + WIND_AS_STRING(oppContourWinding); + SkDebugf("%s %s contourWinding=%s oppContourWinding=%s sign=%d\n", fun, __FUNCTION__, + contourWindingStr, oppContourWindingStr, spanSign(angles[first])); int index = first; bool firstTime = true; do { @@ -4165,13 +4222,7 @@ the same winding is shared by both. start, segment.xAtT(&sSpan), segment.yAtT(&sSpan), end, segment.xAtT(&eSpan), segment.yAtT(&eSpan), angle.sign(), mSpan.fWindValue); - start here; - // create an inline to replace this conditional - if (mSpan.fWindSum == SK_MinS32) { - SkDebugf("?"); - } else { - SkDebugf("%d", mSpan.fWindSum); - } + winding_printf(mSpan.fWindSum); int last, wind; if (opp) { last = oppLastSum; @@ -4180,12 +4231,19 @@ the same winding is shared by both. last = lastSum; wind = windSum; } + bool useInner = valid_wind(last) && valid_wind(wind) && useInnerWinding(last, wind); + WIND_AS_STRING(last); + WIND_AS_STRING(wind); + WIND_AS_STRING(lastSum); + WIND_AS_STRING(oppLastSum); + WIND_AS_STRING(windSum); + WIND_AS_STRING(oppWindSum); + #undef WIND_AS_STRING if (!oppoSign) { - SkDebugf(" %d->%d (max=%d)", last, wind, - useInnerWinding(last, wind) ? wind : last); + SkDebugf(" %s->%s (max=%s)", lastStr, windStr, useInner ? windStr : lastStr); } else { - SkDebugf(" %d->%d (%d->%d)", last, wind, opp ? lastSum : oppLastSum, - opp ? windSum : oppWindSum); + SkDebugf(" %s->%s (%s->%s)", lastStr, windStr, opp ? lastSumStr : oppLastSumStr, + opp ? windSumStr : oppWindSumStr); } SkDebugf(" done=%d tiny=%d opp=%d\n", mSpan.fDone, mSpan.fTiny, opp); #if false && DEBUG_ANGLE @@ -4307,7 +4365,7 @@ public: void addCubic(const SkPoint pts[4]) { fSegments.push_back().addCubic(pts, fOperand, fXor); - fContainsCurves = true; + fContainsCurves = fContainsCubics = true; } int addLine(const SkPoint pts[2]) { @@ -4326,7 +4384,7 @@ public: } int addT(int segIndex, double newT, Contour* other, int otherIndex, const SkPoint& pt) { - containsIntercepts(); + setContainsIntercepts(); return fSegments[segIndex].addT(newT, &other->fSegments[otherIndex], pt); } @@ -4343,9 +4401,9 @@ public: setBounds(); fContainsIntercepts = false; } - - void containsIntercepts() { - fContainsIntercepts = true; + + bool containsCubics() const { + return fContainsCubics; } bool crosses(const Contour* crosser) const { @@ -4405,7 +4463,7 @@ public: void reset() { fSegments.reset(); fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); - fContainsCurves = fContainsIntercepts = fDone = false; + fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false; } void resolveCoincidence(SkTDArray<Contour*>& contourList) { @@ -4591,6 +4649,10 @@ public: return fSegments; } + void setContainsIntercepts() { + fContainsIntercepts = true; + } + void setOperand(bool isOp) { fOperand = isOp; } @@ -4790,7 +4852,8 @@ private: SkTDArray<Coincidence> fCoincidences; SkTDArray<const Contour*> fCrosses; Bounds fBounds; - bool fContainsIntercepts; + bool fContainsIntercepts; // FIXME: is this used by anybody? + bool fContainsCubics; bool fContainsCurves; bool fDone; bool fOperand; // true for the second argument to a binary operator @@ -5135,27 +5198,42 @@ protected: }; #if DEBUG_ADD_INTERSECTING_TS + +#define DEBUG_AS_C_CODE 1 +#if DEBUG_AS_C_CODE +#define CUBIC_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}}" +#define QUAD_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}, {%1.17g,%1.17g}}" +#define LINE_DEBUG_STR "{{%1.17g,%1.17g}, {%1.17g,%1.17g}}" +#define PT_DEBUG_STR "{{%1.17g,%1.17g}}" +#else +#define CUBIC_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" +#define QUAD_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" +#define LINE_DEBUG_STR "(%1.9g,%1.9g %1.9g,%1.9g)" +#define PT_DEBUG_STR "(%1.9g,%1.9g)" +#endif +#define T_DEBUG_STR(t, n) #t "[" #n "]=%1.9g" +#define TX_DEBUG_STR(t) #t "[%d]=%1.9g" +#define CUBIC_DEBUG_DATA(c) c[0].fX, c[0].fY, c[1].fX, c[1].fY, c[2].fX, c[2].fY, c[3].fX, c[3].fY +#define QUAD_DEBUG_DATA(q) q[0].fX, q[0].fY, q[1].fX, q[1].fY, q[2].fX, q[2].fY +#define LINE_DEBUG_DATA(l) l[0].fX, l[0].fY, l[1].fX, l[1].fY +#define PT_DEBUG_DATA(i, n) i.fPt[n].x, i.fPt[n].y + static void debugShowLineIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, wn.pts()[0].fX, wn.pts()[0].fY, - wn.pts()[1].fX, wn.pts()[1].fY); + SkDebugf("%s no intersect " LINE_DEBUG_STR " " LINE_DEBUG_STR "\n", + __FUNCTION__, LINE_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", - __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, i.fPt[0].x, i.fPt[0].y); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " LINE_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], LINE_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); if (pts == 2) { - SkDebugf(" wtTs[1]=%1.9g (%1.9g,%1.9g)", i.fT[0][1], i.fPt[1].x, i.fPt[1].y); + SkDebugf(" " T_DEBUG_STR(wtTs, 1) " " PT_DEBUG_STR, i.fT[0][1], PT_DEBUG_DATA(i, 1)); } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g)", i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, - wn.pts()[1].fX, wn.pts()[1].fY); + SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts())); if (pts == 2) { - SkDebugf(" wnTs[1]=%1.9g", i.fT[1][1]); + SkDebugf(" " T_DEBUG_STR(wnTs, 1), i.fT[1][1]); } SkDebugf("\n"); } @@ -5164,25 +5242,18 @@ static void debugShowQuadLineIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" - " (%1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY, - wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY); + SkDebugf("%s no intersect " QUAD_DEBUG_STR " " LINE_DEBUG_STR "\n", + __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY, - i.fPt[0].x, i.fPt[0].y); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wtTs[%d]=%1.9g (%1.9g,%1.9g)", index, i.fT[0][index], - i.fPt[index].x, i.fPt[index].y); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n)); } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g)", i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, - wn.pts()[1].fX, wn.pts()[1].fY); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wnTs[%d]=%1.9g", index, i.fT[1][index]); + SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts())); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]); } SkDebugf("\n"); } @@ -5191,27 +5262,18 @@ static void debugShowQuadIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" - " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY, - wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY, - wn.pts()[2].fX, wn.pts()[2].fY ); + SkDebugf("%s no intersect " QUAD_DEBUG_STR " " QUAD_DEBUG_STR "\n", + __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, - wt.pts()[1].fX, wt.pts()[1].fY, wt.pts()[2].fX, wt.pts()[2].fY, - i.fPt[0].x, i.fPt[0].y); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wtTs[%d]=%1.9g (%1.9g,%1.9g)", index, i.fT[0][index], i.fPt[index].x, - i.fPt[index].y); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n)); } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)", - i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, - wn.pts()[1].fX, wn.pts()[1].fY, wn.pts()[2].fX, wn.pts()[2].fY); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wnTs[%d]=%1.9g", index, i.fT[1][index]); + SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i.fT[1][0], QUAD_DEBUG_DATA(wn.pts())); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]); } SkDebugf("\n"); } @@ -5220,92 +5282,85 @@ static void debugShowCubicLineIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" - " (%1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY); + SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " LINE_DEBUG_STR "\n", + __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", - __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - i.fPt[0].x, i.fPt[0].y); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wtTs[%d]=%1.9g (%1.9g,%1.9g)", index, i.fT[0][index], i.fPt[index].x, - i.fPt[index].y); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n)); } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g)", - i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wnTs[%d]=%1.9g", index, i.fT[1][index]); + SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i.fT[1][0], LINE_DEBUG_DATA(wn.pts())); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]); } SkDebugf("\n"); } -// FIXME: show more than two intersection points static void debugShowCubicQuadIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" - " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY, - wn.pts()[2].fX, wn.pts()[2].fY ); + SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " QUAD_DEBUG_STR "\n", + __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", - __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - i.fPt[0].x, i.fPt[0].y); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wtTs[%d]=%1.9g (%1.9g,%1.9g)", index, i.fT[0][index], i.fPt[index].x, - i.fPt[index].y); - } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)", - i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY, - wn.pts()[2].fX, wn.pts()[2].fY); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wnTs[%d]=%1.9g", index, i.fT[1][index]); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n)); + } + SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i.fT[1][0], QUAD_DEBUG_DATA(wn.pts())); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]); } SkDebugf("\n"); } -// FIXME: show more than two intersection points static void debugShowCubicIntersection(int pts, const Work& wt, const Work& wn, const Intersections& i) { SkASSERT(i.used() == pts); if (!pts) { - SkDebugf("%s no intersect (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)" - " (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)\n", - __FUNCTION__, wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY, - wn.pts()[2].fX, wn.pts()[2].fY, wn.pts()[3].fX, wn.pts()[3].fY ); + SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CUBIC_DEBUG_STR "\n", + __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CUBIC_DEBUG_DATA(wn.pts())); return; } - SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)", - __FUNCTION__, - i.fT[0][0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY, - wt.pts()[2].fX, wt.pts()[2].fY, wt.pts()[3].fX, wt.pts()[3].fY, - i.fPt[0].x, i.fPt[0].y); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wtTs[%d]=%1.9g (%1.9g,%1.9g)", index, i.fT[0][index], i.fPt[index].x, - i.fPt[index].y); - } - SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g)", - i.fT[1][0], wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY, - wn.pts()[2].fX, wn.pts()[2].fY, wn.pts()[3].fX, wn.pts()[3].fY); - for (int index = 1; index < pts; ++index) { - SkDebugf(" wnTs[%d]=%1.9g", index, i.fT[0][index]); + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i.fT[0][n], PT_DEBUG_DATA(i, n)); + } + SkDebugf(" wnTs[0]=%g " CUBIC_DEBUG_STR, i.fT[1][0], CUBIC_DEBUG_DATA(wn.pts())); + for (int n = 1; n < pts; ++n) { + SkDebugf(" " TX_DEBUG_STR(wnTs), n, i.fT[1][n]); + } + SkDebugf("\n"); +} + +static void debugShowCubicIntersection(int pts, const Work& wt, const Intersections& i) { + SkASSERT(i.used() == pts); + if (!pts) { + SkDebugf("%s no self intersect " CUBIC_DEBUG_STR "\n", __FUNCTION__, + CUBIC_DEBUG_DATA(wt.pts())); + return; } + SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__, + i.fT[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0)); + SkDebugf(" " T_DEBUG_STR(wtTs, 1), i.fT[1][0]); SkDebugf("\n"); } +#undef CUBIC_DEBUG_STR +#undef QUAD_DEBUG_STR +#undef LINE_DEBUG_STR +#undef PT_DEBUG_STR +#undef T_DEBUG_STR +#undef CUBIC_DEBUG_DATA +#undef QUAD_DEBUG_DATA +#undef LINE_DEBUG_DATA +#undef PT_DEBUG_DATA + #else static void debugShowLineIntersection(int , const Work& , const Work& , const Intersections& ) { } @@ -5326,6 +5381,9 @@ static void debugShowCubicQuadIntersection(int , const Work& , const Work& , static void debugShowCubicIntersection(int , const Work& , const Work& , const Intersections& ) { } + +static void debugShowCubicIntersection(int , const Work& , const Intersections& ) { +} #endif static bool addIntersectTs(Contour* test, Contour* next) { @@ -5565,6 +5623,30 @@ static bool addIntersectTs(Contour* test, Contour* next) { return true; } +static void addSelfIntersectTs(Contour* test) { + Work wt; + wt.init(test); + do { + if (wt.segmentType() != Work::kCubic_Segment) { + continue; + } + Intersections ts; + int pts = CubicIntersect(wt.pts(), ts); + debugShowCubicIntersection(pts, wt, ts); + if (!pts) { + continue; + } + SkASSERT(pts == 1); + SkASSERT(ts.fT[0][0] >= 0 && ts.fT[0][0] <= 1); + SkASSERT(ts.fT[1][0] >= 0 && ts.fT[1][0] <= 1); + SkPoint point = ts.fPt[0].asSkPoint(); + int testTAt = wt.addT(ts.fT[0][0], wt, point); + int nextTAt = wt.addT(ts.fT[1][0], wt, point); + wt.addOtherT(testTAt, ts.fT[1][0], nextTAt); + wt.addOtherT(nextTAt, ts.fT[0][0], testTAt); + } while (wt.advance()); +} + // resolve any coincident pairs found while intersecting, and // see if coincidence is formed by clipping non-concident segments static void coincidenceCheck(SkTDArray<Contour*>& contourList, int total) { @@ -6324,6 +6406,9 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) { } void simplifyx(const SkPath& path, SkPath& result) { +#if DEBUG_SORT + gDebugSortCount = gDebugSortCountDefault; +#endif // returns 1 for evenodd, -1 for winding, regardless of inverse-ness result.reset(); result.setFillType(SkPath::kEvenOdd_FillType); @@ -6331,7 +6416,6 @@ void simplifyx(const SkPath& path, SkPath& result) { // turn path into list of segments SkTArray<Contour> contours; - // FIXME: add self-intersecting cubics' T values to segment EdgeBuilder builder(path, contours); builder.finish(); SkTDArray<Contour*> contourList; @@ -6345,6 +6429,9 @@ void simplifyx(const SkPath& path, SkPath& result) { do { Contour** nextPtr = currentPtr; Contour* current = *currentPtr++; + if (current->containsCubics()) { + addSelfIntersectTs(current); + } Contour* next; do { next = *nextPtr++; |