Beispiel #1
0
SkOpSegment* FindSortableTop(const SkTArray<SkOpContour*, true>& contourList,
                             SkOpAngle::IncludeType angleIncludeType, bool* firstContour, int* indexPtr,
                             int* endIndexPtr, SkPoint* topLeft, bool* unsortable, bool* done) {
    SkOpSegment* current = findSortableTop(contourList, indexPtr, endIndexPtr, topLeft, unsortable,
                                           done, true);
    if (!current) {
        return NULL;
    }
    const int index = *indexPtr;
    const int endIndex = *endIndexPtr;
    if (*firstContour) {
        current->initWinding(index, endIndex);
        *firstContour = false;
        return current;
    }
    int minIndex = SkMin32(index, endIndex);
    int sumWinding = current->windSum(minIndex);
    if (sumWinding != SK_MinS32) {
        return current;
    }
    SkASSERT(current->windSum(SkMin32(index, endIndex)) == SK_MinS32);
    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle, true> angles;
    SkSTArray<SkOpAngle::kStackBasedCount, SkOpAngle*, true> sorted;
    sumWinding = current->computeSum(index, endIndex, angleIncludeType, &angles, &sorted);
    if (sumWinding != SK_MinS32 && sumWinding != SK_NaN32) {
        return current;
    }
    int contourWinding;
    int oppContourWinding = 0;
    // the simple upward projection of the unresolved points hit unsortable angles
    // shoot rays at right angles to the segment to find its winding, ignoring angle cases
    bool tryAgain;
    double tHit;
    SkScalar hitDx = 0;
    SkScalar hitOppDx = 0;
    do {
        // if current is vertical, find another candidate which is not
        // if only remaining candidates are vertical, then they can be marked done
        SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
        skipVertical(contourList, &current, indexPtr, endIndexPtr);

        SkASSERT(*indexPtr != *endIndexPtr && *indexPtr >= 0 && *endIndexPtr >= 0);
        tryAgain = false;
        contourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
                                           &hitDx, &tryAgain, false);
        if (tryAgain) {
            continue;
        }
        if (angleIncludeType < SkOpAngle::kBinarySingle) {
            break;
        }
        oppContourWinding = rightAngleWinding(contourList, &current, indexPtr, endIndexPtr, &tHit,
                                              &hitOppDx, &tryAgain, true);
    } while (tryAgain);
    current->initWinding(*indexPtr, *endIndexPtr, tHit, contourWinding, hitDx, oppContourWinding,
                         hitOppDx);
    return current;
}
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;
}
Beispiel #3
0
static void bridgeOp(SkTDArray<Contour*>& contourList, const ShapeOp op,
        const int aXorMask, const int bXorMask, PathWrapper& simple) {
    bool firstContour = true;
    SkPoint topLeft = {SK_ScalarMin, SK_ScalarMin};
    do {

#if SORTABLE_CONTOURS // old way
        Segment* topStart = findTopContour(contourList);
        if (!topStart) {
            break;
        }
        // Start at the top. Above the top is outside, below is inside.
        // follow edges to intersection by changing the index by direction.
        int index, endIndex;
        Segment* current = topStart->findTop(index, endIndex);
#else // new way: iterate while top is unsortable
        int index, endIndex;
        Segment* current = findSortableTop(contourList, index, endIndex, topLeft);
        if (!current) {
            break;
        }
#endif
        int contourWinding;
        if (firstContour) {
            contourWinding = 0;
            firstContour = false;
        } else {
            int sumWinding = current->windSum(SkMin32(index, endIndex));
            // FIXME: don't I have to adjust windSum to get contourWinding?
            if (sumWinding == SK_MinS32) {
                sumWinding = current->computeSum(index, endIndex);
            }
            if (sumWinding == SK_MinS32) {
                contourWinding = innerContourCheck(contourList, current,
                        index, endIndex);
            } else {
                contourWinding = sumWinding;
                int spanWinding = current->spanSign(index, endIndex);
                bool inner = useInnerWinding(sumWinding - spanWinding, sumWinding);
                if (inner) {
                    contourWinding -= spanWinding;
                }
#if DEBUG_WINDING
                SkDebugf("%s sumWinding=%d spanWinding=%d sign=%d inner=%d result=%d\n", __FUNCTION__,
                        sumWinding, spanWinding, SkSign32(index - endIndex),
                        inner, contourWinding);
#endif
            }
#if DEBUG_WINDING
         //   SkASSERT(current->debugVerifyWinding(index, endIndex, contourWinding));
            SkDebugf("%s contourWinding=%d\n", __FUNCTION__, contourWinding);
#endif
        }
    //    SkPoint lastPt;
        int winding = contourWinding;
        int spanWinding = current->spanSign(index, endIndex);
        int oppWinding = current->oppSign(index, endIndex);
        bool active = windingIsActive(winding, spanWinding, oppWinding, op);
        SkTDArray<Span*> chaseArray;
        bool unsortable = false;
        do {
        #if DEBUG_WINDING
            SkDebugf("%s active=%s winding=%d spanWinding=%d\n",
                    __FUNCTION__, active ? "true" : "false",
                    winding, spanWinding);
        #endif
        //    const SkPoint* firstPt = NULL;
            do {
                SkASSERT(!current->done());
                int nextStart = index;
                int nextEnd = endIndex;
                Segment* next = current->findNextOp(chaseArray, active,
                        nextStart, nextEnd, winding, spanWinding, unsortable, op,
                        aXorMask, bXorMask);
                if (!next) {
                    // FIXME: if unsortable, allow partial paths to be later
                    // assembled
                    SkASSERT(!unsortable);
                    if (active && simple.hasMove()
                            && current->verb() != SkPath::kLine_Verb
                            && !simple.isClosed()) {
                       /* lastPt = */ current->addCurveTo(index, endIndex, simple, true);
                        SkASSERT(simple.isClosed());
                    }
                    break;
                }
         //       if (!firstPt) {
         //           firstPt = &current->addMoveTo(index, simple, active);
         //       }
                /* lastPt = */ current->addCurveTo(index, endIndex, simple, active);
                current = next;
                index = nextStart;
                endIndex = nextEnd;
            } while (!simple.isClosed() && (active || !current->done()));
            if (simple.hasMove() && active) {
        #if DEBUG_PATH_CONSTRUCTION
                SkDebugf("%s close\n", __FUNCTION__);
        #endif
                simple.close();
            }
            current = findChase(chaseArray, index, endIndex, contourWinding);
        #if DEBUG_ACTIVE_SPANS
            debugShowActiveSpans(contourList);
        #endif
            if (!current) {
                break;
            }
            int lesser = SkMin32(index, endIndex);
            spanWinding = current->spanSign(index, endIndex);
            winding = current->windSum(lesser);
            bool inner = useInnerWinding(winding - spanWinding, winding);
        #if DEBUG_WINDING
            SkDebugf("%s id=%d t=%1.9g spanWinding=%d winding=%d sign=%d"
                    " inner=%d result=%d\n",
                    __FUNCTION__, current->debugID(), current->t(lesser),
                    spanWinding, winding, SkSign32(index - endIndex),
                    useInnerWinding(winding - spanWinding, winding),
                    inner ? winding - spanWinding : winding);
        #endif
            if (inner) {
                winding -= spanWinding;
            }
            int oppWinding = current->oppSign(index, endIndex);
            active = windingIsActive(winding, spanWinding, oppWinding, op);
        } while (true);
    } while (true);
}