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)); } }
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); }