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; }
/* * Thread - Compose ArchReqs in the queue. */ void * Compose( void *arg) { QueueInit(&composeQ); ThreadsInitWait(wakeup, wakeup); while (AdState->AdExec < ES_term) { struct QueueEntry *qe; struct ArchReq *ar; struct ArchSet *as; /* * Wait for entries in the queue. */ ThreadsReconfigSync(RC_allow); PthreadMutexLock(&composeWaitMutex); while (AdState->AdExec < ES_term && composeQ.QuHead.QeFwd == &composeQ.QuHead) { PthreadCondWait(&composeWait, &composeWaitMutex); } if (AdState->AdExec >= ES_term) { PthreadMutexUnlock(&composeWaitMutex); break; } ThreadsReconfigSync(RC_wait); /* * Remove and process next compose queue entry. */ qe = composeQ.QuHead.QeFwd; ar = qe->QeAr; arname = qe->QeArname; QueueRemove(qe); PthreadMutexUnlock(&composeWaitMutex); arFiList = NULL; if ((ar->ArStatus & (ARF_changed | ARF_merge | ARF_rmreq)) || (ar->ArFlags & AR_unqueue)) { ar->ArFlags &= AR_unqueue; MessageReturnQueueEntry(qe); continue; } if (!(ar->ArFlags & AR_first)) { /* * Remove processed files. */ pruneArchReq(ar); if (ar->ArFiles == 0) { MessageReturnQueueEntry(qe); continue; } ar->ArState = ARS_schedule; } ar->ArFlags &= AR_offline | AR_segment; as = FindArchSet(ar->ArAsname); if (as == NULL) { Trace(TR_MISC, "Invalid ArchReq %s", arname); MessageReturnQueueEntry(qe); continue; } if (as->AsFlags & AS_disk_archive) { ar->ArFlags |= AR_disk; } else if (as->AsFlags & AS_honeycomb) { ar->ArFlags |= AR_honeycomb; } ar->ArDrivesUsed = 0; ar->ArDivides = DM_none; ar->ArSelFiles = ar->ArFiles; ar->ArSelSpace = ar->ArSpace; /* * Process the compositions as required. */ if (ar->ArFlags & AR_offline) { /* * Check offline files for available stage volumes. */ checkOffline(ar); ar->ArDivides = DM_offline; } if (ar->ArFlags & AR_segment) { ar->ArDivides = DM_segment; sortSegments(ar); } if (as->AsJoin != JM_none) { ar = joinFiles(ar, as); qe->QeAr = ar; } if (as->AsSort != SM_none) { sortFiles(ar, as); } if (as->AsReserve & RM_owner) { ar->ArDivides = (as->AsReserve & RM_dir) ? DM_ownerDir : DM_ownerUidGid; } prepareArchReq(ar); ScheduleEnqueue(qe); } ThreadsExit(); /*NOTREACHED*/ return (arg); }