Fix concentric 2pt conical gradient in GPU where r1 < r0

No-Tree-Checks: true
No-Try: true
No-Presubmit: true
Bug: skia:7683
Change-Id: I6608e72fa695c855af6a6a447885c4889b09fc1d
Reviewed-On: https://skia-review.googlesource.com/115042
Commit-Queue: Yuqian Li <liyuqian@google.com>
Reviewed-By: Greg Daniel <egdaniel@google.com>
Reviewed-on: https://skia-review.googlesource.com/117160
Reviewed-by: Yuqian Li <liyuqian@google.com>
diff --git a/gm/gradients_2pt_conical.cpp b/gm/gradients_2pt_conical.cpp
index 8a6b19a..f2e2d18 100644
--- a/gm/gradients_2pt_conical.cpp
+++ b/gm/gradients_2pt_conical.cpp
@@ -98,17 +98,26 @@
 
 static sk_sp<SkShader> Make2ConicalInsideCenter(const SkPoint pts[2], const GradData& data,
                              SkShader::TileMode tm, const SkMatrix& localMatrix) {
-    SkPoint center0, center1;
+    SkPoint center0;
     center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
                 SkScalarAve(pts[0].fY, pts[1].fY));
-    center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5),
-                SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4));
     return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 7,
                                                  center0, (pts[1].fX - pts[0].fX) / 2,
                                                  data.fColors, data.fPos, data.fCount, tm,
                                                  0, &localMatrix);
 }
 
+static sk_sp<SkShader> Make2ConicalInsideCenterReversed(const SkPoint pts[2], const GradData& data,
+                             SkShader::TileMode tm, const SkMatrix& localMatrix) {
+    SkPoint center0;
+    center0.set(SkScalarAve(pts[0].fX, pts[1].fX),
+                SkScalarAve(pts[0].fY, pts[1].fY));
+    return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2,
+                                                 center0, (pts[1].fX - pts[0].fX) / 7,
+                                                 data.fColors, data.fPos, data.fCount, tm,
+                                                 0, &localMatrix);
+}
+
 static sk_sp<SkShader> Make2ConicalZeroRad(const SkPoint pts[2], const GradData& data,
                                            SkShader::TileMode tm, const SkMatrix& localMatrix) {
     SkPoint center0, center1;
@@ -270,6 +279,7 @@
 constexpr GradMaker gGradMakersInside[] = {
     Make2ConicalInside, Make2ConicalInsideFlip, Make2ConicalInsideCenter,
     Make2ConicalZeroRad, Make2ConicalZeroRadFlip, Make2ConicalZeroRadCenter,
+    Make2ConicalInsideCenterReversed
 };
 
 constexpr GradMaker gGradMakersEdgeCases[] = {
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
index 38e4495..6956fa2 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -92,7 +92,9 @@
     bool isNativelyFocal() const { return this->isFocal() && fData.fFocalData.isNativelyFocal(); }
 
     // Note that focalX = f = r0 / (r0 - r1), so 1 - focalX > 0 == r0 < r1
-    bool isRadiusIncreasing() const { return this->isFocal() && 1 - fData.fFocalData.fFocalX > 0; }
+    bool isRadiusIncreasing() const {
+        return this->isFocal() ? 1 - fData.fFocalData.fFocalX > 0 : this->diffRadius() > 0;
+    }
 
 protected:
     void onGetGLSLProcessorKey(const GrShaderCaps& c, GrProcessorKeyBuilder* b) const override {
@@ -237,7 +239,8 @@
         const char* p = coords2D.c_str();
 
         if (effect.getType() == Type::kRadial) {
-            fragBuilder->codeAppendf("half %s = length(%s) - %s;", tName, p, p0.c_str());
+            char sign = effect.diffRadius() < 0 ? '-' : '+';
+            fragBuilder->codeAppendf("half %s = %clength(%s) - %s;", tName, sign, p, p0.c_str());
         } else {
             // output will default to transparent black (we simply won't write anything
             // else to it if invalid, instead of discarding or returning prematurely)
@@ -263,8 +266,9 @@
     void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& p) override {
         INHERITED::onSetData(pdman, p);
         const TwoPointConicalEffect& effect = p.cast<TwoPointConicalEffect>();
-        // kRadialType should imply r1 - r0 = 1 (after our transformation) so r0 = r0 / (r1 - r0)
-        SkASSERT(effect.getType() == Type::kStrip || SkScalarNearlyZero(effect.diffRadius() - 1));
+        // kRadialType should imply |r1 - r0| = 1 (after our transformation)
+        SkASSERT(effect.getType() == Type::kStrip ||
+                 SkScalarNearlyZero(SkTAbs(effect.diffRadius()) - 1));
         pdman.set1f(fParamUni, effect.getType() == Type::kRadial ? effect.r0()
                                                                  : effect.r0() * effect.r0());
     }
@@ -407,12 +411,14 @@
 TwoPointConicalEffect::Data::Data(const SkTwoPointConicalGradient& shader, SkMatrix& matrix) {
     fType = shader.getType();
     if (fType == Type::kRadial) {
-        SkScalar dr = shader.getDiffRadius();
-        // Map center to (0, 0) and scale dr to 1
+        // Map center to (0, 0)
         matrix.postTranslate(-shader.getStartCenter().fX, -shader.getStartCenter().fY);
+
+        // scale |fDiffRadius| to 1
+        SkScalar dr = shader.getDiffRadius();
         matrix.postScale(1 / dr, 1 / dr);
         fRadius0 = shader.getStartRadius() / dr;
-        fDiffRadius = 1;
+        fDiffRadius = dr < 0 ? -1 : 1;
     } else if (fType == Type::kStrip) {
         fRadius0 = shader.getStartRadius() / shader.getCenterX1();
         fDiffRadius = 0;