bool HandleCoincidence(SkTArray<SkOpContour*, true>* contourList, int total) { #if DEBUG_SHOW_WINDING SkOpContour::debugShowWindingValues(contourList); #endif CoincidenceCheck(contourList, total); #if DEBUG_SHOW_WINDING SkOpContour::debugShowWindingValues(contourList); #endif fixOtherTIndex(contourList); checkEnds(contourList); // check if connecting curve intersected at the same end bool hasM = checkMultiples(contourList); // check if intersections agree on t and point values SkTDArray<SkOpSegment::AlignedSpan> aligned; if (hasM) { alignMultiples(contourList, &aligned); // align pairs of identical points alignCoincidence(contourList, aligned); } checkDuplicates(contourList); // check if spans have the same number on the other end checkTiny(contourList); // if pair have the same end points, mark them as parallel checkSmall(contourList); // a pair of curves with a small span may turn into coincident lines joinCoincidence(contourList); // join curves that connect to a coincident pair sortSegments(contourList); if (!calcAngles(contourList)) { return false; } sortAngles(contourList); #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY DebugShowActiveSpans(*contourList); #endif return true; }
static const SimplifyFindNextTest::Segment* testCommon( int contourWinding, int spanWinding, int startIndex, int endIndex, SkTArray<SimplifyFindNextTest::Contour>& contours) { SkTDArray<SimplifyFindNextTest::Contour*> contourList; makeContourList(contours, contourList, false, false); addIntersectTs(contourList[0], contourList[0]); if (contours.count() > 1) { SkASSERT(contours.count() == 2); addIntersectTs(contourList[0], contourList[1]); addIntersectTs(contourList[1], contourList[1]); } fixOtherTIndex(contourList); SimplifyFindNextTest::Segment& segment = contours[0].debugSegments()[0]; SkPoint pts[2]; pts[0] = segment.xyAtT(&segment.span(endIndex)); int nextStart = startIndex; int nextEnd = endIndex; SkTDArray<SimplifyFindNextTest::Span*> chaseArray; bool unsortable = false; SimplifyFindNextTest::Segment* next = segment.findNextWinding(chaseArray, true, nextStart, nextEnd, contourWinding, spanWinding, unsortable); pts[1] = next->xyAtT(&next->span(nextStart)); SkASSERT(pts[0] == pts[1]); return next; }
void operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result) { result.reset(); result.setFillType(SkPath::kEvenOdd_FillType); // turn path into list of segments SkTArray<Op::Contour> contours; // FIXME: add self-intersecting cubics' T values to segment Op::EdgeBuilder builder(one, contours); const int aXorMask = builder.xorMask(); builder.addOperand(two); const int bXorMask = builder.xorMask(); builder.finish(); SkTDArray<Op::Contour*> contourList; makeContourList(contours, contourList); Op::Contour** currentPtr = contourList.begin(); if (!currentPtr) { return; } Op::Contour** listEnd = contourList.end(); // find all intersections between segments do { Op::Contour** nextPtr = currentPtr; Op::Contour* current = *currentPtr++; Op::Contour* next; do { next = *nextPtr++; } while (addIntersectTs(current, next) && nextPtr != listEnd); } while (currentPtr != listEnd); // eat through coincident edges coincidenceCheck(contourList); fixOtherTIndex(contourList); // construct closed contours Op::PathWrapper wrapper(result); bridgeOp(contourList, op, aXorMask, bXorMask, wrapper); }
static const SimplifyFindTopTest::Segment* testCommon( SkTArray<SimplifyFindTopTest::Contour>& contours, int& index, int& end) { SkTDArray<SimplifyFindTopTest::Contour*> contourList; makeContourList(contours, contourList, false, false); addIntersectTs(contourList[0], contourList[0]); if (contours.count() > 1) { SkASSERT(contours.count() == 2); addIntersectTs(contourList[0], contourList[1]); addIntersectTs(contourList[1], contourList[1]); } fixOtherTIndex(contourList); #if SORTABLE_CONTOURS // old way SimplifyFindTopTest::Segment* topStart = findTopContour(contourList); const SimplifyFindTopTest::Segment* topSegment = topStart->findTop(index, end); #else SkPoint bestXY = {SK_ScalarMin, SK_ScalarMin}; bool done, unsortable = false; const SimplifyFindTopTest::Segment* topSegment = findSortableTop(contourList, index, end, bestXY, unsortable, done, true); #endif return topSegment; }