shape ops work in progress
git-svn-id: http://skia.googlecode.com/svn/trunk@7738 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
index f799699..ed7c62e 100644
--- a/experimental/Intersection/Simplify.cpp
+++ b/experimental/Intersection/Simplify.cpp
@@ -31,6 +31,7 @@
#define APPROXIMATE_CUBICS 1
#define DEBUG_UNUSED 0 // set to expose unused functions
+
#define FORCE_RELEASE 1 // set force release to 1 for multiple thread -- no debugging
#if FORCE_RELEASE || defined SK_RELEASE
@@ -109,7 +110,7 @@
Intersections& intersections) {
MAKE_CONST_LINE(aLine, a);
MAKE_CONST_LINE(bLine, b);
- return intersect(aLine, bLine, intersections.fT[0], intersections.fT[1]);
+ return intersect(aLine, bLine, intersections);
}
static int QuadLineIntersect(const SkPoint a[3], const SkPoint b[2],
@@ -136,7 +137,7 @@
#else
intersect(aQuad, bQuad, intersections);
#endif
- return intersections.fUsed ? intersections.fUsed : intersections.fCoincidentUsed;
+ return intersections.fUsed;
}
#if APPROXIMATE_CUBICS
@@ -152,11 +153,11 @@
MAKE_CONST_CUBIC(aCubic, a);
MAKE_CONST_CUBIC(bCubic, b);
#if APPROXIMATE_CUBICS
- intersect2(aCubic, bCubic, intersections);
+ intersect3(aCubic, bCubic, intersections);
#else
intersect(aCubic, bCubic, intersections);
#endif
- return intersections.fUsed ? intersections.fUsed : intersections.fCoincidentUsed;
+ return intersections.fUsed;
}
static int HLineIntersect(const SkPoint a[2], SkScalar left, SkScalar right,
@@ -366,6 +367,31 @@
CubicDYAtT
};
+static SkPoint LineDXDYAtT(const SkPoint a[2], double ) {
+ return a[1] - a[0];
+}
+
+static SkPoint QuadDXDYAtT(const SkPoint a[3], double t) {
+ MAKE_CONST_QUAD(quad, a);
+ _Point pt;
+ dxdy_at_t(quad, t, pt);
+ return pt.asSkPoint();
+}
+
+static SkPoint CubicDXDYAtT(const SkPoint a[4], double t) {
+ MAKE_CONST_CUBIC(cubic, a);
+ _Point pt;
+ dxdy_at_t(cubic, t, pt);
+ return pt.asSkPoint();
+}
+
+static SkPoint (* const SegmentDXDYAtT[])(const SkPoint [], double ) = {
+ NULL,
+ LineDXDYAtT,
+ QuadDXDYAtT,
+ CubicDXDYAtT
+};
+
static void LineSubDivide(const SkPoint a[2], double startT, double endT,
SkPoint sub[2]) {
MAKE_CONST_LINE(aLine, a);
@@ -428,6 +454,25 @@
sub_divide(aCubic, startT, endT, dst);
}
+static SkPoint QuadTop(const SkPoint a[3], double startT, double endT) {
+ MAKE_CONST_QUAD(quad, a);
+ _Point topPt = top(quad, startT, endT);
+ return topPt.asSkPoint();
+}
+
+static SkPoint CubicTop(const SkPoint a[3], double startT, double endT) {
+ MAKE_CONST_CUBIC(cubic, a);
+ _Point topPt = top(cubic, startT, endT);
+ return topPt.asSkPoint();
+}
+
+static SkPoint (* SegmentTop[])(const SkPoint[], double , double ) = {
+ NULL,
+ NULL,
+ QuadTop,
+ CubicTop
+};
+
#if DEBUG_UNUSED
static void QuadSubBounds(const SkPoint a[3], double startT, double endT,
SkRect& bounds) {
@@ -819,7 +864,7 @@
nextC = 3;
#if 1 // FIXME: try enabling this and see if a) it's called and b) does it break anything
if (dx() == 0 && dy() == 0) {
- SkDebugf("*** %s cubic is line\n");
+ SkDebugf("*** %s cubic is line\n", __FUNCTION__);
fTangent1.cubicEndPoints(fCurvePart, 0, 3);
}
#endif
@@ -1261,31 +1306,50 @@
return false;
}
- void activeLeftTop(SkPoint& result) const {
+ SkPoint activeLeftTop(bool onlySortable, int* firstT) const {
SkASSERT(!done());
+ SkPoint topPt = {SK_ScalarMax, SK_ScalarMax};
int count = fTs.count();
- result.fX = result.fY = SK_ScalarMax;
+ // see if either end is not done since we want smaller Y of the pair
bool lastDone = true;
bool lastUnsortable = false;
+ double lastT = -1;
for (int index = 0; index < count; ++index) {
const Span& span = fTs[index];
- if (span.fUnsortableStart | lastUnsortable) {
+ if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
goto next;
}
- if (!span.fDone | !lastDone) {
- const SkPoint& xy = xyAtT(index);
- if (result.fY < xy.fY) {
- goto next;
+ if (span.fDone && lastDone) {
+ goto next;
+ }
+ if (approximately_negative(span.fT - lastT)) {
+ goto next;
+ }
+ {
+ const SkPoint& xy = xyAtT(&span);
+ if (topPt.fY > xy.fY || (topPt.fY == xy.fY && topPt.fX > xy.fX)) {
+ topPt = xy;
+ if (firstT) {
+ *firstT = index;
+ }
}
- if (result.fY == xy.fY && result.fX < xy.fX) {
- goto next;
+ if (fVerb != SkPath::kLine_Verb && !lastDone) {
+ SkPoint curveTop = (*SegmentTop[fVerb])(fPts, lastT, span.fT);
+ if (topPt.fY > curveTop.fY || (topPt.fY == curveTop.fY
+ && topPt.fX > curveTop.fX)) {
+ topPt = curveTop;
+ if (firstT) {
+ *firstT = index;
+ }
+ }
}
- result = xy;
+ lastT = span.fT;
}
next:
lastDone = span.fDone;
lastUnsortable = span.fUnsortableEnd;
}
+ return topPt;
}
bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, ShapeOp op) {
@@ -1397,7 +1461,8 @@
fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
xyAtT(tIndexStart).fY);
#endif
- addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT, false);
+ addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT, false,
+ fTs[tIndexStart].fPt);
}
if (nextT < 1 && fTs[tIndex].fWindValue) {
#if DEBUG_CONCIDENT
@@ -1406,7 +1471,7 @@
fTs[tIndex].fT, xyAtT(tIndex).fX,
xyAtT(tIndex).fY);
#endif
- addTPair(fTs[tIndex].fT, other, other.fTs[oIndexStart].fT, false);
+ addTPair(fTs[tIndex].fT, other, other.fTs[oIndexStart].fT, false, fTs[tIndex].fPt);
}
} else {
SkASSERT(!other.fTs[oIndexStart].fWindValue);
@@ -1443,11 +1508,12 @@
do {
++tIndex;
} while (!approximately_negative(tStart - fTs[tIndex].fT));
+ SkPoint ptStart = fTs[tIndex].fPt;
do {
++oIndex;
} while (!approximately_negative(oStart - other.fTs[oIndex].fT));
if (tIndex > 0 || oIndex > 0 || fOperand != other.fOperand) {
- addTPair(tStart, other, oStart, false);
+ addTPair(tStart, other, oStart, false, ptStart);
}
tStart = fTs[tIndex].fT;
oStart = other.fTs[oIndex].fT;
@@ -1457,6 +1523,7 @@
nextT = fTs[++tIndex].fT;
} while (approximately_negative(nextT - tStart));
tStart = nextT;
+ ptStart = fTs[tIndex].fPt;
do {
nextT = other.fTs[++oIndex].fT;
} while (approximately_negative(nextT - oStart));
@@ -1464,7 +1531,7 @@
if (tStart == 1 && oStart == 1 && fOperand == other.fOperand) {
break;
}
- addTPair(tStart, other, oStart, false);
+ addTPair(tStart, other, oStart, false, ptStart);
} while (tStart < 1 && oStart < 1 && !approximately_negative(oEnd - oStart));
}
@@ -1563,7 +1630,7 @@
// resolve overlapping ts when considering coincidence later
// add non-coincident intersection. Resulting edges are sorted in T.
- int addT(double newT, Segment* other) {
+ int addT(double newT, Segment* other, const SkPoint& pt) {
// FIXME: in the pathological case where there is a ton of intercepts,
// binary search?
int insertedAt = -1;
@@ -1597,7 +1664,7 @@
}
span->fT = newT;
span->fOther = other;
- span->fPt.fX = SK_ScalarNaN;
+ span->fPt = pt;
span->fWindSum = SK_MinS32;
span->fOppSum = SK_MinS32;
span->fWindValue = 1;
@@ -1733,8 +1800,8 @@
}
}
- int addUnsortableT(double newT, Segment* other, bool start) {
- int result = addT(newT, other);
+ int addUnsortableT(double newT, Segment* other, bool start, const SkPoint& pt) {
+ int result = addT(newT, other, pt);
Span* span = &fTs[result];
if (start) {
if (result > 0) {
@@ -1838,7 +1905,7 @@
// FIXME: this doesn't prevent the same span from being added twice
// fix in caller, SkASSERT here?
- void addTPair(double t, Segment& other, double otherT, bool borrowWind) {
+ void addTPair(double t, Segment& other, double otherT, bool borrowWind, const SkPoint& pt) {
int tCount = fTs.count();
for (int tIndex = 0; tIndex < tCount; ++tIndex) {
const Span& span = fTs[tIndex];
@@ -1858,8 +1925,8 @@
SkDebugf("%s addTPair this=%d %1.9g other=%d %1.9g\n",
__FUNCTION__, fID, t, other.fID, otherT);
#endif
- int insertedAt = addT(t, &other);
- int otherInsertedAt = other.addT(otherT, this);
+ int insertedAt = addT(t, &other, pt);
+ int otherInsertedAt = other.addT(otherT, this, pt);
addOtherT(insertedAt, otherT, otherInsertedAt);
other.addOtherT(otherInsertedAt, t, insertedAt);
matchWindingValue(insertedAt, t, borrowWind);
@@ -2188,6 +2255,14 @@
bool done(const Angle* angle) const {
return done(SkMin32(angle->start(), angle->end()));
}
+
+ SkPoint dxdy(int index) const {
+ return (*SegmentDXDYAtT[fVerb])(fPts, fTs[index].fT);
+ }
+
+ SkScalar dy(int index) const {
+ return (*SegmentDYAtT[fVerb])(fPts, fTs[index].fT);
+ }
bool equalPoints(int greaterTIndex, int lesserTIndex) {
SkASSERT(greaterTIndex >= lesserTIndex);
@@ -2696,8 +2771,7 @@
}
}
- // start here;
- // either:
+ // FIXME: either:
// a) mark spans with either end unsortable as done, or
// b) rewrite findTop / findTopSegment / findTopContour to iterate further
// when encountering an unsortable span
@@ -2710,29 +2784,7 @@
// topmost tangent from y-min to first pt is closer to horizontal
SkASSERT(!done());
int firstT = -1;
- SkPoint topPt;
- topPt.fY = SK_ScalarMax;
- int count = fTs.count();
- // see if either end is not done since we want smaller Y of the pair
- bool lastDone = true;
- bool lastUnsortable = false;
- for (int index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (onlySortable && (span.fUnsortableStart || lastUnsortable)) {
- goto next;
- }
- if (!span.fDone | !lastDone) {
- const SkPoint& intercept = xyAtT(&span);
- if (topPt.fY > intercept.fY || (topPt.fY == intercept.fY
- && topPt.fX > intercept.fX)) {
- topPt = intercept;
- firstT = index;
- }
- }
- next:
- lastDone = span.fDone;
- lastUnsortable = span.fUnsortableEnd;
- }
+ SkPoint topPt = activeLeftTop(onlySortable, &firstT);
SkASSERT(firstT >= 0);
// sort the edges to find the leftmost
int step = 1;
@@ -2767,6 +2819,13 @@
tIndex = angle->end();
endIndex = angle->start();
} while (leftSegment->fTs[SkMin32(tIndex, endIndex)].fDone);
+ if (leftSegment->verb() >= SkPath::kQuad_Verb) {
+ SkScalar dyE = leftSegment->dy(endIndex);
+ SkScalar dyS = leftSegment->dy(tIndex);
+ if (dyE < 0 && dyS > 0) {
+ SkTSwap(tIndex, endIndex);
+ }
+ }
SkASSERT(!leftSegment->fTs[SkMin32(tIndex, endIndex)].fTiny);
return leftSegment;
}
@@ -4152,6 +4211,7 @@
Contour* fContours[2];
int fSegments[2];
double fTs[2][2];
+ SkPoint fPts[2];
};
class Contour {
@@ -4176,20 +4236,12 @@
coincidence.fContours[1] = other;
coincidence.fSegments[0] = index;
coincidence.fSegments[1] = otherIndex;
- if (fSegments[index].verb() == SkPath::kLine_Verb &&
- other->fSegments[otherIndex].verb() == SkPath::kLine_Verb) {
- // FIXME: coincident lines use legacy Ts instead of coincident Ts
- coincidence.fTs[swap][0] = ts.fT[0][0];
- coincidence.fTs[swap][1] = ts.fT[0][1];
- coincidence.fTs[!swap][0] = ts.fT[1][0];
- coincidence.fTs[!swap][1] = ts.fT[1][1];
- } else if (fSegments[index].verb() >= SkPath::kQuad_Verb &&
- other->fSegments[otherIndex].verb() >= SkPath::kQuad_Verb) {
- coincidence.fTs[swap][0] = ts.fCoincidentT[0][0];
- coincidence.fTs[swap][1] = ts.fCoincidentT[0][1];
- coincidence.fTs[!swap][0] = ts.fCoincidentT[1][0];
- coincidence.fTs[!swap][1] = ts.fCoincidentT[1][1];
- }
+ coincidence.fTs[swap][0] = ts.fT[0][0];
+ coincidence.fTs[swap][1] = ts.fT[0][1];
+ coincidence.fTs[!swap][0] = ts.fT[1][0];
+ coincidence.fTs[!swap][1] = ts.fT[1][1];
+ coincidence.fPts[0] = ts.fPt[0].asSkPoint();
+ coincidence.fPts[1] = ts.fPt[1].asSkPoint();
}
void addCross(const Contour* crosser) {
@@ -4221,13 +4273,14 @@
return fSegments.count();
}
- int addT(int segIndex, double newT, Contour* other, int otherIndex) {
+ int addT(int segIndex, double newT, Contour* other, int otherIndex, const SkPoint& pt) {
containsIntercepts();
- return fSegments[segIndex].addT(newT, &other->fSegments[otherIndex]);
+ return fSegments[segIndex].addT(newT, &other->fSegments[otherIndex], pt);
}
- int addUnsortableT(int segIndex, double newT, Contour* other, int otherIndex, bool start) {
- return fSegments[segIndex].addUnsortableT(newT, &other->fSegments[otherIndex], start);
+ int addUnsortableT(int segIndex, double newT, Contour* other, int otherIndex, bool start,
+ const SkPoint& pt) {
+ return fSegments[segIndex].addUnsortableT(newT, &other->fSegments[otherIndex], start, pt);
}
const Bounds& bounds() const {
@@ -4340,11 +4393,11 @@
// make sure startT and endT have t entries
if (startT > 0 || oEndT < 1
|| thisOne.isMissing(startT) || other.isMissing(oEndT)) {
- thisOne.addTPair(startT, other, oEndT, true);
+ thisOne.addTPair(startT, other, oEndT, true, coincidence.fPts[0]);
}
if (oStartT > 0 || endT < 1
|| thisOne.isMissing(endT) || other.isMissing(oStartT)) {
- other.addTPair(oStartT, thisOne, endT, true);
+ other.addTPair(oStartT, thisOne, endT, true, coincidence.fPts[1]);
}
if (!thisOne.done() && !other.done()) {
thisOne.addTCancel(startT, endT, other, oStartT, oEndT);
@@ -4352,11 +4405,11 @@
} else {
if (startT > 0 || oStartT > 0
|| thisOne.isMissing(startT) || other.isMissing(oStartT)) {
- thisOne.addTPair(startT, other, oStartT, true);
+ thisOne.addTPair(startT, other, oStartT, true, coincidence.fPts[0]);
}
if (endT < 1 || oEndT < 1
|| thisOne.isMissing(endT) || other.isMissing(oEndT)) {
- other.addTPair(oEndT, thisOne, endT, true);
+ other.addTPair(oEndT, thisOne, endT, true, coincidence.fPts[1]);
}
if (!thisOne.done() && !other.done()) {
thisOne.addTCoincident(startT, endT, other, oStartT, oEndT);
@@ -4411,20 +4464,20 @@
// make sure startT and endT have t entries
if (startT > 0 || oEndT < 1
|| thisOne.isMissing(startT) || other.isMissing(oEndT)) {
- thisOne.addTPair(startT, other, oEndT, true);
+ thisOne.addTPair(startT, other, oEndT, true, coincidence.fPts[0]);
}
if (oStartT > 0 || endT < 1
|| thisOne.isMissing(endT) || other.isMissing(oStartT)) {
- other.addTPair(oStartT, thisOne, endT, true);
+ other.addTPair(oStartT, thisOne, endT, true, coincidence.fPts[1]);
}
} else {
if (startT > 0 || oStartT > 0
|| thisOne.isMissing(startT) || other.isMissing(oStartT)) {
- thisOne.addTPair(startT, other, oStartT, true);
+ thisOne.addTPair(startT, other, oStartT, true, coincidence.fPts[0]);
}
if (endT < 1 || oEndT < 1
|| thisOne.isMissing(endT) || other.isMissing(oEndT)) {
- other.addTPair(oEndT, thisOne, endT, true);
+ other.addTPair(oEndT, thisOne, endT, true, coincidence.fPts[1]);
}
}
#if DEBUG_CONCIDENT
@@ -4554,8 +4607,7 @@
continue;
}
fDone = false;
- SkPoint testXY;
- testSegment->activeLeftTop(testXY);
+ SkPoint testXY = testSegment->activeLeftTop(true, NULL);
if (topStart) {
if (testXY.fY < topLeft.fY) {
continue;
@@ -4908,12 +4960,12 @@
// be nearly equal, any problems caused by this should be taken care
// of later.
// On the edge or out of range values are negative; add 2 to get end
- int addT(double newT, const Work& other) {
- return fContour->addT(fIndex, newT, other.fContour, other.fIndex);
+ int addT(double newT, const Work& other, const SkPoint& pt) {
+ return fContour->addT(fIndex, newT, other.fContour, other.fIndex, pt);
}
- int addUnsortableT(double newT, const Work& other, bool start) {
- return fContour->addUnsortableT(fIndex, newT, other.fContour, other.fIndex, start);
+ int addUnsortableT(double newT, const Work& other, bool start, const SkPoint& pt) {
+ return fContour->addUnsortableT(fIndex, newT, other.fContour, other.fIndex, start, pt);
}
bool advance() {
@@ -5031,9 +5083,9 @@
};
#if DEBUG_ADD_INTERSECTING_TS
-static void debugShowLineIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
- return;
+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,
@@ -5041,27 +5093,24 @@
wn.pts()[1].fX, wn.pts()[1].fY);
return;
}
- SkPoint wtOutPt, wnOutPt;
- LineXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
__FUNCTION__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
- wt.pts()[1].fX, wt.pts()[1].fY, wtOutPt.fX, wtOutPt.fY);
+ 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);
if (pts == 2) {
- SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
+ SkDebugf(" wtTs[1]=%1.9g (%1.9g,%1.9g)", i.fT[0][1], i.fPt[1].x, i.fPt[1].y);
}
- SkDebugf(" wnTs[0]=%g (%1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
- wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
- wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
+ 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);
if (pts == 2) {
- SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
+ SkDebugf(" wnTs[1]=%1.9g", i.fT[1][1]);
}
SkDebugf("\n");
}
static void debugShowQuadLineIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
+ 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",
@@ -5070,31 +5119,25 @@
wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY);
return;
}
- SkPoint wtOutPt, wnOutPt;
- QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
- SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
- __FUNCTION__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
+ 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,
- wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- QuadXYAtT(wt.pts(), wtTs[1], &wtOutPt);
- SkDebugf(" wtTs[1]=%1.9g (%1.9g,%1.9g)", wtTs[1], wtOutPt.fX, wtOutPt.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)",
- wnTs[0], wn.pts()[0].fX, wn.pts()[0].fY,
- wn.pts()[1].fX, wn.pts()[1].fY, wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- LineXYAtT(wn.pts(), wnTs[1], &wnOutPt);
- SkDebugf(" wnTs[1]=%1.9g (%1.9g,%1.9g)", wnTs[1], wnOutPt.fX, wnOutPt.fY);
+ 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("\n");
}
-// FIXME: show more than two intersection points
static void debugShowQuadIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
+ 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",
@@ -5104,29 +5147,26 @@
wn.pts()[2].fX, wn.pts()[2].fY );
return;
}
- SkPoint wtOutPt, wnOutPt;
- QuadXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- QuadXYAtT(wn.pts(), wnTs[0], &wnOutPt);
- SkDebugf("%s wtTs[0]=%1.9g (%1.9g,%1.9g %1.9g,%1.9g %1.9g,%1.9g) (%1.9g,%1.9g)",
- __FUNCTION__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY,
+ 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,
- wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
+ 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)",
- wnTs[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,
- wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
+ 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("\n");
}
static void debugShowCubicLineIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
+ 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",
@@ -5135,31 +5175,27 @@
wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY);
return;
}
- SkPoint wtOutPt, wnOutPt;
- CubicXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- LineXYAtT(wn.pts(), wnTs[0], &wnOutPt);
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__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY,
+ 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,
- wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- CubicXYAtT(wt.pts(), wtTs[1], &wtOutPt);
- SkDebugf(" wtTs[1]=%1.9g (%1.9g,%1.9g)", wtTs[1], wtOutPt.fX, wtOutPt.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)",
- wtTs[0], wn.pts()[0].fX, wn.pts()[0].fY, wn.pts()[1].fX, wn.pts()[1].fY,
- wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- LineXYAtT(wn.pts(), wnTs[1], &wnOutPt);
- SkDebugf(" wnTs[1]=%1.9g (%1.9g,%1.9g)", wnTs[1], wnOutPt.fX, wnOutPt.fY);
+ 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("\n");
}
// FIXME: show more than two intersection points
static void debugShowCubicQuadIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
+ 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",
@@ -5169,30 +5205,28 @@
wn.pts()[2].fX, wn.pts()[2].fY );
return;
}
- SkPoint wtOutPt, wnOutPt;
- CubicXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- QuadXYAtT(wn.pts(), wnTs[0], &wnOutPt);
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__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY,
+ 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,
- wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
+ 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)",
- wnTs[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,
- wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
+ 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("\n");
}
// FIXME: show more than two intersection points
static void debugShowCubicIntersection(int pts, const Work& wt,
- const Work& wn, const double wtTs[2], const double wnTs[2]) {
+ 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",
@@ -5202,50 +5236,43 @@
wn.pts()[2].fX, wn.pts()[2].fY, wn.pts()[3].fX, wn.pts()[3].fY );
return;
}
- SkPoint wtOutPt, wnOutPt;
- CubicXYAtT(wt.pts(), wtTs[0], &wtOutPt);
- CubicXYAtT(wn.pts(), wnTs[0], &wnOutPt);
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__,
- wtTs[0], wt.pts()[0].fX, wt.pts()[0].fY, wt.pts()[1].fX, wt.pts()[1].fY,
+ 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,
- wtOutPt.fX, wtOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wtTs[1]=%1.9g", wtTs[1]);
+ 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) (%1.9g,%1.9g)",
- wnTs[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,
- wnOutPt.fX, wnOutPt.fY);
- if (pts == 2) {
- SkDebugf(" wnTs[1]=%1.9g", wnTs[1]);
+ 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("\n");
}
#else
-static void debugShowLineIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowLineIntersection(int , const Work& , const Work& , const Intersections& ) {
}
-static void debugShowQuadLineIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowQuadLineIntersection(int , const Work& , const Work& , const Intersections& ) {
}
-static void debugShowQuadIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowQuadIntersection(int , const Work& , const Work& , const Intersections& ) {
}
-static void debugShowCubicLineIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowCubicLineIntersection(int , const Work& , const Work& ,
+ const Intersections& ) {
}
-static void debugShowCubicQuadIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowCubicQuadIntersection(int , const Work& , const Work& ,
+ const Intersections& ) {
}
-static void debugShowCubicIntersection(int , const Work& ,
- const Work& , const double [2], const double [2]) {
+static void debugShowCubicIntersection(int , const Work& , const Work& , const Intersections& ) {
}
#endif
@@ -5284,8 +5311,7 @@
case Work::kLine_Segment: {
pts = HLineIntersect(wn.pts(), wt.left(),
wt.right(), wt.y(), wt.xFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[1], ts.fT[0]);
+ debugShowLineIntersection(pts, wt, wn, ts);
break;
}
case Work::kQuad_Segment: {
@@ -5296,7 +5322,7 @@
case Work::kCubic_Segment: {
pts = HCubicIntersect(wn.pts(), wt.left(),
wt.right(), wt.y(), wt.xFlipped(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts.fT[0], ts.fT[1]);
+ debugShowCubicLineIntersection(pts, wn, wt, ts);
break;
}
default:
@@ -5311,8 +5337,7 @@
case Work::kLine_Segment: {
pts = VLineIntersect(wn.pts(), wt.top(),
wt.bottom(), wt.x(), wt.yFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[1], ts.fT[0]);
+ debugShowLineIntersection(pts, wt, wn, ts);
break;
}
case Work::kQuad_Segment: {
@@ -5323,7 +5348,7 @@
case Work::kCubic_Segment: {
pts = VCubicIntersect(wn.pts(), wt.top(),
wt.bottom(), wt.x(), wt.yFlipped(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts.fT[0], ts.fT[1]);
+ debugShowCubicLineIntersection(pts, wn, wt, ts);
break;
}
default:
@@ -5335,32 +5360,28 @@
case Work::kHorizontalLine_Segment:
pts = HLineIntersect(wt.pts(), wn.left(),
wn.right(), wn.y(), wn.xFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[1], ts.fT[0]);
+ debugShowLineIntersection(pts, wt, wn, ts);
break;
case Work::kVerticalLine_Segment:
pts = VLineIntersect(wt.pts(), wn.top(),
wn.bottom(), wn.x(), wn.yFlipped(), ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[1], ts.fT[0]);
+ debugShowLineIntersection(pts, wt, wn, ts);
break;
case Work::kLine_Segment: {
pts = LineIntersect(wt.pts(), wn.pts(), ts);
- debugShowLineIntersection(pts, wt, wn,
- ts.fT[1], ts.fT[0]);
+ debugShowLineIntersection(pts, wt, wn, ts);
break;
}
case Work::kQuad_Segment: {
swap = true;
pts = QuadLineIntersect(wn.pts(), wt.pts(), ts);
- debugShowQuadLineIntersection(pts, wn, wt,
- ts.fT[0], ts.fT[1]);
+ debugShowQuadLineIntersection(pts, wn, wt, ts);
break;
}
case Work::kCubic_Segment: {
swap = true;
pts = CubicLineIntersect(wn.pts(), wt.pts(), ts);
- debugShowCubicLineIntersection(pts, wn, wt, ts.fT[0], ts.fT[1]);
+ debugShowCubicLineIntersection(pts, wn, wt, ts);
break;
}
default:
@@ -5379,25 +5400,23 @@
break;
case Work::kLine_Segment: {
pts = QuadLineIntersect(wt.pts(), wn.pts(), ts);
- debugShowQuadLineIntersection(pts, wt, wn,
- ts.fT[0], ts.fT[1]);
+ debugShowQuadLineIntersection(pts, wt, wn, ts);
break;
}
case Work::kQuad_Segment: {
pts = QuadIntersect(wt.pts(), wn.pts(), ts);
- debugShowQuadIntersection(pts, wt, wn,
- ts.fT[0], ts.fT[1]);
+ debugShowQuadIntersection(pts, wt, wn, ts);
break;
}
case Work::kCubic_Segment: {
#if APPROXIMATE_CUBICS
swap = true;
pts = CubicQuadIntersect(wn.pts(), wt.pts(), ts);
- debugShowCubicQuadIntersection(pts, wn, wt, ts.fT[0], ts.fT[1]);
+ debugShowCubicQuadIntersection(pts, wn, wt, ts);
#else
wt.promoteToCubic();
pts = CubicIntersect(wt.cubic(), wn.pts(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicIntersection(pts, wt, wn, ts);
#endif
break;
}
@@ -5410,31 +5429,32 @@
case Work::kHorizontalLine_Segment:
pts = HCubicIntersect(wt.pts(), wn.left(),
wn.right(), wn.y(), wn.xFlipped(), ts);
+ debugShowCubicLineIntersection(pts, wt, wn, ts);
break;
case Work::kVerticalLine_Segment:
pts = VCubicIntersect(wt.pts(), wn.top(),
wn.bottom(), wn.x(), wn.yFlipped(), ts);
- debugShowCubicLineIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicLineIntersection(pts, wt, wn, ts);
break;
case Work::kLine_Segment: {
pts = CubicLineIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicLineIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicLineIntersection(pts, wt, wn, ts);
break;
}
case Work::kQuad_Segment: {
#if APPROXIMATE_CUBICS
pts = CubicQuadIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicQuadIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicQuadIntersection(pts, wt, wn, ts);
#else
wn.promoteToCubic();
pts = CubicIntersect(wt.pts(), wn.cubic(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicIntersection(pts, wt, wn, ts);
#endif
break;
}
case Work::kCubic_Segment: {
pts = CubicIntersect(wt.pts(), wn.pts(), ts);
- debugShowCubicIntersection(pts, wt, wn, ts.fT[0], ts.fT[1]);
+ debugShowCubicIntersection(pts, wt, wn, ts);
break;
}
default:
@@ -5455,9 +5475,10 @@
for (int pt = 0; pt < ts.used(); ++pt) {
// FIXME: if unsortable, the other points to the original. This logic is
// untested downstream.
- int testTAt = wt.addUnsortableT(ts.fT[swap][pt], wt, start);
+ SkPoint point = ts.fPt[pt].asSkPoint();
+ int testTAt = wt.addUnsortableT(ts.fT[swap][pt], wt, start, point);
wt.addOtherT(testTAt, ts.fT[swap][pt], testTAt);
- testTAt = wn.addUnsortableT(ts.fT[!swap][pt], wn, start ^ ts.fFlip);
+ testTAt = wn.addUnsortableT(ts.fT[!swap][pt], wn, start ^ ts.fFlip, point);
wn.addOtherT(testTAt, ts.fT[!swap][pt], testTAt);
start ^= true;
}
@@ -5471,7 +5492,8 @@
}
if (wn.segmentType() >= Work::kQuad_Segment
&& wt.segmentType() >= Work::kQuad_Segment
- && ts.coincidentUsed() == 2) {
+ && ts.fIsCoincident[0]) {
+ SkASSERT(ts.coincidentUsed() == 2);
wt.addCoincident(wn, ts, swap);
continue;
}
@@ -5480,8 +5502,9 @@
for (int pt = 0; pt < pts; ++pt) {
SkASSERT(ts.fT[0][pt] >= 0 && ts.fT[0][pt] <= 1);
SkASSERT(ts.fT[1][pt] >= 0 && ts.fT[1][pt] <= 1);
- int testTAt = wt.addT(ts.fT[swap][pt], wn);
- int nextTAt = wn.addT(ts.fT[!swap][pt], wt);
+ SkPoint point = ts.fPt[pt].asSkPoint();
+ int testTAt = wt.addT(ts.fT[swap][pt], wn, point);
+ int nextTAt = wn.addT(ts.fT[!swap][pt], wt, point);
wt.addOtherT(testTAt, ts.fT[!swap][pt ^ ts.fFlip], nextTAt);
wn.addOtherT(nextTAt, ts.fT[swap][pt ^ ts.fFlip], testTAt);
}