static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2, Intersections& i) { _Line line1; line1[0] = line1[1] = cubic1[start ? 0 : 3]; _Point dxy1 = line1[0] - cubic1[start ? 1 : 2]; dxy1 /= precisionUnit; line1[1] += dxy1; _Rect line1Bounds; line1Bounds.setBounds(line1); if (!bounds2.intersects(line1Bounds)) { return false; } _Line line2; line2[0] = line2[1] = line1[0]; _Point dxy2 = line2[0] - cubic1[start ? 3 : 0]; dxy2 /= precisionUnit; line2[1] += dxy2; #if 0 // this is so close to the first bounds test it isn't worth the short circuit test _Rect line2Bounds; line2Bounds.setBounds(line2); if (!bounds2.intersects(line2Bounds)) { return false; } #endif Intersections local1; if (!intersect(cubic2, line1, local1)) { return false; } Intersections local2; if (!intersect(cubic2, line2, local2)) { return false; } double tMin, tMax; tMin = tMax = local1.fT[0][0]; for (int index = 1; index < local1.fUsed; ++index) { tMin = std::min(tMin, local1.fT[0][index]); tMax = std::max(tMax, local1.fT[0][index]); } for (int index = 1; index < local2.fUsed; ++index) { tMin = std::min(tMin, local2.fT[0][index]); tMax = std::max(tMax, local2.fT[0][index]); } #if SK_DEBUG debugDepth = 0; #endif return intersect2(cubic1, start ? 0 : 1, start ? 1.0 / precisionUnit : 1 - 1.0 / precisionUnit, cubic2, tMin, tMax, 1, i); }
// intersect the end of the cubic with the other. Try lines from the end to control and opposite // end to determine range of t on opposite cubic. static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2, Intersections& i) { // bool selfIntersect = cubic1 == cubic2; _Line line; int t1Index = start ? 0 : 3; line[0] = cubic1[t1Index]; // don't bother if the two cubics are connnected #if 0 if (!selfIntersect && (line[0].approximatelyEqual(cubic2[0]) || line[0].approximatelyEqual(cubic2[3]))) { return false; } #endif bool result = false; SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array for (int index = 0; index < 4; ++index) { if (index == t1Index) { continue; } _Vector dxy1 = cubic1[index] - line[0]; dxy1 /= gPrecisionUnit; line[1] = line[0] + dxy1; _Rect lineBounds; lineBounds.setBounds(line); if (!bounds2.intersects(lineBounds)) { continue; } Intersections local; if (!intersect(cubic2, line, local)) { continue; } for (int idx2 = 0; idx2 < local.used(); ++idx2) { double foundT = local.fT[0][idx2]; if (approximately_less_than_zero(foundT) || approximately_greater_than_one(foundT)) { continue; } if (local.fPt[idx2].approximatelyEqual(line[0])) { if (i.swapped()) { // FIXME: insert should respect swap i.insert(foundT, start ? 0 : 1, line[0]); } else { i.insert(start ? 0 : 1, foundT, line[0]); } result = true; } else { *tVals.append() = local.fT[0][idx2]; } } } if (tVals.count() == 0) { return result; } QSort<double>(tVals.begin(), tVals.end() - 1); double tMin1 = start ? 0 : 1 - LINE_FRACTION; double tMax1 = start ? LINE_FRACTION : 1; int tIdx = 0; do { int tLast = tIdx; while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVals[tIdx])) { ++tLast; } double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); int lastUsed = i.used(); result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); if (lastUsed == i.used()) { tMin2 = SkTMax(tVals[tIdx] - (1.0 / gPrecisionUnit), 0.0); tMax2 = SkTMin(tVals[tLast] + (1.0 / gPrecisionUnit), 1.0); result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); } tIdx = tLast + 1; } while (tIdx < tVals.count()); return result; }