diff options
-rw-r--r-- | gm/beziereffects.cpp | 14 | ||||
-rw-r--r-- | src/gpu/GrPathUtils.cpp | 38 | ||||
-rw-r--r-- | src/gpu/GrPathUtils.h | 10 | ||||
-rw-r--r-- | src/gpu/effects/GrBezierEffect.cpp | 6 |
4 files changed, 36 insertions, 32 deletions
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp index 54c28a7e5f..9167410e9f 100644 --- a/gm/beziereffects.cpp +++ b/gm/beziereffects.cpp @@ -156,15 +156,16 @@ protected: }; SkPoint chopped[10]; SkScalar klmEqs[9]; - SkScalar klmSigns[3]; + int loopIndex; int cnt = GrPathUtils::chopCubicAtLoopIntersection(controlPts, chopped, klmEqs, - klmSigns); + &loopIndex); SkPaint ctrlPtPaint; ctrlPtPaint.setColor(rand.nextU() | 0xFF000000); - for (int i = 0; i < 4; ++i) { + canvas->drawCircle(controlPts[0].fX, controlPts[0].fY, 8.f, ctrlPtPaint); + for (int i = 1; i < 4; ++i) { canvas->drawCircle(controlPts[i].fX, controlPts[i].fY, 6.f, ctrlPtPaint); } @@ -196,8 +197,13 @@ protected: GrPaint grPaint; grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc)); + SkScalar sign = 1.0f; + if (c == loopIndex && cnt != 3) { + sign = -1.0f; + } + std::unique_ptr<GrMeshDrawOp> op = - BezierCubicOrConicTestOp::Make(gp, bounds, color, klmEqs, klmSigns[c]); + BezierCubicOrConicTestOp::Make(gp, bounds, color, klmEqs, sign); renderTargetContext->priv().testingOnly_addMeshDrawOp( std::move(grPaint), GrAAType::kNone, std::move(op)); diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp index 867407d9e4..0bc84795b3 100644 --- a/src/gpu/GrPathUtils.cpp +++ b/src/gpu/GrPathUtils.cpp @@ -621,7 +621,7 @@ static void set_serp_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkSc m[2] = mt_ms * mt_ms * ms; m[3] = -1.f * mt_ms * mt_ms * mt_ms; - // If d0 < 0 we need to flip the orientation of our curve + // If d0 > 0 we need to flip the orientation of our curve // This is done by negating the k and l values // We want negative distance values to be on the inside if ( d[0] > 0) { @@ -655,10 +655,12 @@ static void set_loop_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], SkSc m[3] = -1.f * (lt - ls) * (mt - ms) * (mt - ms); - // If (d0 < 0 && sign(k1) > 0) || (d0 > 0 && sign(k1) < 0), - // we need to flip the orientation of our curve. - // This is done by negating the k and l values - if ( (d[0] < 0 && k[1] > 0) || (d[0] > 0 && k[1] < 0)) { + // For the general loop curve, we flip the orientation in the same pattern as the serp case + // above. Thus we only check d[0]. Technically we should check the value of the hessian as well + // cause we care about the sign of d[0]*Hessian. However, the Hessian is always negative outside + // the loop section and positive inside. We take care of the flipping for the loop sections + // later on. + if (d[0] > 0) { for (int i = 0; i < 4; ++i) { k[i] = -k[i]; l[i] = -l[i]; @@ -709,8 +711,8 @@ static void set_quadratic_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], m[2] = 2.f/3.f; m[3] = 1.f; - // If d2 < 0 we need to flip the orientation of our curve - // This is done by negating the k and l values + // If d2 < 0 we need to flip the orientation of our curve since we want negative values to be on + // the "inside" of the curve. This is done by negating the k and l values if ( d[2] > 0) { for (int i = 0; i < 4; ++i) { k[i] = -k[i]; @@ -720,7 +722,7 @@ static void set_quadratic_klm(const SkScalar d[3], SkScalar k[4], SkScalar l[4], } int GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[10], SkScalar klm[9], - SkScalar klm_rev[3]) { + int* loopIndex) { // Variable to store the two parametric values at the loop double point SkScalar smallS = 0.f; SkScalar largeS = 0.f; @@ -762,28 +764,24 @@ int GrPathUtils::chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[1 } } - if (klm && klm_rev) { - // Set klm_rev to to match the sub_section of cubic that needs to have its orientation - // flipped. This will always be the section that is the "loop" + if (loopIndex) { if (2 == chop_count) { - klm_rev[0] = 1.f; - klm_rev[1] = -1.f; - klm_rev[2] = 1.f; + *loopIndex = 1; } else if (1 == chop_count) { if (smallS < 0.f) { - klm_rev[0] = -1.f; - klm_rev[1] = 1.f; + *loopIndex = 0; } else { - klm_rev[0] = 1.f; - klm_rev[1] = -1.f; + *loopIndex = 1; } } else { if (smallS < 0.f && largeS > 1.f) { - klm_rev[0] = -1.f; + *loopIndex = 0; } else { - klm_rev[0] = 1.f; + *loopIndex = -1; } } + } + if (klm) { SkScalar controlK[4]; SkScalar controlL[4]; SkScalar controlM[4]; diff --git a/src/gpu/GrPathUtils.h b/src/gpu/GrPathUtils.h index fcc32c89c4..8b844180b7 100644 --- a/src/gpu/GrPathUtils.h +++ b/src/gpu/GrPathUtils.h @@ -146,16 +146,16 @@ namespace GrPathUtils { // K = (klm[0], klm[1], klm[2]) // L = (klm[3], klm[4], klm[5]) // M = (klm[6], klm[7], klm[8]) - // klm_rev: These values are flags for the corresponding sub cubic saying whether or not - // the K and L values need to be flipped. A value of -1.f means flip K and L and - // a value of 1.f means do nothing. - // *****DO NOT FLIP M, JUST K AND L***** + // loopIndex: This value will tell the caller which of the chopped sections are the the actual + // loop once we've chopped. A value of -1 means there is no loop section. The caller + // can then use this value to decide how/if they want to flip the orientation of this + // section. This flip should be done by negating the K and L values. // // Notice that the klm lines are calculated in the same space as the input control points. // If you transform the points the lines will also need to be transformed. This can be done // by mapping the lines with the inverse-transpose of the matrix used to map the points. int chopCubicAtLoopIntersection(const SkPoint src[4], SkPoint dst[10] = nullptr, - SkScalar klm[9] = nullptr, SkScalar klm_rev[3] = nullptr); + SkScalar klm[9] = nullptr, int* loopIndex = nullptr); // Input is p which holds the 4 control points of a non-rational cubic Bezier curve. // Output is the coefficients of the three linear functionals K, L, & M which diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index 6c01f70028..e8476c8243 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -183,7 +183,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); fragBuilder->codeAppendf("%s = %s / %s;", edgeAlpha.c_str(), func.c_str(), gFM.c_str()); - fragBuilder->codeAppendf("%s = clamp(1.0 - %s, 0.0, 1.0);", + fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);", edgeAlpha.c_str(), edgeAlpha.c_str()); // Add line below for smooth cubic ramp // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); @@ -390,7 +390,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { fragBuilder->codeAppendf("edgeAlpha = (%s.x * %s.x - %s.y);", v.fsIn(), v.fsIn(), v.fsIn()); fragBuilder->codeAppend("edgeAlpha = edgeAlpha / sqrt(dot(gF, gF));"); - fragBuilder->codeAppend("edgeAlpha = clamp(1.0 - edgeAlpha, 0.0, 1.0);"); + fragBuilder->codeAppend("edgeAlpha = clamp(0.5 - edgeAlpha, 0.0, 1.0);"); // Add line below for smooth cubic ramp // fragBuilder->codeAppend("edgeAlpha = edgeAlpha*edgeAlpha*(3.0-2.0*edgeAlpha);"); break; @@ -624,7 +624,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) { v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn()); fragBuilder->codeAppendf("%s = %s / %s;", edgeAlpha.c_str(), func.c_str(), gFM.c_str()); - fragBuilder->codeAppendf("%s = clamp(1.0 - %s, 0.0, 1.0);", + fragBuilder->codeAppendf("%s = clamp(0.5 - %s, 0.0, 1.0);", edgeAlpha.c_str(), edgeAlpha.c_str()); // Add line below for smooth cubic ramp // fragBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);", |