const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windingPtr, bool* sortablePtr) { // find first angle, initialize winding to computed fWindSum
SkOpSegment* segment = start->segment(); const SkOpAngle* angle = segment->spanToAngle(start, end); if (!angle) {
*windingPtr = SK_MinS32; return nullptr;
} bool computeWinding = false; const SkOpAngle* firstAngle = angle; bool loop = false; bool unorderable = false; int winding = SK_MinS32; do {
angle = angle->next(); if (!angle) { return nullptr;
}
unorderable |= angle->unorderable(); if ((computeWinding = unorderable || (angle == firstAngle && loop))) { break; // if we get here, there's no winding, loop is unorderable
}
loop |= angle == firstAngle;
segment = angle->segment();
winding = segment->windSum(angle);
} while (winding == SK_MinS32); // if the angle loop contains an unorderable span, the angle order may be useless // directly compute the winding in this case for each span if (computeWinding) {
firstAngle = angle;
winding = SK_MinS32; do {
SkOpSpanBase* startSpan = angle->start();
SkOpSpanBase* endSpan = angle->end();
SkOpSpan* lesser = startSpan->starter(endSpan); int testWinding = lesser->windSum(); if (testWinding == SK_MinS32) {
testWinding = lesser->computeWindSum();
} if (testWinding != SK_MinS32) {
segment = angle->segment();
winding = testWinding;
}
angle = angle->next();
} while (angle != firstAngle);
}
*sortablePtr = !unorderable;
*windingPtr = winding; return angle;
}
SkOpSpan* FindUndone(SkOpContourHead* contourHead) {
SkOpContour* contour = contourHead; do { if (contour->done()) { continue;
}
SkOpSpan* result = contour->undoneSpan(); if (result) { return result;
}
} while ((contour = contour->next())); return nullptr;
}
SkOpSegment* FindChase(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** startPtr,
SkOpSpanBase** endPtr) { while (!chase->empty()) {
SkOpSpanBase* span = chase->back();
chase->pop_back();
SkOpSegment* segment = span->segment();
*startPtr = span->ptT()->next()->span(); bool done = true;
*endPtr = nullptr; if (SkOpAngle* last = segment->activeAngle(*startPtr, startPtr, endPtr, &done)) {
*startPtr = last->start();
*endPtr = last->end(); #if TRY_ROTATE
*chase->insert(0) = span; #else
*chase->append() = span; #endif return last->segment();
} if (done) { continue;
} // find first angle, initialize winding to computed wind sum int winding; bool sortable; const SkOpAngle* angle = AngleWinding(*startPtr, *endPtr, &winding, &sortable); if (!angle) { return nullptr;
} if (winding == SK_MinS32) { continue;
} int sumWinding SK_INIT_TO_AVOID_WARNING; if (sortable) {
segment = angle->segment();
sumWinding = segment->updateWindingReverse(angle);
}
SkOpSegment* first = nullptr; const SkOpAngle* firstAngle = angle; while ((angle = angle->next()) != firstAngle) {
segment = angle->segment();
SkOpSpanBase* start = angle->start();
SkOpSpanBase* end = angle->end(); int maxWinding SK_INIT_TO_AVOID_WARNING; if (sortable) {
segment->setUpWinding(start, end, &maxWinding, &sumWinding);
} if (!segment->done(angle)) { if (!first && (sortable || start->starter(end)->windSum() != SK_MinS32)) {
first = segment;
*startPtr = start;
*endPtr = end;
} // OPTIMIZATION: should this also add to the chase? if (sortable) { // TODO: add error handling
SkAssertResult(segment->markAngle(maxWinding, sumWinding, angle, nullptr));
}
}
} if (first) { #if TRY_ROTATE
*chase->insert(0) = span; #else
*chase->append() = span; #endif return first;
}
} return nullptr;
}
bool SortContourList(SkOpContourHead** contourList, bool evenOdd, bool oppEvenOdd) {
SkTDArray<SkOpContour* > list;
SkOpContour* contour = *contourList; do { if (contour->count()) {
contour->setOppXor(contour->operand() ? evenOdd : oppEvenOdd);
*list.append() = contour;
}
} while ((contour = contour->next())); int count = list.size(); if (!count) { returnfalse;
} if (count > 1) {
SkTQSort<SkOpContour>(list.begin(), list.end());
}
contour = list[0];
SkOpContourHead* contourHead = static_cast<SkOpContourHead*>(contour);
contour->globalState()->setContourHead(contourHead);
*contourList = contourHead; for (int index = 1; index < count; ++index) {
SkOpContour* next = list[index];
contour->setNext(next);
contour = next;
}
contour->setNext(nullptr); returntrue;
}
staticvoid calc_angles(SkOpContourHead* contourList DEBUG_COIN_DECLARE_PARAMS()) {
DEBUG_STATIC_SET_PHASE(contourList);
SkOpContour* contour = contourList; do {
contour->calcAngles();
} while ((contour = contour->next()));
}
staticbool missing_coincidence(SkOpContourHead* contourList DEBUG_COIN_DECLARE_PARAMS()) {
DEBUG_STATIC_SET_PHASE(contourList);
SkOpContour* contour = contourList; bool result = false; do {
result |= contour->missingCoincidence();
} while ((contour = contour->next())); return result;
}
staticbool move_multiples(SkOpContourHead* contourList DEBUG_COIN_DECLARE_PARAMS()) {
DEBUG_STATIC_SET_PHASE(contourList);
SkOpContour* contour = contourList; do { if (!contour->moveMultiples()) { returnfalse;
}
} while ((contour = contour->next())); returntrue;
}
staticbool move_nearby(SkOpContourHead* contourList DEBUG_COIN_DECLARE_PARAMS()) {
DEBUG_STATIC_SET_PHASE(contourList);
SkOpContour* contour = contourList; do { if (!contour->moveNearby()) { returnfalse;
}
} while ((contour = contour->next())); returntrue;
}
staticbool sort_angles(SkOpContourHead* contourList) {
SkOpContour* contour = contourList; do { if (!contour->sortAngles()) { returnfalse;
}
} while ((contour = contour->next())); returntrue;
}
bool HandleCoincidence(SkOpContourHead* contourList, SkOpCoincidence* coincidence) {
SkOpGlobalState* globalState = contourList->globalState(); // match up points within the coincident runs if (!coincidence->addExpanded(DEBUG_PHASE_ONLY_PARAMS(kIntersecting))) { returnfalse;
} // combine t values when multiple intersections occur on some segments but not others if (!move_multiples(contourList DEBUG_PHASE_PARAMS(kWalking))) { returnfalse;
} // move t values and points together to eliminate small/tiny gaps if (!move_nearby(contourList DEBUG_COIN_PARAMS())) { returnfalse;
} // add coincidence formed by pairing on curve points and endpoints
coincidence->correctEnds(DEBUG_PHASE_ONLY_PARAMS(kIntersecting)); if (!coincidence->addEndMovedSpans(DEBUG_COIN_ONLY_PARAMS())) { returnfalse;
} constint SAFETY_COUNT = 3; int safetyHatch = SAFETY_COUNT; // look for coincidence present in A-B and A-C but missing in B-C do { bool added; if (!coincidence->addMissing(&added DEBUG_ITER_PARAMS(SAFETY_COUNT - safetyHatch))) { returnfalse;
} if (!added) { break;
} if (!--safetyHatch) {
SkASSERT(globalState->debugSkipAssert()); returnfalse;
}
move_nearby(contourList DEBUG_ITER_PARAMS(SAFETY_COUNT - safetyHatch - 1));
} while (true); // check to see if, loosely, coincident ranges may be expanded if (coincidence->expand(DEBUG_COIN_ONLY_PARAMS())) { bool added; if (!coincidence->addMissing(&added DEBUG_COIN_PARAMS())) { returnfalse;
} if (!coincidence->addExpanded(DEBUG_COIN_ONLY_PARAMS())) { returnfalse;
} if (!move_multiples(contourList DEBUG_COIN_PARAMS())) { returnfalse;
}
move_nearby(contourList DEBUG_COIN_PARAMS());
} // the expanded ranges may not align -- add the missing spans if (!coincidence->addExpanded(DEBUG_PHASE_ONLY_PARAMS(kWalking))) { returnfalse;
} // mark spans of coincident segments as coincident
coincidence->mark(DEBUG_COIN_ONLY_PARAMS()); // look for coincidence lines and curves undetected by intersection if (missing_coincidence(contourList DEBUG_COIN_PARAMS())) {
(void) coincidence->expand(DEBUG_PHASE_ONLY_PARAMS(kIntersecting)); if (!coincidence->addExpanded(DEBUG_COIN_ONLY_PARAMS())) { returnfalse;
} if (!coincidence->mark(DEBUG_PHASE_ONLY_PARAMS(kWalking))) { returnfalse;
}
} else {
(void) coincidence->expand(DEBUG_COIN_ONLY_PARAMS());
}
(void) coincidence->expand(DEBUG_COIN_ONLY_PARAMS());
SkOpCoincidence overlaps(globalState);
safetyHatch = SAFETY_COUNT; do {
SkOpCoincidence* pairs = overlaps.isEmpty() ? coincidence : &overlaps; // adjust the winding value to account for coincident edges if (!pairs->apply(DEBUG_ITER_ONLY_PARAMS(SAFETY_COUNT - safetyHatch))) { returnfalse;
} // For each coincident pair that overlaps another, when the receivers (the 1st of the pair) // are different, construct a new pair to resolve their mutual span if (!pairs->findOverlaps(&overlaps DEBUG_ITER_PARAMS(SAFETY_COUNT - safetyHatch))) { returnfalse;
} if (!--safetyHatch) {
SkASSERT(globalState->debugSkipAssert()); returnfalse;
}
} while (!overlaps.isEmpty());
calc_angles(contourList DEBUG_COIN_PARAMS()); if (!sort_angles(contourList)) { returnfalse;
} #if DEBUG_COINCIDENCE_VERBOSE
coincidence->debugShowCoincidence(); #endif #if DEBUG_COINCIDENCE
coincidence->debugValidate(); #endif
SkPathOpsDebug::ShowActiveSpans(contourList); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.