29 if (
fPts[endIndex].fX ==
fPts[ctrlIndex].fX) {
32 if (
fPts[endIndex].fY ==
fPts[ctrlIndex].fY) {
41 double t = (
min +
max) / 2;
44 double calcPos = (&cubicAtT.
fX)[xAxis];
45 double calcDist = calcPos - axisIntercept;
53 double lessDist = (&lessPt.
fX)[xAxis] - axisIntercept;
54#if DEBUG_CUBIC_BINARY_SEARCH
55 SkDebugf(
"t=%1.9g calc=%1.9g dist=%1.9g step=%1.9g less=%1.9g\n", t, calcPos, calcDist,
58 double lastStep =
step;
60 if (calcDist > 0 ? calcDist > lessDist : calcDist < lessDist) {
63 double nextT = t + lastStep;
72 double moreDist = (&morePt.
fX)[xAxis] - axisIntercept;
73 if (calcDist > 0 ? calcDist <= moreDist : calcDist >= moreDist) {
80 calcPos = (&cubicAtT.
fX)[xAxis];
81 calcDist = calcPos - axisIntercept;
140 *
B += 3 * *
D - 2 * *
C;
162 int end1 = hullOrder[0];
165 endPt[0] = &
fPts[end1];
167 hullIndex = (hullIndex + 1) % hullCount;
168 int end2 = hullOrder[hullIndex];
169 endPt[1] = &
fPts[end2];
170 double origX = endPt[0]->
fX;
171 double origY = endPt[0]->
fY;
172 double adj = endPt[1]->
fX - origX;
173 double opp = endPt[1]->
fY - origY;
175 int oddMan = end1 ^ oddManMask;
176 double sign = (
fPts[oddMan].
fY - origY) * adj - (
fPts[oddMan].fX - origX) * opp;
177 int oddMan2 = end2 ^ oddManMask;
178 double sign2 = (
fPts[oddMan2].
fY - origY) * adj - (
fPts[oddMan2].fX - origX) * opp;
179 if (
sign * sign2 < 0) {
189 bool foundOutlier =
false;
190 for (
int n = 0; n < ptCount; ++n) {
191 double test = (pts[n].
fY - origY) * adj - (pts[n].fX - origX) * opp;
221 if (
fPts[0].approximatelyDEqual(
fPts[3])) {
222 return ((
const SkDQuad *)
this)->isLinear(0, 2);
232 largest =
std::max(largest, -tiniest);
246 double one_t = 1 - t;
251 return 3 * ((
b -
a) * one_t * one_t + 2 * (c -
b) * t * one_t + (
d - c) * t * t);
256 cubic.set(pointsPtr);
257 if (
cubic.monotonicInX() &&
cubic.monotonicInY()) {
264 const double &td = tt[0], &te = tt[1], &sd = ss[0], &se = ss[1];
266 t[0] =
static_cast<SkScalar>((td * se + te * sd) / (2 * sd * se));
267 return (
int) (t[0] > 0 && t[0] < 1);
274 double inflectionTs[2];
275 int infTCount =
cubic.findInflections(inflectionTs);
276 double maxCurvature[3];
277 int roots =
cubic.findMaxCurvature(maxCurvature);
278 #if DEBUG_CUBIC_SPLIT
281 for (
int index = 0; index < infTCount; ++index) {
282 SkDebugf(
"inflectionsTs[%d]=%1.9g ", index, inflectionTs[index]);
285 SkDLine perp = {{pt - dPt, pt + dPt}};
288 for (
int index = 0; index <
roots; ++index) {
289 SkDebugf(
"maxCurvature[%d]=%1.9g ", index, maxCurvature[index]);
292 SkDLine perp = {{pt - dPt, pt + dPt}};
296 if (infTCount == 2) {
297 for (
int index = 0; index <
roots; ++index) {
298 if (
between(inflectionTs[0], maxCurvature[index], inflectionTs[1])) {
299 t[0] = maxCurvature[index];
300 return (
int) (t[0] > 0 && t[0] < 1);
306 double precision =
cubic.calcPrecision() * 2;
307 for (
int index = 0; index <
roots; ++index) {
308 double testT = maxCurvature[index];
309 if (0 >= testT || testT >= 1) {
315 double dPtLen = dPt.
length();
316 if (dPtLen < precision) {
317 t[resultCount++] = testT;
320 if (!resultCount && infTCount == 1) {
321 t[0] = inflectionTs[0];
322 resultCount = (
int) (t[0] > 0 && t[0] < 1);
354 extremeTs[extrema++] = 0;
355 extremeTs[extrema] = 1;
357 SkTQSort(extremeTs, extremeTs + extrema + 1);
359 for (
int index = 0; index < extrema; ) {
360 double min = extremeTs[index];
361 double max = extremeTs[++index];
367 if (validCount >= 3) {
370 validRoots[validCount++] = newT;
378static const double PI = 3.141592653589793;
386 for (
int index = 0; index < realRoots; ++index) {
387 double tValue =
s[index];
389 for (
int idx2 = 0; idx2 < foundRoots; ++idx2) {
397 for (
int idx2 = 0; idx2 < foundRoots; ++idx2) {
414 #if ONE_OFF_DEBUG && ONE_OFF_DEBUG_MATHEMATICA
420 snprintf(str,
sizeof(str),
"Solve[%1.19g x^3 + %1.19g x^2 + %1.19g x + %1.19g == 0, x]",
436 for (
int i = 0;
i < num; ++
i) {
446 for (
int i = 0;
i < num; ++
i) {
462 double Q = (a2 -
b * 3) / 9;
463 double R = (2 * a2 *
a - 9 *
a *
b + 27 * c) / 54;
465 double Q3 =
Q *
Q *
Q;
466 double R2MinusQ3 =
R2 -
Q3;
467 double adiv3 =
a / 3;
473 double neg2RootQ = -2 *
sqrt(
Q);
475 r = neg2RootQ * cos(theta / 3) - adiv3;
478 r = neg2RootQ * cos((theta + 2 *
PI) / 3) - adiv3;
482 r = neg2RootQ * cos((theta - 2 *
PI) / 3) - adiv3;
487 double sqrtR2MinusQ3 =
sqrt(R2MinusQ3);
488 A = fabs(
R) + sqrtR2MinusQ3;
505 return static_cast<int>(
roots -
s);
544 coeff[1] = 3 *
b * c;
545 coeff[2] = 2 *
b *
b + c *
a;
561 double A =
d -
a + 3 * (
b - c);
562 double B = 2 * (
a -
b -
b + c);
581 double coeffX[4], coeffY[4];
585 for (
i = 0;
i < 4;
i++) {
586 coeffX[
i] = coeffX[
i] + coeffY[
i];
588 return RootsValidT(coeffX[0], coeffX[1], coeffX[2], coeffX[3], tValues);
598 double one_t = 1 - t;
599 double one_t2 = one_t * one_t;
600 double a = one_t2 * one_t;
601 double b = 3 * one_t2 * t;
603 double c = 3 * one_t * t2;
667 if (t1 == 0 || t2 == 1) {
668 if (t1 == 0 && t2 == 1) {
684 double mx = ex * 27 -
ax * 8 -
dx;
685 double my = ey * 27 - ay * 8 - dy;
686 double nx = fx * 27 -
ax -
dx * 8;
687 double ny = fy * 27 - ay - dy * 8;
688 dst[1].fX = (mx * 2 - nx) / 18;
689 dst[1].fY = (my * 2 - ny) / 18;
690 dst[2].fX = (nx * 2 - mx) / 18;
691 dst[2].fY = (ny * 2 - my) / 18;
701 dst[0] = sub[1] + (
a - sub[0]);
702 dst[1] = sub[2] + (
d - sub[3]);
703 if (t1 == 0 || t2 == 0) {
706 if (t1 == 1 || t2 == 1) {
724 const double* dCubic = &
fPts[0].
fX;
726 for (
int index = 0; index <
kPointCount * 2; ++index) {
739 for (
int index = 0; index <
roots; ++index) {
740 double t = startT + (endT - startT) * extremeTs[index];
742 if (topPt->
fY > mid.fY || (topPt->
fY == mid.fY && topPt->
fX > mid.fX)) {
static int step(int x, SkScalar min, SkScalar max)
sk_bzero(glyphs, sizeof(glyphs))
static bool approximately_zero(double x)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool SkIsFinite(T x, Pack... values)
SkCubicType SkClassifyCubic(const SkPoint P[4], double t[2], double s[2], double d[4])
static double derivative_at_t(const double *src, double t)
static void formulate_F1DotF2(const double src[], double coeff[4])
static void interp_cubic_coords(const double *src, double *dst, double t)
int other_two(int one, int two)
bool AlmostBequalUlps(float a, float b)
bool AlmostDequalUlps(float a, float b)
bool approximately_equal(double x, double y)
bool precisely_zero(double x)
bool approximately_one_or_less(double x)
bool roughly_between(double a, double b, double c)
bool approximately_zero_or_more(double x)
const double FLT_EPSILON_ORDERABLE_ERR
bool between(double a, double b, double c)
bool precisely_between(double a, double b, double c)
bool approximately_equal_half(double x, double y)
double SkDInterp(double A, double B, double t)
bool approximately_zero_when_compared_to(double x, double y)
bool zero_or_one(double x)
static int sign(SkScalar x)
#define SkDoubleToScalar(x)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
void SkTQSort(T *begin, T *end, const C &lessThan)
static constexpr bool SkToBool(const T &x)
bool cubicEndPoints(const SkDCubic &pts)
double controlPtDistance(const SkDCubic &pts, int index) const
static void MathematicaIze(char *str, size_t bufferSize)
bool hullIntersects(const SkDQuad &quad, bool *isLinear) const override
int intersectRay(SkIntersections *i, const SkDLine &line) const override
void setBounds(SkDRect *) const override
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
static float max(float r, float g, float b)
static float min(float r, float g, float b)
sk_sp< SkBlender > blender SkRect rect
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
const CatchEntryMove ab[]
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
int findMaxCurvature(double tValues[]) const
int convexHull(char order[kPointCount]) const
bool hullIntersects(const SkDCubic &c2, bool *isLinear) const
bool toFloatPoints(SkPoint *) const
bool isLinear(int startIndex, int endIndex) const
SkDCubicPair chopAt(double t) const
static int RootsReal(double A, double B, double C, double D, double t[3])
double binarySearch(double min, double max, double axisIntercept, SearchAxis xAxis) const
int findInflections(double tValues[2]) const
bool monotonicInX() const
bool endsAreExtremaInXOrY() const
void align(int endIndex, int ctrlIndex, SkDPoint *dstPt) const
double calcPrecision() const
SkDPoint fPts[kPointCount]
bool monotonicInY() const
static const int gPrecisionUnit
static int FindExtrema(const double src[], double tValue[2])
double top(const SkDCubic &dCurve, double startT, double endT, SkDPoint *topPt) const
static void Coefficients(const double *cubic, double *A, double *B, double *C, double *D)
int searchRoots(double extremes[6], int extrema, double axisIntercept, SearchAxis xAxis, double *validRoots) const
static int RootsValidT(const double A, const double B, const double C, double D, double s[3])
SkDVector dxdyAtT(double t) const
SkDPoint ptAtT(double t) const
void otherPts(int index, const SkDPoint *o1Pts[kPointCount - 1]) const
static const int kPointCount
SkDCubic subDivide(double t1, double t2) const
static int ComplexBreak(const SkPoint pts[4], SkScalar *t)
static int RootsValidT(const double A, const double B, const double C, double s[2])
static int RootsReal(double A, double B, double C, double t[2])
static int AddValidTs(double s[], int realRoots, double *t)
bool hullIntersects(const SkDQuad &, bool *isLinear) const
SkDPoint fPts[kPointCount]
static const int kPointCount
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)