add boundary patch
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index dc72008..e1e9536 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -27,6 +27,9 @@
 #include "SkShader.h"
 #include "SkTemplates.h"
 
+#include "SkBoundaryPatch.h"
+#include "SkMeshUtils.h"
+
 #define TIME_DRAWx
 
 static uint32_t get_thread_msec() {
@@ -861,8 +864,6 @@
         *matrix = canvas->getTotalMatrix();
     }
 };
-    
-///////////////////////////////////////////////////////////////////////////////
 
 static JNINativeMethod gCanvasMethods[] = {
     {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
@@ -965,6 +966,42 @@
     {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
 };
 
+///////////////////////////////////////////////////////////////////////////////
+
+static void BoundaryPatch_computeCubic(JNIEnv* env, jobject, jfloatArray jpts,
+                                   int texW, int texH, int rows, int cols,
+                                   jfloatArray jverts, jshortArray jidx) {
+    AutoJavaFloatArray ptsArray(env, jpts, 24, kRO_JNIAccess);
+
+    int vertCount = rows * cols;
+    AutoJavaFloatArray vertsArray(env, jverts, vertCount * 4, kRW_JNIAccess);
+    SkPoint* verts = (SkPoint*)vertsArray.ptr();
+    SkPoint* texs = verts + vertCount;
+
+    int idxCount = (rows - 1) * (cols - 1) * 6;
+    AutoJavaShortArray idxArray(env, jidx, idxCount, kRW_JNIAccess);
+    uint16_t* idx = (uint16_t*)idxArray.ptr();  // cast from int16_t*
+
+    SkCubicBoundary cubic;
+    memcpy(cubic.fPts, ptsArray.ptr(), 12 * sizeof(SkPoint));
+
+    SkBoundaryPatch patch;
+    patch.setBoundary(&cubic);
+    // generate our verts
+    patch.evalPatch(verts, rows, cols);
+
+    SkMeshIndices mesh;
+    // generate our texs and idx
+    mesh.init(texs, idx, texW, texH, rows, cols);
+}
+
+static JNINativeMethod gBoundaryPatchMethods[] = {
+    {"nativeComputeCubicPatch", "([FIIII[F[S)V",
+    (void*)BoundaryPatch_computeCubic },
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
 #include <android_runtime/AndroidRuntime.h>
 
 #define REG(env, name, array) \
@@ -976,6 +1013,7 @@
     int result;
 
     REG(env, "android/graphics/Canvas", gCanvasMethods);
+    REG(env, "android/graphics/utils/BoundaryPatch", gBoundaryPatchMethods);
     
     return result;
 }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 2e0caed..01aad938 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -56,7 +56,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 AutoJavaFloatArray::AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
-                                       int minLength)
+                                       int minLength, JNIAccess access)
 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
     SkASSERT(env);
     if (array) {
@@ -66,11 +66,12 @@
         }
         fPtr = env->GetFloatArrayElements(array, NULL);
     }
+    fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
 }
 
 AutoJavaFloatArray::~AutoJavaFloatArray() {
     if (fPtr) {
-        fEnv->ReleaseFloatArrayElements(fArray, fPtr, 0);
+        fEnv->ReleaseFloatArrayElements(fArray, fPtr, fReleaseMode);
     }
 }
 
@@ -94,7 +95,7 @@
 }
 
 AutoJavaShortArray::AutoJavaShortArray(JNIEnv* env, jshortArray array,
-                                       int minLength)
+                                       int minLength, JNIAccess access)
 : fEnv(env), fArray(array), fPtr(NULL), fLen(0) {
     SkASSERT(env);
     if (array) {
@@ -104,11 +105,12 @@
         }
         fPtr = env->GetShortArrayElements(array, NULL);
     }
+    fReleaseMode = (access == kRO_JNIAccess) ? JNI_ABORT : 0;
 }
 
 AutoJavaShortArray::~AutoJavaShortArray() {
     if (fPtr) {
-        fEnv->ReleaseShortArrayElements(fArray, fPtr, 0);
+        fEnv->ReleaseShortArrayElements(fArray, fPtr, fReleaseMode);
     }
 }
 
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 7adadbc..fe24b05 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -80,9 +80,15 @@
     bool fReportSizeToVM;
 };
 
+enum JNIAccess {
+    kRO_JNIAccess,
+    kRW_JNIAccess
+};
+
 class AutoJavaFloatArray {
 public:
-    AutoJavaFloatArray(JNIEnv* env, jfloatArray array, int minLength = 0);
+    AutoJavaFloatArray(JNIEnv* env, jfloatArray array,
+                       int minLength = 0, JNIAccess = kRW_JNIAccess);
     ~AutoJavaFloatArray();
     
     float* ptr() const { return fPtr; }
@@ -93,6 +99,7 @@
     jfloatArray fArray;
     float*      fPtr;
     int         fLen;
+    int         fReleaseMode;
 };
 
 class AutoJavaIntArray {
@@ -112,7 +119,8 @@
 
 class AutoJavaShortArray {
 public:
-    AutoJavaShortArray(JNIEnv* env, jshortArray array, int minLength = 0);
+    AutoJavaShortArray(JNIEnv* env, jshortArray array,
+                       int minLength = 0, JNIAccess = kRW_JNIAccess);
     ~AutoJavaShortArray();
     
     jshort* ptr() const { return fPtr; }
@@ -123,6 +131,7 @@
     jshortArray fArray;
     jshort*      fPtr;
     int         fLen;
+    int         fReleaseMode;
 };
 
 class AutoJavaByteArray {