DEF_TEST(PathOpsDPoint, reporter) { for (size_t index = 0; index < tests_count; ++index) { const SkDPoint& pt = tests[index]; SkASSERT(ValidPoint(pt)); SkDPoint p = pt; REPORTER_ASSERT(reporter, p == pt); REPORTER_ASSERT(reporter, !(pt != pt)); SkDVector v = p - pt; p += v; REPORTER_ASSERT(reporter, p == pt); p -= v; REPORTER_ASSERT(reporter, p == pt); REPORTER_ASSERT(reporter, p.approximatelyEqual(pt)); SkPoint sPt = pt.asSkPoint(); p.set(sPt); REPORTER_ASSERT(reporter, p == pt); REPORTER_ASSERT(reporter, p.approximatelyEqual(sPt)); REPORTER_ASSERT(reporter, p.roughlyEqual(pt)); p.fX = p.fY = 0; REPORTER_ASSERT(reporter, p.fX == 0 && p.fY == 0); REPORTER_ASSERT(reporter, p.approximatelyZero()); REPORTER_ASSERT(reporter, pt.distanceSquared(p) == pt.fX * pt.fX + pt.fY * pt.fY); REPORTER_ASSERT(reporter, approximately_equal(pt.distance(p), sqrt(pt.fX * pt.fX + pt.fY * pt.fY))); } }
static void chopCompare(const SkConic chopped[2], const SkDConic dChopped[2]) { SkASSERT(roughly_equal(chopped[0].fW, dChopped[0].fWeight)); SkASSERT(roughly_equal(chopped[1].fW, dChopped[1].fWeight)); for (int cIndex = 0; cIndex < 2; ++cIndex) { for (int pIndex = 0; pIndex < 3; ++pIndex) { SkDPoint up; up.set(chopped[cIndex].fPts[pIndex]); SkASSERT(dChopped[cIndex].fPts[pIndex].approximatelyEqual(up)); } } #if DEBUG_VISUALIZE_CONICS dChopped[0].dump(); dChopped[1].dump(); #endif }
bool SkOpAngle::endsIntersect(const SkOpAngle& rh) const { SkPath::Verb lVerb = fSegment->verb(); SkPath::Verb rVerb = rh.fSegment->verb(); int lPts = SkPathOpsVerbToPoints(lVerb); int rPts = SkPathOpsVerbToPoints(rVerb); SkDLine rays[] = {{{fCurvePart[0], rh.fCurvePart[rPts]}}, {{fCurvePart[0], fCurvePart[lPts]}}}; if (rays[0][1] == rays[1][1]) { return checkParallel(rh); } double smallTs[2] = {-1, -1}; bool limited[2] = {false, false}; for (int index = 0; index < 2; ++index) { const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; SkIntersections i; (*CurveIntersectRay[index ? rPts : lPts])(segment.pts(), rays[index], &i); // SkASSERT(i.used() >= 1); // if (i.used() <= 1) { // continue; // } double tStart = segment.t(index ? rh.fStart : fStart); double tEnd = segment.t(index ? rh.fComputedEnd : fComputedEnd); bool testAscends = index ? rh.fStart < rh.fComputedEnd : fStart < fComputedEnd; double t = testAscends ? 0 : 1; for (int idx2 = 0; idx2 < i.used(); ++idx2) { double testT = i[0][idx2]; if (!approximately_between_orderable(tStart, testT, tEnd)) { continue; } if (approximately_equal_orderable(tStart, testT)) { continue; } smallTs[index] = t = testAscends ? SkTMax(t, testT) : SkTMin(t, testT); limited[index] = approximately_equal_orderable(t, tEnd); } } #if 0 if (smallTs[0] < 0 && smallTs[1] < 0) { // if neither ray intersects, do endpoint sort double m0xm1 = 0; if (lVerb == SkPath::kLine_Verb) { SkASSERT(rVerb != SkPath::kLine_Verb); SkDVector m0 = rays[1][1] - fCurvePart[0]; SkDPoint endPt; endPt.set(rh.fSegment->pts()[rh.fStart < rh.fEnd ? rPts : 0]); SkDVector m1 = endPt - fCurvePart[0]; m0xm1 = m0.crossCheck(m1); } if (rVerb == SkPath::kLine_Verb) { SkDPoint endPt; endPt.set(fSegment->pts()[fStart < fEnd ? lPts : 0]); SkDVector m0 = endPt - fCurvePart[0]; SkDVector m1 = rays[0][1] - fCurvePart[0]; m0xm1 = m0.crossCheck(m1); } if (m0xm1 != 0) { return m0xm1 < 0; } } #endif bool sRayLonger = false; SkDVector sCept = {0, 0}; double sCeptT = -1; int sIndex = -1; bool useIntersect = false; for (int index = 0; index < 2; ++index) { if (smallTs[index] < 0) { continue; } const SkOpSegment& segment = index ? *rh.fSegment : *fSegment; const SkDPoint& dPt = segment.dPtAtT(smallTs[index]); SkDVector cept = dPt - rays[index][0]; // If this point is on the curve, it should have been detected earlier by ordinary // curve intersection. This may be hard to determine in general, but for lines, // the point could be close to or equal to its end, but shouldn't be near the start. if ((index ? lPts : rPts) == 1) { SkDVector total = rays[index][1] - rays[index][0]; if (cept.lengthSquared() * 2 < total.lengthSquared()) { continue; } } SkDVector end = rays[index][1] - rays[index][0]; if (cept.fX * end.fX < 0 || cept.fY * end.fY < 0) { continue; } double rayDist = cept.length(); double endDist = end.length(); bool rayLonger = rayDist > endDist; if (limited[0] && limited[1] && rayLonger) { useIntersect = true; sRayLonger = rayLonger; sCept = cept; sCeptT = smallTs[index]; sIndex = index; break; } double delta = fabs(rayDist - endDist); double minX, minY, maxX, maxY; minX = minY = SK_ScalarInfinity; maxX = maxY = -SK_ScalarInfinity; const SkDCubic& curve = index ? rh.fCurvePart : fCurvePart; int ptCount = index ? rPts : lPts; for (int idx2 = 0; idx2 <= ptCount; ++idx2) { minX = SkTMin(minX, curve[idx2].fX); minY = SkTMin(minY, curve[idx2].fY); maxX = SkTMax(maxX, curve[idx2].fX); maxY = SkTMax(maxY, curve[idx2].fY); } double maxWidth = SkTMax(maxX - minX, maxY - minY); delta /= maxWidth; if (delta > 1e-4 && (useIntersect ^= true)) { // FIXME: move this magic number sRayLonger = rayLonger; sCept = cept; sCeptT = smallTs[index]; sIndex = index; } } if (useIntersect) { const SkDCubic& curve = sIndex ? rh.fCurvePart : fCurvePart; const SkOpSegment& segment = sIndex ? *rh.fSegment : *fSegment; double tStart = segment.t(sIndex ? rh.fStart : fStart); SkDVector mid = segment.dPtAtT(tStart + (sCeptT - tStart) / 2) - curve[0]; double septDir = mid.crossCheck(sCept); if (!septDir) { return checkParallel(rh); } return sRayLonger ^ (sIndex == 0) ^ (septDir < 0); } else { return checkParallel(rh); } }