printf("[%d] line computed ends match order=%d\n", (int) index, order);
}
if (controlsInside) {
- if ( reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x
- || reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y
- || reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x
- || reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y) {
+ if ( (reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x)
+ || (reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y)
+ || (reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x)
+ || (reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y)) {
printf("[%d] line computed ends order=%d\n", (int) index, order);
}
} else {
// while a control point is outside of bounding box formed by end points, split
_Rect bounds = {DBL_MAX, DBL_MAX, -DBL_MAX, -DBL_MAX};
find_tight_bounds(cubic, bounds);
- if ( !approximately_equal(reduce[0].x, bounds.left) && !approximately_equal(reduce[0].x, bounds.right)
- || !approximately_equal(reduce[0].y, bounds.top) && !approximately_equal(reduce[0].y, bounds.bottom)
- || !approximately_equal(reduce[1].x, bounds.left) && !approximately_equal(reduce[1].x, bounds.right)
- || !approximately_equal(reduce[1].y, bounds.top) && !approximately_equal(reduce[1].y, bounds.bottom)) {
+ if ( (!approximately_equal(reduce[0].x, bounds.left) && !approximately_equal(reduce[0].x, bounds.right))
+ || (!approximately_equal(reduce[0].y, bounds.top) && !approximately_equal(reduce[0].y, bounds.bottom))
+ || (!approximately_equal(reduce[1].x, bounds.left) && !approximately_equal(reduce[1].x, bounds.right))
+ || (!approximately_equal(reduce[1].y, bounds.top) && !approximately_equal(reduce[1].y, bounds.bottom))) {
printf("[%d] line computed tight bounds order=%d\n", (int) index, order);
}
void add(const Bounds& toAdd) {
add(toAdd.fLeft, toAdd.fTop, toAdd.fRight, toAdd.fBottom);
}
-
+
bool isEmpty() {
return fLeft > fRight || fTop > fBottom
|| (fLeft == fRight && fTop == fBottom)
// return outerWinding * innerWinding > 0
// || ((outerWinding + innerWinding < 0) ^ ((outerWinding - innerWinding) < 0)))
static bool useInnerWinding(int outerWinding, int innerWinding) {
- SkASSERT(outerWinding != innerWinding);
+ // SkASSERT(outerWinding != innerWinding);
int absOut = abs(outerWinding);
int absIn = abs(innerWinding);
bool result = absOut == absIn ? outerWinding < 0 : absOut < absIn;
return result;
}
-static const bool gOpLookup[][2][2] = {
- // ==0 !=0
- // b a b a
- {{true , false}, {false, true }}, // a - b
- {{false, false}, {true , true }}, // a & b
- {{true , true }, {false, false}}, // a | b
- {{true , true }, {true , true }}, // a ^ b
+#define F (false) // discard the edge
+#define T (true) // keep the edge
+
+static const bool gActiveEdge[kShapeOp_Count][2][2][2][2] = {
+// miFrom=0 miFrom=1
+// miTo=0 miTo=1 miTo=0 miTo=1
+// suFrom=0 1 suFrom=0 1 suFrom=0 1 suFrom=0 1
+// suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1 suTo=0,1
+ {{{{F, F}, {F, F}}, {{T, F}, {T, F}}}, {{{T, T}, {F, F}}, {{F, T}, {T, F}}}}, // mi - su
+ {{{{F, F}, {F, F}}, {{F, T}, {F, T}}}, {{{F, F}, {T, T}}, {{F, T}, {T, F}}}}, // mi & su
+ {{{{F, T}, {T, F}}, {{T, T}, {F, F}}}, {{{T, F}, {T, F}}, {{F, F}, {F, F}}}}, // mi | su
+ {{{{F, T}, {T, F}}, {{T, F}, {F, T}}}, {{{T, F}, {F, T}}, {{F, T}, {T, F}}}}, // mi ^ su
};
-static bool isActiveOp(bool angleIsOp, int otherNonZero, ShapeOp op) {
- return gOpLookup[op][otherNonZero][angleIsOp];
-}
+#undef F
+#undef T
// wrap path to keep track of whether the contour is initialized and non-empty
class PathWrapper {
}
int maxWinding, sumWinding, oppMaxWinding, oppSumWinding;
return activeOp(xorMiMask, xorSuMask, index, endIndex, op, sumMiWinding, sumSuWinding,
- maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
+ maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
}
-
- bool activeOp(int xorMiMask, int xorSuMask,
- int index, int endIndex, ShapeOp op,
+
+ bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, ShapeOp op,
int& sumMiWinding, int& sumSuWinding,
int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWinding) {
setUpWindings(index, endIndex, sumMiWinding, sumSuWinding,
maxWinding, sumWinding, oppMaxWinding, oppSumWinding);
- int mask, oppMask;
+ bool miFrom;
+ bool miTo;
+ bool suFrom;
+ bool suTo;
if (operand()) {
- mask = xorSuMask;
- oppMask = xorMiMask;
+ miFrom = (oppMaxWinding & xorMiMask) != 0;
+ miTo = (oppSumWinding & xorMiMask) != 0;
+ suFrom = (maxWinding & xorSuMask) != 0;
+ suTo = (sumWinding & xorSuMask) != 0;
} else {
- mask = xorMiMask;
- oppMask = xorSuMask;
+ miFrom = (maxWinding & xorMiMask) != 0;
+ miTo = (sumWinding & xorMiMask) != 0;
+ suFrom = (oppMaxWinding & xorSuMask) != 0;
+ suTo = (oppSumWinding & xorSuMask) != 0;
}
- if ((sumWinding & mask) && (maxWinding & mask)) {
- return false;
- }
- int oppCoin = oppSign(index, endIndex) & oppMask;
- if (oppCoin) {
- bool oppCrossZero = !(oppSumWinding & oppMask) || !(oppMaxWinding & oppMask);
- bool outside = !(oppSumWinding & oppMask) ^ !(sumWinding & mask);
- switch (op) {
- case kIntersect_Op:
- return !oppCrossZero | !outside;
- case kUnion_Op:
- return oppCrossZero & !outside;
- case kDifference_Op:
- return oppCrossZero ? outside : operand();
- case kXor_Op:
- return !oppCrossZero;
- default:
- SkASSERT(0);
- }
-
- }
- bool oppNonZero = oppMaxWinding & oppMask;
- return isActiveOp(operand(), oppNonZero, op);
+ bool result = gActiveEdge[op][miFrom][miTo][suFrom][suTo];
+ SkASSERT(result != -1);
+ return result;
}
void addAngle(SkTDArray<Angle>& angles, int start, int end) const {
// iterate through T intersections and return topmost
// topmost tangent from y-min to first pt is closer to horizontal
SkASSERT(!done());
- int firstT;
- int lastT;
+ int firstT = -1;
SkPoint topPt;
topPt.fY = SK_ScalarMax;
int count = fTs.count();
if (topPt.fY > intercept.fY || (topPt.fY == intercept.fY
&& topPt.fX > intercept.fX)) {
topPt = intercept;
- firstT = lastT = index;
- } else if (topPt == intercept) {
- lastT = index;
+ firstT = index;
}
}
next:
lastDone = span.fDone;
lastUnsortable = span.fUnsortableEnd;
}
+ SkASSERT(firstT >= 0);
// sort the edges to find the leftmost
int step = 1;
int end = nextSpan(firstT, step);
}
}
}
-
+
void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd) {
fDoneSpans = 0;
fOperand = operand;
Span* markAndChaseWinding(const Angle* angle, const int winding) {
int index = angle->start();
int endIndex = angle->end();
- int step = SkSign32(endIndex - index);
+ int step = SkSign32(endIndex - index);
int min = SkMin32(index, endIndex);
markWinding(min, winding);
Span* last;
void markDoneBinary(int index, int winding, int oppWinding) {
// SkASSERT(!done());
- SkASSERT(winding);
+ SkASSERT(winding || oppWinding);
double referenceT = fTs[index].fT;
int lesser = index;
while (--lesser >= 0 && precisely_negative(referenceT - fTs[lesser].fT)) {
*outsideTs.append() = start;
}
}
-
+
void undoneSpan(int& start, int& end) {
size_t tCount = fTs.count();
size_t index;
int lesser = SkMin32(index, endIndex);
int winding = windSum(lesser);
int spanWinding = spanSign(index, endIndex);
- if (useInnerWinding(winding - spanWinding, winding)) {
+ if (winding && useInnerWinding(winding - spanWinding, winding)) {
winding -= spanWinding;
}
return winding;
}
#endif
-#if DEBUG_WINDING
- bool debugVerifyWinding(int start, int end, int winding) const {
- const Span& span = fTs[SkMin32(start, end)];
- int spanWinding = span.fWindSum;
- if (spanWinding == SK_MinS32) {
- return true;
- }
- int spanSign = SkSign32(start - end);
- int signedVal = spanSign * span.fWindValue;
- if (signedVal < 0) {
- spanWinding -= signedVal;
- }
- return span.fWindSum == winding;
- }
-#endif
-
private:
const SkPoint* fPts;
Bounds fBounds;
void setOperand(bool isOp) {
fOperand = isOp;
}
-
+
void setOppXor(bool isOppXor) {
fOppXor = isOppXor;
int segmentCount = fSegments.count();
#endif
}
#if DEBUG_WINDING
- // SkASSERT(current->debugVerifyWinding(index, endIndex, contourWinding));
SkDebugf("%s contourWinding=%d\n", __FUNCTION__, contourWinding);
#endif
}
first = false;
simple.deferredMove(startPtr[0]);
}
- const SkPoint* endPtr;
if (forward) {
contour.toPartialForward(simple);
- endPtr = &contour.end();
} else {
contour.toPartialBackward(simple);
- endPtr = &contour.start();
}
if (sIndex == eIndex) {
simple.close();