Exemplo n.º 1
0
int SkIntersections::insert(double one, double two, const SkDPoint& pt) {
    if (fIsCoincident[0] == 3 && between(fT[0][0], one, fT[0][1])) {
        // For now, don't allow a mix of coincident and non-coincident intersections
        return -1;
    }
    SkASSERT(fUsed <= 1 || fT[0][0] <= fT[0][1]);
    int index;
    for (index = 0; index < fUsed; ++index) {
        double oldOne = fT[0][index];
        double oldTwo = fT[1][index];
        if (one == oldOne && two == oldTwo) {
            return -1;
        }
        if (more_roughly_equal(oldOne, one) && more_roughly_equal(oldTwo, two)) {
            if ((precisely_zero(one) && !precisely_zero(oldOne))
                    || (precisely_equal(one, 1) && !precisely_equal(oldOne, 1))
                    || (precisely_zero(two) && !precisely_zero(oldTwo))
                    || (precisely_equal(two, 1) && !precisely_equal(oldTwo, 1))) {
                SkASSERT(one >= 0 && one <= 1);
                SkASSERT(two >= 0 && two <= 1);
                fT[0][index] = one;
                fT[1][index] = two;
                fPt[index] = pt;
            }
            return -1;
        }
    #if ONE_OFF_DEBUG
        if (pt.roughlyEqual(fPt[index])) {
            SkDebugf("%s t=%1.9g pts roughly equal\n", __FUNCTION__, one);
        }
    #endif
        if (fT[0][index] > one) {
            break;
        }
    }
    if (fUsed >= fMax) {
        SkASSERT(0);  // FIXME : this error, if it is to be handled at runtime in release, must
                      // be propagated all the way back down to the caller, and return failure.
        fUsed = 0;
        return 0;
    }
    int remaining = fUsed - index;
    if (remaining > 0) {
        memmove(&fPt[index + 1], &fPt[index], sizeof(fPt[0]) * remaining);
        memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
        memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
        int clearMask = ~((1 << index) - 1);
        fIsCoincident[0] += fIsCoincident[0] & clearMask;
        fIsCoincident[1] += fIsCoincident[1] & clearMask;
    }
    fPt[index] = pt;
    SkASSERT(one >= 0 && one <= 1);
    SkASSERT(two >= 0 && two <= 1);
    fT[0][index] = one;
    fT[1][index] = two;
    ++fUsed;
    return index;
}
Exemplo n.º 2
0
void SkOpSegment::debugValidate() const {
#if DEBUG_VALIDATE
    int count = fTs.count();
    SK_ALWAYSBREAK(count >= 2);
    SK_ALWAYSBREAK(fTs[0].fT == 0);
    SK_ALWAYSBREAK(fTs[count - 1].fT == 1);
    int done = 0;
    double t = -1;
    const SkOpSpan* last = NULL;
    bool tinyTFound = false;
    bool hasLoop = false;
    for (int i = 0; i < count; ++i) {
        const SkOpSpan& span = fTs[i];
        SK_ALWAYSBREAK(t <= span.fT);
        t = span.fT;
        int otherIndex = span.fOtherIndex;
        const SkOpSegment* other = span.fOther;
        SK_ALWAYSBREAK(other != this || fVerb == SkPath::kCubic_Verb);
        const SkOpSpan& otherSpan = other->fTs[otherIndex];
        SK_ALWAYSBREAK(otherSpan.fPt == span.fPt);
        SK_ALWAYSBREAK(otherSpan.fOtherT == t);
        SK_ALWAYSBREAK(&fTs[i] == &otherSpan.fOther->fTs[otherSpan.fOtherIndex]);
        done += span.fDone;
        if (last) {
            SK_ALWAYSBREAK(last->fT != span.fT || last->fOther != span.fOther);
            bool tsEqual = last->fT == span.fT;
            bool tsPreciselyEqual = precisely_equal(last->fT, span.fT);
            SK_ALWAYSBREAK(!tsEqual || tsPreciselyEqual);
            bool pointsEqual = last->fPt == span.fPt;
            bool pointsNearlyEqual = AlmostEqualUlps(last->fPt, span.fPt);
#if 0  // bufferOverflow test triggers this
            SK_ALWAYSBREAK(!tsPreciselyEqual || pointsNearlyEqual);
#endif
//            SK_ALWAYSBREAK(!last->fTiny || !tsPreciselyEqual || span.fTiny || tinyTFound);
            SK_ALWAYSBREAK(last->fTiny || tsPreciselyEqual || !pointsEqual || hasLoop);
            SK_ALWAYSBREAK(!last->fTiny || pointsEqual);
            SK_ALWAYSBREAK(!last->fTiny || last->fDone);
            SK_ALWAYSBREAK(!last->fSmall || pointsNearlyEqual);
            SK_ALWAYSBREAK(!last->fSmall || last->fDone);
//            SK_ALWAYSBREAK(!last->fSmall || last->fTiny);
//            SK_ALWAYSBREAK(last->fTiny || !pointsEqual || last->fDone == span.fDone);
            if (last->fTiny) {
                tinyTFound |= !tsPreciselyEqual;
            } else {
                tinyTFound = false;
            }
        }
        last = &span;
        hasLoop |= last->fLoop;
    }
    SK_ALWAYSBREAK(done == fDoneSpans);
//    if (fAngles.count() ) {
//        fAngles.begin()->debugValidateLoop();
//    }
#endif
}
Exemplo n.º 3
0
int SkOpContour::alignT(bool swap, int tIndex, SkIntersections* ts) const {
    double tVal = (*ts)[swap][tIndex];
    if (tVal != 0 && precisely_zero(tVal)) {
        ts->set(swap, tIndex, 0);
        return 0;
    } 
     if (tVal != 1 && precisely_equal(tVal, 1)) {
        ts->set(swap, tIndex, 1);
        return 1;
    }
    return -1;
}
Exemplo n.º 4
0
void SkOpAngle::setSpans() {
    double startT = (*fSpans)[fStart].fT;
    double endT = (*fSpans)[fEnd].fT;
    switch (fVerb) {
    case SkPath::kLine_Verb: {
        SkDLine l = SkDLine::SubDivide(fPts, startT, endT);
        // OPTIMIZATION: for pure line compares, we never need fTangent1.c
        fTangent1.lineEndPoints(l);
        fSide = 0;
        } break;
    case SkPath::kQuad_Verb: {
        SkDQuad& quad = *SkTCast<SkDQuad*>(&fCurvePart);
        quad = SkDQuad::SubDivide(fPts, startT, endT);
        fTangent1.quadEndPoints(quad, 0, 1);
        if (dx() == 0 && dy() == 0) {
            fTangent1.quadEndPoints(quad);
        }
        fSide = -fTangent1.pointDistance(fCurvePart[2]);  // not normalized -- compare sign only
        } break;
    case SkPath::kCubic_Verb: {
 //     int nextC = 2;
        fCurvePart = SkDCubic::SubDivide(fPts, startT, endT);
        fTangent1.cubicEndPoints(fCurvePart, 0, 1);
        if (dx() == 0 && dy() == 0) {
            fTangent1.cubicEndPoints(fCurvePart, 0, 2);
 //         nextC = 3;
            if (dx() == 0 && dy() == 0) {
                fTangent1.cubicEndPoints(fCurvePart, 0, 3);
            }
        }
 //     fSide = -fTangent1.pointDistance(fCurvePart[nextC]);  // compare sign only
 //     if (nextC == 2 && approximately_zero(fSide)) {
 //         fSide = -fTangent1.pointDistance(fCurvePart[3]);
 //     }
        double testTs[4];
        // OPTIMIZATION: keep inflections precomputed with cubic segment?
        int testCount = SkDCubic::FindInflections(fPts, testTs);
        double limitT = endT;
        int index;
        for (index = 0; index < testCount; ++index) {
            if (!between(startT, testTs[index], limitT)) {
                testTs[index] = -1;
            }
        }
        testTs[testCount++] = startT;
        testTs[testCount++] = endT;
        SkTQSort<double>(testTs, &testTs[testCount - 1]);
        double bestSide = 0;
        int testCases = (testCount << 1) - 1;
        index = 0;
        while (testTs[index] < 0) {
            ++index;
        }
        index <<= 1;
        for (; index < testCases; ++index) {
            int testIndex = index >> 1;
            double testT = testTs[testIndex];
            if (index & 1) {
                testT = (testT + testTs[testIndex + 1]) / 2;
            }
            // OPTIMIZE: could avoid call for t == startT, endT
            SkDPoint pt = dcubic_xy_at_t(fPts, testT);
            double testSide = fTangent1.pointDistance(pt);
            if (fabs(bestSide) < fabs(testSide)) {
                bestSide = testSide;
            }
        }
        fSide = -bestSide;  // compare sign only
        } break;
    default:
        SkASSERT(0);
    }
    fUnsortable = dx() == 0 && dy() == 0;
    if (fUnsortable) {
        return;
    }
    SkASSERT(fStart != fEnd);
    int step = fStart < fEnd ? 1 : -1;  // OPTIMIZE: worth fStart - fEnd >> 31 type macro?
    for (int index = fStart; index != fEnd; index += step) {
#if 1
        const SkOpSpan& thisSpan = (*fSpans)[index];
        const SkOpSpan& nextSpan = (*fSpans)[index + step];
        if (thisSpan.fTiny || precisely_equal(thisSpan.fT, nextSpan.fT)) {
            continue;
        }
        fUnsortable = step > 0 ? thisSpan.fUnsortableStart : nextSpan.fUnsortableEnd;
#if DEBUG_UNSORTABLE
        if (fUnsortable) {
            SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, thisSpan.fT);
            SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, nextSpan.fT);
            SkDebugf("%s unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
                    index, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
        }
#endif
        return;
#else
        if ((*fSpans)[index].fUnsortableStart) {
            fUnsortable = true;
            return;
        }
#endif
    }
#if 1
#if DEBUG_UNSORTABLE
    SkPoint iPt = (*CurvePointAtT[fVerb])(fPts, startT);
    SkPoint ePt = (*CurvePointAtT[fVerb])(fPts, endT);
    SkDebugf("%s all tiny unsortable [%d] (%1.9g,%1.9g) [%d] (%1.9g,%1.9g)\n", __FUNCTION__,
        fStart, iPt.fX, iPt.fY, fEnd, ePt.fX, ePt.fY);
#endif
    fUnsortable = true;
#endif
}