From febbffad1c24136f041d7fc2d5ffcd50e47a047f Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Thu, 8 Jun 2017 13:12:02 -0600 Subject: Improve cubic KLM accuracy Moves cubic root finding logic out of GrPathUtils and PathOpsCubicIntersectionTest, and unifies it in SkGeometry. "Normalizes" the homogeneous parameter values of the roots, rather than the cubic inflection function. Does this normalization by twiddling the exponents instead of division (which causes a loss of precision). Abandons the built-in derivatives in GrCubicEffect. These don't have high enough precision on many mobile gpus. Instead we pass the KLM matrix to the vertex shader via uniform, where we can use it to set up new linear functionals from which the fragment shader can calculate the gradient of the implicit function. Bug: skia:4410 Change-Id: Ibd64e999520adc8cdef7803a492d3699995aef5a Reviewed-on: https://skia-review.googlesource.com/19017 Reviewed-by: Greg Daniel Commit-Queue: Chris Dalton --- src/pathops/SkPathOpsCubic.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'src/pathops') diff --git a/src/pathops/SkPathOpsCubic.cpp b/src/pathops/SkPathOpsCubic.cpp index 794e54fdfe..d7b905cdad 100644 --- a/src/pathops/SkPathOpsCubic.cpp +++ b/src/pathops/SkPathOpsCubic.cpp @@ -248,20 +248,13 @@ int SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) { if (cubic.monotonicInX() && cubic.monotonicInY()) { return 0; } - SkScalar d[4]; - SkCubicType cubicType = SkClassifyCubic(pointsPtr, d); + SkScalar tt[2], ss[2]; + SkCubicType cubicType = SkClassifyCubic(pointsPtr, tt, ss); switch (cubicType) { case SkCubicType::kLoop: { - // crib code from gpu path utils that finds t values where loop self-intersects - // use it to find mid of t values which should be a friendly place to chop - SkASSERT(d[0] < 0); - const SkScalar q = d[2] + SkScalarCopySign(SkScalarSqrt(-d[0]), d[2]); - const SkScalar td = q; - const SkScalar sd = 2 * d[1]; - const SkScalar te = 2 * (d[2] * d[2] - d[3] * d[1]); - const SkScalar se = d[1] * q; + const SkScalar &td = tt[0], &te = tt[1], &sd = ss[0], &se = ss[1]; if (roughly_between(0, td, sd) && roughly_between(0, te, se)) { - SkASSERT(roughly_between(0, td / sd, 1) && roughly_between(0, te / se, 1)); + SkASSERT(roughly_between(0, td/sd, 1) && roughly_between(0, te/se, 1)); t[0] = (td * se + te * sd) / (2 * sd * se); SkASSERT(roughly_between(0, *t, 1)); return (int) (t[0] > 0 && t[0] < 1); @@ -270,7 +263,7 @@ int SkDCubic::ComplexBreak(const SkPoint pointsPtr[4], SkScalar* t) { // fall through if no t value found case SkCubicType::kSerpentine: case SkCubicType::kLocalCusp: - case SkCubicType::kInfiniteCusp: { + case SkCubicType::kCuspAtInfinity: { double inflectionTs[2]; int infTCount = cubic.findInflections(inflectionTs); double maxCurvature[3]; -- cgit v1.2.3