Add convex path renderer (disabled)

Review URL: http://codereview.appspot.com/5533061/



git-svn-id: http://skia.googlecode.com/svn/trunk@3040 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrPathUtils.cpp b/src/gpu/GrPathUtils.cpp
index 0a7759d..e41de5c 100644
--- a/src/gpu/GrPathUtils.cpp
+++ b/src/gpu/GrPathUtils.cpp
@@ -8,8 +8,8 @@
 
 
 #include "GrPathUtils.h"
-
 #include "GrPoint.h"
+#include "SkGeometry.h"
 
 GrScalar GrPathUtils::scaleToleranceToSrc(GrScalar devTol,
                                           const GrMatrix& viewM,
@@ -186,3 +186,107 @@
     }
     return pointCount;
 }
+
+namespace {
+// The matrix computed for quadDesignSpaceToUVCoordsMatrix should never really
+// have perspective and we really want to avoid perspective matrix muls.
+//  However, the first two entries of the perspective row may be really close to
+// 0 and the third may not be 1 due to a scale on the entire matrix.
+inline void fixup_matrix(GrMatrix* mat) {
+    GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
+    static const GrScalar gTOL = 1.f / 100.f;
+    GrAssert(GrScalarAbs(mat->get(SkMatrix::kMPersp0)) < gTOL);
+    GrAssert(GrScalarAbs(mat->get(SkMatrix::kMPersp1)) < gTOL);
+    float m33 = mat->get(SkMatrix::kMPersp2);
+    if (1.f != m33) {
+        m33 = 1.f / m33;
+        mat->setAll(m33 * mat->get(SkMatrix::kMScaleX),
+                    m33 * mat->get(SkMatrix::kMSkewX),
+                    m33 * mat->get(SkMatrix::kMTransX),
+                    m33 * mat->get(SkMatrix::kMSkewY),
+                    m33 * mat->get(SkMatrix::kMScaleY),
+                    m33 * mat->get(SkMatrix::kMTransY),
+                    0.f, 0.f, 1.f);
+    } else {
+        mat->setPerspX(0);
+        mat->setPerspY(0);
+    }
+}
+}
+
+// Compute a matrix that goes from the 2d space coordinates to UV space where
+// u^2-v = 0 specifies the quad.
+void GrPathUtils::quadDesignSpaceToUVCoordsMatrix(const SkPoint qPts[3],
+                                                  GrMatrix* matrix) {
+    // can't make this static, no cons :(
+    SkMatrix UVpts;
+    GR_STATIC_ASSERT(SK_SCALAR_IS_FLOAT);
+    UVpts.setAll(0,   0.5f,  1.f,
+                 0,   0,     1.f,
+                 1.f, 1.f,   1.f);
+    matrix->setAll(qPts[0].fX, qPts[1].fX, qPts[2].fX,
+                   qPts[0].fY, qPts[1].fY, qPts[2].fY,
+                   1.f,        1.f,        1.f);
+    matrix->invert(matrix);
+    matrix->postConcat(UVpts);
+    fixup_matrix(matrix);
+}
+
+namespace {
+void convert_noninflect_cubic_to_quads(const SkPoint p[4],
+                                       SkScalar tolScale,
+                                       SkTArray<SkPoint, true>* quads,
+                                       int sublevel = 0) {
+    SkVector ab = p[1];
+    ab -= p[0];
+    SkVector dc = p[2];
+    dc -= p[3];
+
+    static const SkScalar gLengthScale = 3 * SK_Scalar1 / 2;
+    // base tolerance is 2 pixels in dev coords.
+    const SkScalar distanceSqdTol = SkScalarMul(tolScale, 1 * SK_Scalar1);
+    static const int kMaxSubdivs = 10;
+
+    ab.scale(gLengthScale);
+    dc.scale(gLengthScale);
+
+    SkVector c0 = p[0];
+    c0 += ab;
+    SkVector c1 = p[3];
+    c1 += dc;
+
+    SkScalar dSqd = c0.distanceToSqd(c1);
+    if (sublevel > kMaxSubdivs || dSqd <= distanceSqdTol) {
+        SkPoint cAvg = c0;
+        cAvg += c1;
+        cAvg.scale(SK_ScalarHalf);
+
+        SkPoint* pts = quads->push_back_n(3);
+        pts[0] = p[0];
+        pts[1] = cAvg;
+        pts[2] = p[3];
+
+        return;
+    } else {
+        SkPoint choppedPts[7];
+        SkChopCubicAtHalf(p, choppedPts);
+        convert_noninflect_cubic_to_quads(choppedPts + 0, tolScale, 
+                                          quads, sublevel + 1);
+        convert_noninflect_cubic_to_quads(choppedPts + 3, tolScale,
+                                          quads, sublevel + 1);
+    }
+}
+}
+
+void GrPathUtils::convertCubicToQuads(const GrPoint p[4],
+                                      SkScalar tolScale,
+                                      SkTArray<SkPoint, true>* quads) {
+    SkPoint chopped[10];
+    int count = SkChopCubicAtInflections(p, chopped);
+
+    for (int i = 0; i < count; ++i) {
+        SkPoint* cubic = chopped + 3*i;
+        convert_noninflect_cubic_to_quads(cubic, tolScale, quads);
+    }
+
+}