static void oneOff(skiatest::Reporter* reporter, const SkDCubic& cubic1, const SkDCubic& cubic2,
        bool coin) {
    SkASSERT(ValidCubic(cubic1));
    SkASSERT(ValidCubic(cubic2));
#if ONE_OFF_DEBUG
    SkDebugf("computed quadratics given\n");
    SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
        cubic1[0].fX, cubic1[0].fY, cubic1[1].fX, cubic1[1].fY,
        cubic1[2].fX, cubic1[2].fY, cubic1[3].fX, cubic1[3].fY);
    SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
        cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY,
        cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY);
#endif
    SkTArray<SkDQuad, true> quads1;
    CubicToQuads(cubic1, cubic1.calcPrecision(), quads1);
#if ONE_OFF_DEBUG
    SkDebugf("computed quadratics set 1\n");
    for (int index = 0; index < quads1.count(); ++index) {
        const SkDQuad& q = quads1[index];
        SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX, q[0].fY,
                 q[1].fX, q[1].fY,  q[2].fX, q[2].fY);
    }
#endif
    SkTArray<SkDQuad, true> quads2;
    CubicToQuads(cubic2, cubic2.calcPrecision(), quads2);
#if ONE_OFF_DEBUG
    SkDebugf("computed quadratics set 2\n");
    for (int index = 0; index < quads2.count(); ++index) {
        const SkDQuad& q = quads2[index];
        SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", q[0].fX, q[0].fY,
                 q[1].fX, q[1].fY,  q[2].fX, q[2].fY);
    }
#endif
    SkIntersections intersections;
    intersections.intersect(cubic1, cubic2);
    REPORTER_ASSERT(reporter, !coin || intersections.used() == 2);
    double tt1, tt2;
    SkDPoint xy1, xy2;
    for (int pt3 = 0; pt3 < intersections.used(); ++pt3) {
        tt1 = intersections[0][pt3];
        xy1 = cubic1.ptAtT(tt1);
        tt2 = intersections[1][pt3];
        xy2 = cubic2.ptAtT(tt2);
        const SkDPoint& iPt = intersections.pt(pt3);
#if ONE_OFF_DEBUG
        SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n",
                __FUNCTION__, tt1, xy1.fX, xy1.fY, iPt.fX,
                iPt.fY, xy2.fX, xy2.fY, tt2);
#endif
       REPORTER_ASSERT(reporter, xy1.approximatelyEqual(iPt));
       REPORTER_ASSERT(reporter, xy2.approximatelyEqual(iPt));
       REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
    }
    reporter->bumpTestCount();
}
static void oneOff(skiatest::Reporter* reporter, const CubicPts& cubic1, const CubicPts& cubic2,
        bool coin) {
    SkDCubic c1, c2;
    c1.debugSet(cubic1.fPts);
    c2.debugSet(cubic2.fPts);
    SkASSERT(ValidCubic(c1));
    SkASSERT(ValidCubic(c2));
#if ONE_OFF_DEBUG
    SkDebugf("computed quadratics given\n");
    SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
        cubic1[0].fX, cubic1[0].fY, cubic1[1].fX, cubic1[1].fY,
        cubic1[2].fX, cubic1[2].fY, cubic1[3].fX, cubic1[3].fY);
    SkDebugf("  {{%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}, {%1.9g,%1.9g}},\n",
        cubic2[0].fX, cubic2[0].fY, cubic2[1].fX, cubic2[1].fY,
        cubic2[2].fX, cubic2[2].fY, cubic2[3].fX, cubic2[3].fY);
#endif
    SkIntersections intersections;
    intersections.intersect(c1, c2);
#if DEBUG_T_SECT_DUMP == 3
    SkDebugf("</div>\n\n");
    SkDebugf("<script type=\"text/javascript\">\n\n");
    SkDebugf("var testDivs = [\n");
    for (int index = 1; index <= gDumpTSectNum; ++index) {
        SkDebugf("sect%d,\n", index);
    }
#endif
    if (coin && intersections.used() < 2) {
        SkDebugf("");
    }
    REPORTER_ASSERT(reporter, !coin || intersections.used() >= 2);
    double tt1, tt2;
    SkDPoint xy1, xy2;
    for (int pt3 = 0; pt3 < intersections.used(); ++pt3) {
        tt1 = intersections[0][pt3];
        xy1 = c1.ptAtT(tt1);
        tt2 = intersections[1][pt3];
        xy2 = c2.ptAtT(tt2);
        const SkDPoint& iPt = intersections.pt(pt3);
#if ONE_OFF_DEBUG
        SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n",
                __FUNCTION__, tt1, xy1.fX, xy1.fY, iPt.fX,
                iPt.fY, xy2.fX, xy2.fY, tt2);
#endif
       REPORTER_ASSERT(reporter, xy1.approximatelyEqual(iPt));
       REPORTER_ASSERT(reporter, xy2.approximatelyEqual(iPt));
       REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
    }
    reporter->bumpTestCount();
}
static void cubicQuadIntersection(skiatest::Reporter* reporter, int index) {
    int iIndex = static_cast<int>(index);
    const SkDCubic& cubic = quadCubicTests[index].cubic;
    SkASSERT(ValidCubic(cubic));
    const SkDQuad& quad = quadCubicTests[index].quad;
    SkASSERT(ValidQuad(quad));
    SkReduceOrder reduce1;
    SkReduceOrder reduce2;
    int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics);
    int order2 = reduce2.reduce(quad);
    if (order1 != 4) {
        SkDebugf("[%d] cubic order=%d\n", iIndex, order1);
        REPORTER_ASSERT(reporter, 0);
    }
    if (order2 != 3) {
        SkDebugf("[%d] quad order=%d\n", iIndex, order2);
        REPORTER_ASSERT(reporter, 0);
    }
    SkIntersections i;
    int roots = i.intersect(cubic, quad);
    for (int pt = 0; pt < roots; ++pt) {
        double tt1 = i[0][pt];
        SkDPoint xy1 = cubic.ptAtT(tt1);
        double tt2 = i[1][pt];
        SkDPoint xy2 = quad.ptAtT(tt2);
        if (!xy1.approximatelyEqual(xy2)) {
            SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
                __FUNCTION__, iIndex, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
        }
        REPORTER_ASSERT(reporter, xy1.approximatelyEqual(xy2));
    }
    reporter->bumpTestCount();
}
static void PathOpsDRectTest(skiatest::Reporter* reporter) {
    size_t index;
    SkDRect rect, rect2;
    for (index = 0; index < lineTests_count; ++index) {
        const SkDLine& line = lineTests[index];
        SkASSERT(ValidLine(line));
        rect.setBounds(line);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(line[0].fY, line[1].fY));
        rect2.set(line[0]);
        rect2.add(line[1]);
        REPORTER_ASSERT(reporter, rect2.fLeft == SkTMin(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect2.fTop == SkTMin(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect2.fRight == SkTMax(line[0].fX, line[1].fX));
        REPORTER_ASSERT(reporter, rect2.fBottom == SkTMax(line[0].fY, line[1].fY));
        REPORTER_ASSERT(reporter, rect.contains(line[0]));
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
    }
    for (index = 0; index < quadTests_count; ++index) {
        const SkDQuad& quad = quadTests[index];
        SkASSERT(ValidQuad(quad));
        rect.setRawBounds(quad);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(quad[0].fX,
                SkTMin(quad[1].fX, quad[2].fX)));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(quad[0].fY,
                SkTMin(quad[1].fY, quad[2].fY)));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(quad[0].fX,
                SkTMax(quad[1].fX, quad[2].fX)));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(quad[0].fY,
                SkTMax(quad[1].fY, quad[2].fY)));
        rect2.setBounds(quad);
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
        // FIXME: add a recursive box subdivision method to verify that tight bounds is correct
        SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
        REPORTER_ASSERT(reporter, rect.contains(leftTop));
        SkDPoint rightBottom = {rect2.fRight, rect2.fBottom};
        REPORTER_ASSERT(reporter, rect.contains(rightBottom));
    }
    for (index = 0; index < cubicTests_count; ++index) {
        const SkDCubic& cubic = cubicTests[index];
        SkASSERT(ValidCubic(cubic));
        rect.setRawBounds(cubic);
        REPORTER_ASSERT(reporter, rect.fLeft == SkTMin(cubic[0].fX,
                SkTMin(cubic[1].fX, SkTMin(cubic[2].fX, cubic[3].fX))));
        REPORTER_ASSERT(reporter, rect.fTop == SkTMin(cubic[0].fY,
                SkTMin(cubic[1].fY, SkTMin(cubic[2].fY, cubic[3].fY))));
        REPORTER_ASSERT(reporter, rect.fRight == SkTMax(cubic[0].fX,
                SkTMax(cubic[1].fX, SkTMax(cubic[2].fX, cubic[3].fX))));
        REPORTER_ASSERT(reporter, rect.fBottom == SkTMax(cubic[0].fY,
                SkTMax(cubic[1].fY, SkTMax(cubic[2].fY, cubic[3].fY))));
        rect2.setBounds(cubic);
        REPORTER_ASSERT(reporter, rect.intersects(&rect2));
        // FIXME: add a recursive box subdivision method to verify that tight bounds is correct
        SkDPoint leftTop = {rect2.fLeft, rect2.fTop};
        REPORTER_ASSERT(reporter, rect.contains(leftTop));
        SkDPoint rightBottom = {rect2.fRight, rect2.fBottom};
        REPORTER_ASSERT(reporter, rect.contains(rightBottom));
    }
}
Exemple #5
0
static void setup(const SortSet* set, const size_t idx,
        SkOpSegment* seg, int* ts, const SkPoint& startPt) {
    SkPoint start, end;
    const SkPoint* data = set[idx].ptData;
    bool useIntersectPt = startPt.fX != 0 || startPt.fY != 0;
    if (useIntersectPt) {
        start = startPt;
        end = set[idx].endPt;
    }
    switch(set[idx].ptCount) {
        case 2: {
            SkASSERT(ValidPoints(data, 2));
            seg->addLine(data, false, false);
            SkDLine dLine;
            dLine.set(set[idx].ptData);
            SkASSERT(ValidLine(dLine));
            if (useIntersectPt) {
                break;
            }
            start = dLine.ptAtT(set[idx].tStart).asSkPoint();
            end = dLine.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
        case 3: {
            SkASSERT(ValidPoints(data, 3));
            seg->addQuad(data, false, false);
            SkDQuad dQuad;
            dQuad.set(set[idx].ptData);
            SkASSERT(ValidQuad(dQuad));
             if (useIntersectPt) {
                break;
            }
            start = dQuad.ptAtT(set[idx].tStart).asSkPoint();
            end = dQuad.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
        case 4: {
            SkASSERT(ValidPoints(data, 4));
            seg->addCubic(data, false, false);
            SkDCubic dCubic;
            dCubic.set(set[idx].ptData);
            SkASSERT(ValidCubic(dCubic));
            if (useIntersectPt) {
                break;
            }
            start = dCubic.ptAtT(set[idx].tStart).asSkPoint();
            end = dCubic.ptAtT(set[idx].tEnd).asSkPoint();
            } break;
    }
    double tStart = set[idx].tStart;
    double tEnd = set[idx].tEnd;
    seg->addT(NULL, start, tStart);
    seg->addT(NULL, end, tEnd);
    if (tStart != 0 && tEnd != 0) {
        seg->addT(NULL, set[idx].ptData[0], 0);
    }
    if (tStart != 1 && tEnd != 1) {
        seg->addT(NULL, set[idx].ptData[set[idx].ptCount - 1], 1);
    }
    int tIndex = 0;
    ts[0] = 0;
    ts[1] = 1;
    do {
        if (seg->t(tIndex) == set[idx].tStart) {
            ts[0] = tIndex;
        }
        if (seg->t(tIndex) == set[idx].tEnd) {
            ts[1] = tIndex;
        }
        if (seg->t(tIndex) >= 1) {
            break;
        }
    } while (++tIndex);
}