static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp op, const int xorMask, const int xorOpMask, SkPathWriter* simple) { bool firstContour = true; bool unsortable = false; bool topUnsortable = false; SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; do { int index, endIndex; bool done; SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySingle, &firstContour, &index, &endIndex, &topLeft, &topUnsortable, &done); if (!current) { if (topUnsortable || !done) { topUnsortable = false; SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin); topLeft.fX = topLeft.fY = SK_ScalarMin; continue; } break; } SkTDArray<SkOpSpan*> chaseArray; do { if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { do { if (!unsortable && current->done()) { #if DEBUG_ACTIVE_SPANS DebugShowActiveSpans(contourList); #endif if (simple->isEmpty()) { simple->init(); } break; } SkASSERT(unsortable || !current->done()); int nextStart = index; int nextEnd = endIndex; SkOpSegment* next = current->findNextOp(&chaseArray, &nextStart, &nextEnd, &unsortable, op, xorMask, xorOpMask); if (!next) { if (!unsortable && simple->hasMove() && current->verb() != SkPath::kLine_Verb && !simple->isClosed()) { current->addCurveTo(index, endIndex, simple, true); SkASSERT(simple->isClosed()); } break; } #if DEBUG_FLOW SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__, current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY, current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); #endif current->addCurveTo(index, endIndex, simple, true); current = next; index = nextStart; endIndex = nextEnd; } while (!simple->isClosed() && (!unsortable || !current->done(SkMin32(index, endIndex)))); if (current->activeWinding(index, endIndex) && !simple->isClosed()) { // FIXME : add to simplify, xor cpaths int min = SkMin32(index, endIndex); if (!unsortable && !simple->isEmpty()) { unsortable = current->checkSmall(min); } SkASSERT(unsortable || simple->isEmpty()); if (!current->done(min)) { current->addCurveTo(index, endIndex, simple, true); current->markDoneBinary(min); } } simple->close(); } else { SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex); if (last && !last->fLoop) { *chaseArray.append() = last; } } current = findChaseOp(chaseArray, index, endIndex); #if DEBUG_ACTIVE_SPANS DebugShowActiveSpans(contourList); #endif if (!current) { break; } } while (true); } while (true); return simple->someAssemblyRequired(); }
static bool bridgeOp(SkTArray<SkOpContour*, true>& contourList, const SkPathOp op, const int xorMask, const int xorOpMask, SkPathWriter* simple) { bool firstContour = true; bool unsortable = false; bool topUnsortable = false; bool firstPass = true; SkPoint lastTopLeft; SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin}; do { int index, endIndex; bool topDone; bool onlyVertical = false; lastTopLeft = topLeft; SkOpSegment* current = FindSortableTop(contourList, SkOpAngle::kBinarySingle, &firstContour, &index, &endIndex, &topLeft, &topUnsortable, &topDone, &onlyVertical, firstPass); if (!current) { if ((!topUnsortable || firstPass) && !topDone) { SkASSERT(topLeft.fX != SK_ScalarMin && topLeft.fY != SK_ScalarMin); if (lastTopLeft.fX == SK_ScalarMin && lastTopLeft.fY == SK_ScalarMin) { if (firstPass) { firstPass = false; } else { break; } } topLeft.fX = topLeft.fY = SK_ScalarMin; continue; } break; } else if (onlyVertical) { break; } firstPass = !topUnsortable || lastTopLeft != topLeft; SkTDArray<SkOpSpan*> chase; do { if (current->activeOp(index, endIndex, xorMask, xorOpMask, op)) { do { if (!unsortable && current->done()) { break; } SkASSERT(unsortable || !current->done()); int nextStart = index; int nextEnd = endIndex; SkOpSegment* next = current->findNextOp(&chase, &nextStart, &nextEnd, &unsortable, op, xorMask, xorOpMask); if (!next) { if (!unsortable && simple->hasMove() && current->verb() != SkPath::kLine_Verb && !simple->isClosed()) { current->addCurveTo(index, endIndex, simple, true); #if DEBUG_ACTIVE_SPANS if (!simple->isClosed()) { DebugShowActiveSpans(contourList); } #endif // SkASSERT(simple->isClosed()); } break; } #if DEBUG_FLOW SkDebugf("%s current id=%d from=(%1.9g,%1.9g) to=(%1.9g,%1.9g)\n", __FUNCTION__, current->debugID(), current->xyAtT(index).fX, current->xyAtT(index).fY, current->xyAtT(endIndex).fX, current->xyAtT(endIndex).fY); #endif current->addCurveTo(index, endIndex, simple, true); current = next; index = nextStart; endIndex = nextEnd; } while (!simple->isClosed() && (!unsortable || !current->done(SkMin32(index, endIndex)))); if (current->activeWinding(index, endIndex) && !simple->isClosed()) { // FIXME : add to simplify, xor cpaths int min = SkMin32(index, endIndex); if (!unsortable && !simple->isEmpty()) { unsortable = current->checkSmall(min); } if (!current->done(min)) { current->addCurveTo(index, endIndex, simple, true); current->markDoneBinary(min); } } simple->close(); } else { SkOpSpan* last = current->markAndChaseDoneBinary(index, endIndex); if (last && !last->fChased && !last->fLoop) { last->fChased = true; SkASSERT(!SkPathOpsDebug::ChaseContains(chase, last)); *chase.append() = last; #if DEBUG_WINDING SkDebugf("%s chase.append id=%d windSum=%d small=%d\n", __FUNCTION__, last->fOther->span(last->fOtherIndex).fOther->debugID(), last->fWindSum, last->fSmall); #endif } } current = findChaseOp(chase, &index, &endIndex); #if DEBUG_ACTIVE_SPANS DebugShowActiveSpans(contourList); #endif if (!current) { break; } } while (true); } while (true); return simple->someAssemblyRequired(); }