This takes the convex path tesselator from the Android code and hooks it into a
GrPathRenderer. GrAndroidPathRenderer is activated by gyp flag 'skia_android_path_rendering'.

A few changes to get this to work:
- Had to change SkPaint* param to SkStrokeRec& in ConvexPathVertices()
- Had to copy the vertex buffer created by the Android code to GrDrawTarget-generated vertex buffer, and convert float alpha to GrColor for AA paths


git-svn-id: http://skia.googlecode.com/svn/trunk@7110 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp
index 051ed19..6c32248 100644
--- a/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp
+++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.cpp
@@ -12,7 +12,7 @@
 #define VERTEX_DEBUG 0
 
 #include <SkPath.h>
-#include <SkPaint.h>
+#include <SkStrokeRec.h>
 
 #include <stdlib.h>
 #include <stdint.h>
@@ -520,12 +520,11 @@
 #endif
 }
 
-void PathRenderer::ConvexPathVertices(const SkPath &path, const SkPaint* paint,
+void PathRenderer::ConvexPathVertices(const SkPath &path, const SkStrokeRec& stroke, bool isAA,
         const SkMatrix* transform, VertexBuffer* vertexBuffer) {
     SK_TRACE_EVENT0("PathRenderer::convexPathVertices");
 
-    SkPaint::Style style = paint->getStyle();
-    bool isAA = paint->isAntiAlias();
+    SkStrokeRec::Style style = stroke.getStyle();
 
     float inverseScaleX, inverseScaleY;
     computeInverseScales(transform, inverseScaleX, inverseScaleY);
@@ -533,18 +532,18 @@
     SkTArray<Vertex, true> tempVertices;
     float threshInvScaleX = inverseScaleX;
     float threshInvScaleY = inverseScaleY;
-    if (style == SkPaint::kStroke_Style) {
+    if (style == SkStrokeRec::kStroke_Style) {
         // alter the bezier recursion threshold values we calculate in order to compensate for
         // expansion done after the path vertices are found
         SkRect bounds = path.getBounds();
         if (!bounds.isEmpty()) {
-            threshInvScaleX *= bounds.width() / (bounds.width() + paint->getStrokeWidth());
-            threshInvScaleY *= bounds.height() / (bounds.height() + paint->getStrokeWidth());
+            threshInvScaleX *= bounds.width() / (bounds.width() + stroke.getWidth());
+            threshInvScaleY *= bounds.height() / (bounds.height() + stroke.getWidth());
         }
     }
 
     // force close if we're filling the path, since fill path expects closed perimeter.
-    bool forceClose = style != SkPaint::kStroke_Style;
+    bool forceClose = style != SkStrokeRec::kStroke_Style;
     bool wasClosed = ConvexPathPerimeterVertices(path, forceClose, threshInvScaleX * threshInvScaleX,
             threshInvScaleY * threshInvScaleY, &tempVertices);
 
@@ -559,8 +558,8 @@
     }
 #endif
 
-    if (style == SkPaint::kStroke_Style) {
-        float halfStrokeWidth = paint->getStrokeWidth() * 0.5f;
+    if (style == SkStrokeRec::kStroke_Style) {
+        float halfStrokeWidth = stroke.getWidth() * 0.5f;
         if (!isAA) {
             if (wasClosed) {
                 getStrokeVerticesFromPerimeter(tempVertices, halfStrokeWidth, vertexBuffer,
diff --git a/experimental/AndroidPathRenderer/AndroidPathRenderer.h b/experimental/AndroidPathRenderer/AndroidPathRenderer.h
index 64aebfa..0e87aed 100644
--- a/experimental/AndroidPathRenderer/AndroidPathRenderer.h
+++ b/experimental/AndroidPathRenderer/AndroidPathRenderer.h
@@ -57,7 +57,7 @@
 public:
     static SkRect ComputePathBounds(const SkPath& path, const SkPaint* paint);
 
-    static void ConvexPathVertices(const SkPath& path, const SkPaint* paint,
+    static void ConvexPathVertices(const SkPath& path, const SkStrokeRec& stroke, bool isAA,
             const SkMatrix* transform, VertexBuffer* vertexBuffer);
 
 private:
diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp
new file mode 100644
index 0000000..c2bb708
--- /dev/null
+++ b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.cpp
@@ -0,0 +1,75 @@
+

+/*

+ * Copyright 2012 Google Inc.

+ *

+ * Use of this source code is governed by a BSD-style license that can be

+ * found in the LICENSE file.

+ */

+

+#include "GrAndroidPathRenderer.h"

+#include "AndroidPathRenderer.h"

+#include "Vertex.h"

+

+GrAndroidPathRenderer::GrAndroidPathRenderer() {

+}

+

+bool GrAndroidPathRenderer::canDrawPath(const SkPath& path,

+                                        const SkStrokeRec& stroke,

+                                        const GrDrawTarget* target,

+                                        bool antiAlias) const {

+    return ((stroke.isFillStyle() || stroke.getStyle() == SkStrokeRec::kStroke_Style) 

+             && !path.isInverseFillType() && path.isConvex());

+}

+

+struct ColorVertex {

+    SkPoint pos;

+    GrColor color;

+};

+

+bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,

+                                       const SkStrokeRec& stroke,

+                                       GrDrawTarget* target,

+                                       bool antiAlias) {

+

+    // generate verts using Android algorithm

+    android::uirenderer::VertexBuffer vertices;

+    android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL, 

+                                                          &vertices);

+ 

+    // set vertex layout depending on anti-alias

+    GrVertexLayout layout = antiAlias ? GrDrawTarget::kCoverage_VertexLayoutBit : 0;

+

+    // allocate our vert buffer

+    int vertCount = vertices.getSize();

+    GrDrawTarget::AutoReleaseGeometry geo(target, layout, vertCount, 0);

+    if (!geo.succeeded()) {

+        GrPrintf("Failed to get space for vertices!\n");

+        return false;

+    }

+

+    // copy android verts to our vertex buffer

+    if (antiAlias) {

+        ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices());

+        android::uirenderer::AlphaVertex* inVert = 

+            reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer());

+

+        for (int i = 0; i < vertCount; ++i) {

+            // copy vertex position

+            outVert->pos.set(inVert->position[0], inVert->position[1]);

+            // copy alpha

+            int coverage = static_cast<int>(inVert->alpha * 0xff);

+            outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage);

+            ++outVert;

+            ++inVert;

+        }

+    } else {

+       size_t vsize = GrDrawTarget::VertexSize(layout);

+       size_t copySize = vsize*vertCount;

+       memcpy(geo.vertices(), vertices.getBuffer(), copySize);

+    }

+    

+    // render it

+    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount);

+

+    return true;

+}

diff --git a/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h
new file mode 100644
index 0000000..38d2030
--- /dev/null
+++ b/experimental/AndroidPathRenderer/GrAndroidPathRenderer.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrPathRenderer.h"
+
+
+class GrAndroidPathRenderer : public GrPathRenderer {
+public:
+    GrAndroidPathRenderer();
+
+    virtual bool canDrawPath(const SkPath& path,
+                             const SkStrokeRec& stroke,
+                             const GrDrawTarget* target,
+                             bool antiAlias) const SK_OVERRIDE;
+
+protected:
+    virtual bool onDrawPath(const SkPath& path,
+                            const SkStrokeRec& stroke,
+                            GrDrawTarget* target,
+                            bool antiAlias) SK_OVERRIDE;
+
+private:
+    typedef GrPathRenderer INHERITED;
+};