Merge "Matrix JNI update"
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index b0f3bb4..f8bb77a 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
@@ -25,14 +25,25 @@
 
 namespace android {
 
+static_assert(sizeof(SkMatrix) == 40, "Unexpected sizeof(SkMatrix), "
+        "update size in Matrix.java#NATIVE_ALLOCATION_SIZE and here");
+static_assert(SK_SCALAR_IS_FLOAT, "SK_SCALAR_IS_FLOAT is false, "
+        "only float scalar is supported");
+
 class SkMatrixGlue {
 public:
 
-    static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
+    // ---------------- Regular JNI -----------------------------
+
+    static void finalizer(jlong objHandle) {
         SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
         delete obj;
     }
 
+    static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) {
+        return static_cast<jlong>(reinterpret_cast<uintptr_t>(&finalizer));
+    }
+
     static jlong create(JNIEnv* env, jobject clazz, jlong srcHandle) {
         const SkMatrix* src = reinterpret_cast<SkMatrix*>(srcHandle);
         SkMatrix* obj = new SkMatrix();
@@ -43,156 +54,39 @@
         return reinterpret_cast<jlong>(obj);
     }
 
-    static jboolean isIdentity(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        return obj->isIdentity() ? JNI_TRUE : JNI_FALSE;
-    }
+    // ---------------- @FastNative -----------------------------
 
-    static jboolean isAffine(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        return obj->asAffine(NULL) ? JNI_TRUE : JNI_FALSE;
-    }
-
-    static jboolean rectStaysRect(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        return obj->rectStaysRect() ? JNI_TRUE : JNI_FALSE;
-    }
-
-    static void reset(JNIEnv* env, jobject clazz, jlong objHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->reset();
-    }
-     static void set(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
-        *obj = *other;
-    }
-     static void setTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setTranslate(dx, dy);
-    }
-     static void setScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setScale(sx, sy, px, py);
-    }
-     static void setScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setScale(sx, sy);
-    }
-     static void setRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setRotate(degrees, px, py);
-    }
-     static void setRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setRotate(degrees);
-    }
-     static void setSinCos__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sinValue, jfloat cosValue, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setSinCos(sinValue, cosValue, px, py);
-    }
-     static void setSinCos__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sinValue, jfloat cosValue) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setSinCos(sinValue, cosValue);
-    }
-     static void setSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setSkew(kx, ky, px, py);
-    }
-     static void setSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->setSkew(kx, ky);
-    }
-     static void setConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong aHandle, jlong bHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle);
-        SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle);
-        obj->setConcat(*a, *b);
-    }
-
-    static void preTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preTranslate(dx, dy);
-    }
-
-    static void preScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preScale(sx, sy, px, py);
-    }
-
-    static void preScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preScale(sx, sy);
-    }
-
-    static void preRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preRotate(degrees, px, py);
-    }
-
-    static void preRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preRotate(degrees);
-    }
-
-    static void preSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preSkew(kx, ky, px, py);
-    }
-
-    static void preSkew__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->preSkew(kx, ky);
-    }
-
-    static void preConcat(JNIEnv* env, jobject clazz, jlong objHandle, jlong otherHandle) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
-        obj->preConcat(*other);
-    }
-
-    static void postTranslate(JNIEnv* env, jobject clazz, jlong objHandle, jfloat dx, jfloat dy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postTranslate(dx, dy);
-    }
-
-    static void postScale__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postScale(sx, sy, px, py);
-    }
-
-    static void postScale__FF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat sx, jfloat sy) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postScale(sx, sy);
-    }
-
-    static void postRotate__FFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postRotate(degrees, px, py);
-    }
-
-    static void postRotate__F(JNIEnv* env, jobject clazz, jlong objHandle, jfloat degrees) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postRotate(degrees);
-    }
-
-    static void postSkew__FFFF(JNIEnv* env, jobject clazz, jlong objHandle, jfloat kx, jfloat ky, jfloat px, jfloat py) {
-        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
-        obj->postSkew(kx, ky, px, py);
-    }
-
-    static void postSkew__FF(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat kx, jfloat ky) {
+    static void mapPoints(JNIEnv* env, jobject clazz, jlong matrixHandle,
+            jfloatArray dst, jint dstIndex, jfloatArray src, jint srcIndex,
+            jint ptCount, jboolean isPts) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        matrix->postSkew(kx, ky);
+        SkASSERT(ptCount >= 0);
+        AutoJavaFloatArray autoSrc(env, src, srcIndex + (ptCount << 1),
+                kRO_JNIAccess);
+        AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1),
+                kRW_JNIAccess);
+        float* srcArray = autoSrc.ptr() + srcIndex;
+        float* dstArray = autoDst.ptr() + dstIndex;
+        if (isPts)
+            matrix->mapPoints((SkPoint*) dstArray, (const SkPoint*) srcArray,
+                    ptCount);
+        else
+            matrix->mapVectors((SkVector*) dstArray, (const SkVector*) srcArray,
+                    ptCount);
     }
 
-    static void postConcat(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong otherHandle) {
+    static jboolean mapRect__RectFRectF(JNIEnv* env, jobject clazz,
+            jlong matrixHandle, jobjectArray dst, jobject src) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
-        matrix->postConcat(*other);
+        SkRect dst_, src_;
+        GraphicsJNI::jrectf_to_rect(env, src, &src_);
+        jboolean rectStaysRect = matrix->mapRect(&dst_, src_);
+        GraphicsJNI::rect_to_jrectf(dst_, env, dst);
+        return rectStaysRect ? JNI_TRUE : JNI_FALSE;
     }
 
-    static jboolean setRectToRect(JNIEnv* env, jobject clazz, jlong matrixHandle, jobject src, jobject dst, jint stfHandle) {
+    static jboolean setRectToRect(JNIEnv* env, jobject clazz,
+            jlong matrixHandle, jobject src, jobject dst, jint stfHandle) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         SkMatrix::ScaleToFit stf = static_cast<SkMatrix::ScaleToFit>(stfHandle);
         SkRect src_;
@@ -202,150 +96,290 @@
         return matrix->setRectToRect(src_, dst_, stf) ? JNI_TRUE : JNI_FALSE;
     }
 
-    static jboolean setPolyToPoly(JNIEnv* env, jobject clazz, jlong matrixHandle,
-                                  jfloatArray jsrc, jint srcIndex,
-                                  jfloatArray jdst, jint dstIndex, jint ptCount) {
+    static jboolean setPolyToPoly(JNIEnv* env, jobject clazz,
+            jlong matrixHandle, jfloatArray jsrc, jint srcIndex,
+            jfloatArray jdst, jint dstIndex, jint ptCount) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         SkASSERT(srcIndex >= 0);
         SkASSERT(dstIndex >= 0);
-        SkASSERT((unsigned)ptCount <= 4);
+        SkASSERT((unsigned )ptCount <= 4);
 
-        AutoJavaFloatArray autoSrc(env, jsrc, srcIndex + (ptCount << 1), kRO_JNIAccess);
-        AutoJavaFloatArray autoDst(env, jdst, dstIndex + (ptCount << 1), kRW_JNIAccess);
+        AutoJavaFloatArray autoSrc(env, jsrc, srcIndex + (ptCount << 1),
+                kRO_JNIAccess);
+        AutoJavaFloatArray autoDst(env, jdst, dstIndex + (ptCount << 1),
+                kRW_JNIAccess);
         float* src = autoSrc.ptr() + srcIndex;
         float* dst = autoDst.ptr() + dstIndex;
         bool result;
 
-#ifdef SK_SCALAR_IS_FLOAT
-        result = matrix->setPolyToPoly((const SkPoint*)src, (const SkPoint*)dst,
-                                     ptCount);
-#else
-        SkASSERT(false);
-#endif
+        result = matrix->setPolyToPoly((const SkPoint*) src,
+                (const SkPoint*) dst, ptCount);
         return result ? JNI_TRUE : JNI_FALSE;
     }
 
-    static jboolean invert(JNIEnv* env, jobject clazz, jlong matrixHandle, jlong inverseHandle) {
+    static void getValues(JNIEnv* env, jobject clazz, jlong matrixHandle,
+            jfloatArray values) {
+        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+        AutoJavaFloatArray autoValues(env, values, 9, kRW_JNIAccess);
+        float* dst = autoValues.ptr();
+        for (int i = 0; i < 9; i++) {
+            dst[i] = matrix->get(i);
+        }
+    }
+
+    static void setValues(JNIEnv* env, jobject clazz, jlong matrixHandle,
+            jfloatArray values) {
+        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+        AutoJavaFloatArray autoValues(env, values, 9, kRO_JNIAccess);
+        const float* src = autoValues.ptr();
+
+        for (int i = 0; i < 9; i++) {
+            matrix->set(i, src[i]);
+        }
+    }
+
+    // ---------------- @CriticalNative -----------------------------
+
+    static jboolean isIdentity(jlong objHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        return obj->isIdentity() ? JNI_TRUE : JNI_FALSE;
+    }
+
+    static jboolean isAffine(jlong objHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        return obj->asAffine(NULL) ? JNI_TRUE : JNI_FALSE;
+    }
+
+    static jboolean rectStaysRect(jlong objHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        return obj->rectStaysRect() ? JNI_TRUE : JNI_FALSE;
+    }
+
+    static void reset(jlong objHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->reset();
+    }
+
+    static void set(jlong objHandle, jlong otherHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
+        *obj = *other;
+    }
+
+    static void setTranslate(jlong objHandle, jfloat dx, jfloat dy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setTranslate(dx, dy);
+    }
+
+    static void setScale__FFFF(jlong objHandle, jfloat sx, jfloat sy, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setScale(sx, sy, px, py);
+    }
+
+    static void setScale__FF(jlong objHandle, jfloat sx, jfloat sy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setScale(sx, sy);
+    }
+
+    static void setRotate__FFF(jlong objHandle, jfloat degrees, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setRotate(degrees, px, py);
+    }
+
+    static void setRotate__F(jlong objHandle, jfloat degrees) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setRotate(degrees);
+    }
+
+    static void setSinCos__FFFF(jlong objHandle, jfloat sinValue,
+            jfloat cosValue, jfloat px, jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setSinCos(sinValue, cosValue, px, py);
+    }
+
+    static void setSinCos__FF(jlong objHandle, jfloat sinValue,
+            jfloat cosValue) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setSinCos(sinValue, cosValue);
+    }
+
+    static void setSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setSkew(kx, ky, px, py);
+    }
+
+    static void setSkew__FF(jlong objHandle, jfloat kx, jfloat ky) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->setSkew(kx, ky);
+    }
+
+    static void setConcat(jlong objHandle, jlong aHandle, jlong bHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle);
+        SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle);
+        obj->setConcat(*a, *b);
+    }
+
+    static void preTranslate(jlong objHandle, jfloat dx, jfloat dy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preTranslate(dx, dy);
+    }
+
+    static void preScale__FFFF(jlong objHandle, jfloat sx, jfloat sy, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preScale(sx, sy, px, py);
+    }
+
+    static void preScale__FF(jlong objHandle, jfloat sx, jfloat sy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preScale(sx, sy);
+    }
+
+    static void preRotate__FFF(jlong objHandle, jfloat degrees, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preRotate(degrees, px, py);
+    }
+
+    static void preRotate__F(jlong objHandle, jfloat degrees) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preRotate(degrees);
+    }
+
+    static void preSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preSkew(kx, ky, px, py);
+    }
+
+    static void preSkew__FF(jlong objHandle, jfloat kx, jfloat ky) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->preSkew(kx, ky);
+    }
+
+    static void preConcat(jlong objHandle, jlong otherHandle) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
+        obj->preConcat(*other);
+    }
+
+    static void postTranslate(jlong objHandle, jfloat dx, jfloat dy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postTranslate(dx, dy);
+    }
+
+    static void postScale__FFFF(jlong objHandle, jfloat sx, jfloat sy,
+            jfloat px, jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postScale(sx, sy, px, py);
+    }
+
+    static void postScale__FF(jlong objHandle, jfloat sx, jfloat sy) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postScale(sx, sy);
+    }
+
+    static void postRotate__FFF(jlong objHandle, jfloat degrees, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postRotate(degrees, px, py);
+    }
+
+    static void postRotate__F(jlong objHandle, jfloat degrees) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postRotate(degrees);
+    }
+
+    static void postSkew__FFFF(jlong objHandle, jfloat kx, jfloat ky, jfloat px,
+            jfloat py) {
+        SkMatrix* obj = reinterpret_cast<SkMatrix*>(objHandle);
+        obj->postSkew(kx, ky, px, py);
+    }
+
+    static void postSkew__FF(jlong matrixHandle, jfloat kx, jfloat ky) {
+        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+        matrix->postSkew(kx, ky);
+    }
+
+    static void postConcat(jlong matrixHandle, jlong otherHandle) {
+        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+        SkMatrix* other = reinterpret_cast<SkMatrix*>(otherHandle);
+        matrix->postConcat(*other);
+    }
+
+    static jboolean invert(jlong matrixHandle, jlong inverseHandle) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         SkMatrix* inverse = reinterpret_cast<SkMatrix*>(inverseHandle);
         return matrix->invert(inverse);
     }
 
-    static void mapPoints(JNIEnv* env, jobject clazz, jlong matrixHandle,
-                              jfloatArray dst, jint dstIndex,
-                              jfloatArray src, jint srcIndex,
-                              jint ptCount, jboolean isPts) {
-        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        SkASSERT(ptCount >= 0);
-        AutoJavaFloatArray autoSrc(env, src, srcIndex + (ptCount << 1), kRO_JNIAccess);
-        AutoJavaFloatArray autoDst(env, dst, dstIndex + (ptCount << 1), kRW_JNIAccess);
-        float* srcArray = autoSrc.ptr() + srcIndex;
-        float* dstArray = autoDst.ptr() + dstIndex;
-#ifdef SK_SCALAR_IS_FLOAT
-        if (isPts)
-            matrix->mapPoints((SkPoint*)dstArray, (const SkPoint*)srcArray,
-                              ptCount);
-        else
-            matrix->mapVectors((SkVector*)dstArray, (const SkVector*)srcArray,
-                               ptCount);
-#else
-        SkASSERT(false);
-#endif
-    }
-
-    static jboolean mapRect__RectFRectF(JNIEnv* env, jobject clazz, jlong matrixHandle, jobjectArray dst, jobject src) {
-        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        SkRect dst_, src_;
-        GraphicsJNI::jrectf_to_rect(env, src, &src_);
-        jboolean rectStaysRect = matrix->mapRect(&dst_, src_);
-        GraphicsJNI::rect_to_jrectf(dst_, env, dst);
-        return rectStaysRect ? JNI_TRUE : JNI_FALSE;
-    }
-
-    static jfloat mapRadius(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloat radius) {
+    static jfloat mapRadius(jlong matrixHandle, jfloat radius) {
         SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
         float result;
         result = SkScalarToFloat(matrix->mapRadius(radius));
         return static_cast<jfloat>(result);
     }
-    static void getValues(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloatArray values) {
-        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        AutoJavaFloatArray autoValues(env, values, 9, kRW_JNIAccess);
-        float* dst = autoValues.ptr();
-#ifdef SK_SCALAR_IS_FLOAT
-        for (int i = 0; i < 9; i++) {
-            dst[i] = matrix->get(i);
-        }
-#else
-        SkASSERT(false);
-#endif
-    }
 
-    static void setValues(JNIEnv* env, jobject clazz, jlong matrixHandle, jfloatArray values) {
-        SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-        AutoJavaFloatArray autoValues(env, values, 9, kRO_JNIAccess);
-        const float* src = autoValues.ptr();
-
-#ifdef SK_SCALAR_IS_FLOAT
-        for (int i = 0; i < 9; i++) {
-            matrix->set(i, src[i]);
-        }
-#else
-        SkASSERT(false);
-#endif
-    }
-
-    static jboolean equals(JNIEnv* env, jobject clazz, jlong aHandle, jlong bHandle) {
+    static jboolean equals(jlong aHandle, jlong bHandle) {
         const SkMatrix* a = reinterpret_cast<SkMatrix*>(aHandle);
         const SkMatrix* b = reinterpret_cast<SkMatrix*>(bHandle);
         return *a == *b;
     }
- };
+};
 
 static const JNINativeMethod methods[] = {
-    {"finalizer", "(J)V", (void*) SkMatrixGlue::finalizer},
-    {"native_create","(J)J", (void*) SkMatrixGlue::create},
+    {"nGetNativeFinalizer", "()J", (void*) SkMatrixGlue::getNativeFinalizer},
+    {"nCreate","(J)J", (void*) SkMatrixGlue::create},
 
-    {"native_isIdentity","!(J)Z", (void*) SkMatrixGlue::isIdentity},
-    {"native_isAffine","!(J)Z", (void*) SkMatrixGlue::isAffine},
-    {"native_rectStaysRect","!(J)Z", (void*) SkMatrixGlue::rectStaysRect},
-    {"native_reset","!(J)V", (void*) SkMatrixGlue::reset},
-    {"native_set","!(JJ)V", (void*) SkMatrixGlue::set},
-    {"native_setTranslate","!(JFF)V", (void*) SkMatrixGlue::setTranslate},
-    {"native_setScale","!(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF},
-    {"native_setScale","!(JFF)V", (void*) SkMatrixGlue::setScale__FF},
-    {"native_setRotate","!(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF},
-    {"native_setRotate","!(JF)V", (void*) SkMatrixGlue::setRotate__F},
-    {"native_setSinCos","!(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF},
-    {"native_setSinCos","!(JFF)V", (void*) SkMatrixGlue::setSinCos__FF},
-    {"native_setSkew","!(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF},
-    {"native_setSkew","!(JFF)V", (void*) SkMatrixGlue::setSkew__FF},
-    {"native_setConcat","!(JJJ)V", (void*) SkMatrixGlue::setConcat},
-    {"native_preTranslate","!(JFF)V", (void*) SkMatrixGlue::preTranslate},
-    {"native_preScale","!(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF},
-    {"native_preScale","!(JFF)V", (void*) SkMatrixGlue::preScale__FF},
-    {"native_preRotate","!(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF},
-    {"native_preRotate","!(JF)V", (void*) SkMatrixGlue::preRotate__F},
-    {"native_preSkew","!(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF},
-    {"native_preSkew","!(JFF)V", (void*) SkMatrixGlue::preSkew__FF},
-    {"native_preConcat","!(JJ)V", (void*) SkMatrixGlue::preConcat},
-    {"native_postTranslate","!(JFF)V", (void*) SkMatrixGlue::postTranslate},
-    {"native_postScale","!(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF},
-    {"native_postScale","!(JFF)V", (void*) SkMatrixGlue::postScale__FF},
-    {"native_postRotate","!(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF},
-    {"native_postRotate","!(JF)V", (void*) SkMatrixGlue::postRotate__F},
-    {"native_postSkew","!(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF},
-    {"native_postSkew","!(JFF)V", (void*) SkMatrixGlue::postSkew__FF},
-    {"native_postConcat","!(JJ)V", (void*) SkMatrixGlue::postConcat},
-    {"native_setRectToRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z", (void*) SkMatrixGlue::setRectToRect},
-    {"native_setPolyToPoly","!(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly},
-    {"native_invert","!(JJ)Z", (void*) SkMatrixGlue::invert},
-    {"native_mapPoints","!(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints},
-    {"native_mapRect","!(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z", (void*) SkMatrixGlue::mapRect__RectFRectF},
-    {"native_mapRadius","!(JF)F", (void*) SkMatrixGlue::mapRadius},
-    {"native_getValues","!(J[F)V", (void*) SkMatrixGlue::getValues},
-    {"native_setValues","!(J[F)V", (void*) SkMatrixGlue::setValues},
-    {"native_equals", "!(JJ)Z", (void*) SkMatrixGlue::equals}
+    // ------- @FastNative below here ---------------
+    {"nMapPoints","(J[FI[FIIZ)V", (void*) SkMatrixGlue::mapPoints},
+    {"nMapRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;)Z",
+            (void*) SkMatrixGlue::mapRect__RectFRectF},
+    {"nSetRectToRect","(JLandroid/graphics/RectF;Landroid/graphics/RectF;I)Z",
+            (void*) SkMatrixGlue::setRectToRect},
+    {"nSetPolyToPoly","(J[FI[FII)Z", (void*) SkMatrixGlue::setPolyToPoly},
+    {"nGetValues","(J[F)V", (void*) SkMatrixGlue::getValues},
+    {"nSetValues","(J[F)V", (void*) SkMatrixGlue::setValues},
+
+    // ------- @CriticalNative below here ---------------
+    {"nIsIdentity","(J)Z", (void*) SkMatrixGlue::isIdentity},
+    {"nIsAffine","(J)Z", (void*) SkMatrixGlue::isAffine},
+    {"nRectStaysRect","(J)Z", (void*) SkMatrixGlue::rectStaysRect},
+    {"nReset","(J)V", (void*) SkMatrixGlue::reset},
+    {"nSet","(JJ)V", (void*) SkMatrixGlue::set},
+    {"nSetTranslate","(JFF)V", (void*) SkMatrixGlue::setTranslate},
+    {"nSetScale","(JFFFF)V", (void*) SkMatrixGlue::setScale__FFFF},
+    {"nSetScale","(JFF)V", (void*) SkMatrixGlue::setScale__FF},
+    {"nSetRotate","(JFFF)V", (void*) SkMatrixGlue::setRotate__FFF},
+    {"nSetRotate","(JF)V", (void*) SkMatrixGlue::setRotate__F},
+    {"nSetSinCos","(JFFFF)V", (void*) SkMatrixGlue::setSinCos__FFFF},
+    {"nSetSinCos","(JFF)V", (void*) SkMatrixGlue::setSinCos__FF},
+    {"nSetSkew","(JFFFF)V", (void*) SkMatrixGlue::setSkew__FFFF},
+    {"nSetSkew","(JFF)V", (void*) SkMatrixGlue::setSkew__FF},
+    {"nSetConcat","(JJJ)V", (void*) SkMatrixGlue::setConcat},
+    {"nPreTranslate","(JFF)V", (void*) SkMatrixGlue::preTranslate},
+    {"nPreScale","(JFFFF)V", (void*) SkMatrixGlue::preScale__FFFF},
+    {"nPreScale","(JFF)V", (void*) SkMatrixGlue::preScale__FF},
+    {"nPreRotate","(JFFF)V", (void*) SkMatrixGlue::preRotate__FFF},
+    {"nPreRotate","(JF)V", (void*) SkMatrixGlue::preRotate__F},
+    {"nPreSkew","(JFFFF)V", (void*) SkMatrixGlue::preSkew__FFFF},
+    {"nPreSkew","(JFF)V", (void*) SkMatrixGlue::preSkew__FF},
+    {"nPreConcat","(JJ)V", (void*) SkMatrixGlue::preConcat},
+    {"nPostTranslate","(JFF)V", (void*) SkMatrixGlue::postTranslate},
+    {"nPostScale","(JFFFF)V", (void*) SkMatrixGlue::postScale__FFFF},
+    {"nPostScale","(JFF)V", (void*) SkMatrixGlue::postScale__FF},
+    {"nPostRotate","(JFFF)V", (void*) SkMatrixGlue::postRotate__FFF},
+    {"nPostRotate","(JF)V", (void*) SkMatrixGlue::postRotate__F},
+    {"nPostSkew","(JFFFF)V", (void*) SkMatrixGlue::postSkew__FFFF},
+    {"nPostSkew","(JFF)V", (void*) SkMatrixGlue::postSkew__FF},
+    {"nPostConcat","(JJ)V", (void*) SkMatrixGlue::postConcat},
+    {"nInvert","(JJ)Z", (void*) SkMatrixGlue::invert},
+    {"nMapRadius","(JF)F", (void*) SkMatrixGlue::mapRadius},
+    {"nEquals", "(JJ)Z", (void*) SkMatrixGlue::equals}
 };
 
 static jfieldID sNativeInstanceField;
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 1e8f11b..35cedae 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -16,8 +16,12 @@
 
 package android.graphics;
 
-import java.io.PrintWriter;
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
 
+import libcore.util.NativeAllocationRegistry;
+
+import java.io.PrintWriter;
 
 /**
  * The Matrix class holds a 3x3 matrix for transforming coordinates.
@@ -216,352 +220,345 @@
         }
     };
 
+    // sizeof(SkMatrix) is 9 * sizeof(float) + uint32_t
+    private static final long NATIVE_ALLOCATION_SIZE = 40;
+
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                Matrix.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+    }
+
     /**
      * @hide
      */
-    public long native_instance;
+    public final long native_instance;
 
     /**
      * Create an identity matrix
      */
     public Matrix() {
-        native_instance = native_create(0);
+        native_instance = nCreate(0);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
     }
 
     /**
      * Create a matrix that is a (deep) copy of src
+     *
      * @param src The matrix to copy into this matrix
      */
     public Matrix(Matrix src) {
-        native_instance = native_create(src != null ? src.native_instance : 0);
+        native_instance = nCreate(src != null ? src.native_instance : 0);
+        NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance);
     }
 
     /**
-     * Returns true if the matrix is identity.
-     * This maybe faster than testing if (getType() == 0)
+     * Returns true if the matrix is identity. This maybe faster than testing if (getType() == 0)
      */
     public boolean isIdentity() {
-        return native_isIdentity(native_instance);
+        return nIsIdentity(native_instance);
     }
 
     /**
-     * Gets whether this matrix is affine. An affine matrix preserves
-     * straight lines and has no perspective.
+     * Gets whether this matrix is affine. An affine matrix preserves straight lines and has no
+     * perspective.
      *
      * @return Whether the matrix is affine.
      */
     public boolean isAffine() {
-        return native_isAffine(native_instance);
+        return nIsAffine(native_instance);
     }
 
     /**
-     * Returns true if will map a rectangle to another rectangle. This can be
-     * true if the matrix is identity, scale-only, or rotates a multiple of 90
-     * degrees.
+     * Returns true if will map a rectangle to another rectangle. This can be true if the matrix is
+     * identity, scale-only, or rotates a multiple of 90 degrees.
      */
     public boolean rectStaysRect() {
-        return native_rectStaysRect(native_instance);
+        return nRectStaysRect(native_instance);
     }
 
     /**
-     * (deep) copy the src matrix into this matrix. If src is null, reset this
-     * matrix to the identity matrix.
+     * (deep) copy the src matrix into this matrix. If src is null, reset this matrix to the
+     * identity matrix.
      */
     public void set(Matrix src) {
         if (src == null) {
             reset();
         } else {
-            native_set(native_instance, src.native_instance);
+            nSet(native_instance, src.native_instance);
         }
     }
 
-    /** Returns true iff obj is a Matrix and its values equal our values.
-    */
+    /**
+     * Returns true iff obj is a Matrix and its values equal our values.
+     */
     @Override
     public boolean equals(Object obj) {
-        //if (obj == this) return true;     -- NaN value would mean matrix != itself
-        if (!(obj instanceof Matrix)) return false;
-        return native_equals(native_instance, ((Matrix)obj).native_instance);
+        // if (obj == this) return true; -- NaN value would mean matrix != itself
+        if (!(obj instanceof Matrix)) {
+            return false;
+        }
+        return nEquals(native_instance, ((Matrix) obj).native_instance);
     }
 
     @Override
     public int hashCode() {
         // This should generate the hash code by performing some arithmetic operation on all
         // the matrix elements -- our equals() does an element-by-element comparison, and we
-        // need to ensure that the hash code for two equal objects is the same.  We're not
+        // need to ensure that the hash code for two equal objects is the same. We're not
         // really using this at the moment, so we take the easy way out.
         return 44;
     }
 
     /** Set the matrix to identity */
     public void reset() {
-        native_reset(native_instance);
+        nReset(native_instance);
     }
 
     /** Set the matrix to translate by (dx, dy). */
     public void setTranslate(float dx, float dy) {
-        native_setTranslate(native_instance, dx, dy);
+        nSetTranslate(native_instance, dx, dy);
     }
 
     /**
-     * Set the matrix to scale by sx and sy, with a pivot point at (px, py).
-     * The pivot point is the coordinate that should remain unchanged by the
-     * specified transformation.
+     * Set the matrix to scale by sx and sy, with a pivot point at (px, py). The pivot point is the
+     * coordinate that should remain unchanged by the specified transformation.
      */
     public void setScale(float sx, float sy, float px, float py) {
-        native_setScale(native_instance, sx, sy, px, py);
+        nSetScale(native_instance, sx, sy, px, py);
     }
 
     /** Set the matrix to scale by sx and sy. */
     public void setScale(float sx, float sy) {
-        native_setScale(native_instance, sx, sy);
+        nSetScale(native_instance, sx, sy);
     }
 
     /**
-     * Set the matrix to rotate by the specified number of degrees, with a pivot
-     * point at (px, py). The pivot point is the coordinate that should remain
-     * unchanged by the specified transformation.
+     * Set the matrix to rotate by the specified number of degrees, with a pivot point at (px, py).
+     * The pivot point is the coordinate that should remain unchanged by the specified
+     * transformation.
      */
     public void setRotate(float degrees, float px, float py) {
-        native_setRotate(native_instance, degrees, px, py);
+        nSetRotate(native_instance, degrees, px, py);
     }
 
     /**
      * Set the matrix to rotate about (0,0) by the specified number of degrees.
      */
     public void setRotate(float degrees) {
-        native_setRotate(native_instance, degrees);
+        nSetRotate(native_instance, degrees);
     }
 
     /**
-     * Set the matrix to rotate by the specified sine and cosine values, with a
-     * pivot point at (px, py). The pivot point is the coordinate that should
-     * remain unchanged by the specified transformation.
+     * Set the matrix to rotate by the specified sine and cosine values, with a pivot point at (px,
+     * py). The pivot point is the coordinate that should remain unchanged by the specified
+     * transformation.
      */
     public void setSinCos(float sinValue, float cosValue, float px, float py) {
-        native_setSinCos(native_instance, sinValue, cosValue, px, py);
+        nSetSinCos(native_instance, sinValue, cosValue, px, py);
     }
 
     /** Set the matrix to rotate by the specified sine and cosine values. */
     public void setSinCos(float sinValue, float cosValue) {
-        native_setSinCos(native_instance, sinValue, cosValue);
+        nSetSinCos(native_instance, sinValue, cosValue);
     }
 
     /**
-     * Set the matrix to skew by sx and sy, with a pivot point at (px, py).
-     * The pivot point is the coordinate that should remain unchanged by the
-     * specified transformation.
+     * Set the matrix to skew by sx and sy, with a pivot point at (px, py). The pivot point is the
+     * coordinate that should remain unchanged by the specified transformation.
      */
     public void setSkew(float kx, float ky, float px, float py) {
-        native_setSkew(native_instance, kx, ky, px, py);
+        nSetSkew(native_instance, kx, ky, px, py);
     }
 
     /** Set the matrix to skew by sx and sy. */
     public void setSkew(float kx, float ky) {
-        native_setSkew(native_instance, kx, ky);
+        nSetSkew(native_instance, kx, ky);
     }
 
     /**
-     * Set the matrix to the concatenation of the two specified matrices and
-     * return true.
-     *
-     * <p>Either of the two matrices may also be the target matrix, that is
-     * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.</p>
-     *
-     * <p class="note">In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this
-     * function returns true only if the result can be represented. In
-     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true.</p>
+     * Set the matrix to the concatenation of the two specified matrices and return true.
+     * <p>
+     * Either of the two matrices may also be the target matrix, that is
+     * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid.
+     * </p>
+     * <p class="note">
+     * In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this function returns
+     * true only if the result can be represented. In
+     * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true.
+     * </p>
      */
     public boolean setConcat(Matrix a, Matrix b) {
-        native_setConcat(native_instance, a.native_instance, b.native_instance);
+        nSetConcat(native_instance, a.native_instance, b.native_instance);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified translation.
-     * M' = M * T(dx, dy)
+     * Preconcats the matrix with the specified translation. M' = M * T(dx, dy)
      */
     public boolean preTranslate(float dx, float dy) {
-        native_preTranslate(native_instance, dx, dy);
+        nPreTranslate(native_instance, dx, dy);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified scale.
-     * M' = M * S(sx, sy, px, py)
+     * Preconcats the matrix with the specified scale. M' = M * S(sx, sy, px, py)
      */
     public boolean preScale(float sx, float sy, float px, float py) {
-        native_preScale(native_instance, sx, sy, px, py);
+        nPreScale(native_instance, sx, sy, px, py);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified scale.
-     * M' = M * S(sx, sy)
+     * Preconcats the matrix with the specified scale. M' = M * S(sx, sy)
      */
     public boolean preScale(float sx, float sy) {
-        native_preScale(native_instance, sx, sy);
+        nPreScale(native_instance, sx, sy);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified rotation.
-     * M' = M * R(degrees, px, py)
+     * Preconcats the matrix with the specified rotation. M' = M * R(degrees, px, py)
      */
     public boolean preRotate(float degrees, float px, float py) {
-        native_preRotate(native_instance, degrees, px, py);
+        nPreRotate(native_instance, degrees, px, py);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified rotation.
-     * M' = M * R(degrees)
+     * Preconcats the matrix with the specified rotation. M' = M * R(degrees)
      */
     public boolean preRotate(float degrees) {
-        native_preRotate(native_instance, degrees);
+        nPreRotate(native_instance, degrees);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified skew.
-     * M' = M * K(kx, ky, px, py)
+     * Preconcats the matrix with the specified skew. M' = M * K(kx, ky, px, py)
      */
     public boolean preSkew(float kx, float ky, float px, float py) {
-        native_preSkew(native_instance, kx, ky, px, py);
+        nPreSkew(native_instance, kx, ky, px, py);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified skew.
-     * M' = M * K(kx, ky)
+     * Preconcats the matrix with the specified skew. M' = M * K(kx, ky)
      */
     public boolean preSkew(float kx, float ky) {
-        native_preSkew(native_instance, kx, ky);
+        nPreSkew(native_instance, kx, ky);
         return true;
     }
 
     /**
-     * Preconcats the matrix with the specified matrix.
-     * M' = M * other
+     * Preconcats the matrix with the specified matrix. M' = M * other
      */
     public boolean preConcat(Matrix other) {
-        native_preConcat(native_instance, other.native_instance);
+        nPreConcat(native_instance, other.native_instance);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified translation.
-     * M' = T(dx, dy) * M
+     * Postconcats the matrix with the specified translation. M' = T(dx, dy) * M
      */
     public boolean postTranslate(float dx, float dy) {
-        native_postTranslate(native_instance, dx, dy);
+        nPostTranslate(native_instance, dx, dy);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified scale.
-     * M' = S(sx, sy, px, py) * M
+     * Postconcats the matrix with the specified scale. M' = S(sx, sy, px, py) * M
      */
     public boolean postScale(float sx, float sy, float px, float py) {
-        native_postScale(native_instance, sx, sy, px, py);
+        nPostScale(native_instance, sx, sy, px, py);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified scale.
-     * M' = S(sx, sy) * M
+     * Postconcats the matrix with the specified scale. M' = S(sx, sy) * M
      */
     public boolean postScale(float sx, float sy) {
-        native_postScale(native_instance, sx, sy);
+        nPostScale(native_instance, sx, sy);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified rotation.
-     * M' = R(degrees, px, py) * M
+     * Postconcats the matrix with the specified rotation. M' = R(degrees, px, py) * M
      */
     public boolean postRotate(float degrees, float px, float py) {
-        native_postRotate(native_instance, degrees, px, py);
+        nPostRotate(native_instance, degrees, px, py);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified rotation.
-     * M' = R(degrees) * M
+     * Postconcats the matrix with the specified rotation. M' = R(degrees) * M
      */
     public boolean postRotate(float degrees) {
-        native_postRotate(native_instance, degrees);
+        nPostRotate(native_instance, degrees);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified skew.
-     * M' = K(kx, ky, px, py) * M
+     * Postconcats the matrix with the specified skew. M' = K(kx, ky, px, py) * M
      */
     public boolean postSkew(float kx, float ky, float px, float py) {
-        native_postSkew(native_instance, kx, ky, px, py);
+        nPostSkew(native_instance, kx, ky, px, py);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified skew.
-     * M' = K(kx, ky) * M
+     * Postconcats the matrix with the specified skew. M' = K(kx, ky) * M
      */
     public boolean postSkew(float kx, float ky) {
-        native_postSkew(native_instance, kx, ky);
+        nPostSkew(native_instance, kx, ky);
         return true;
     }
 
     /**
-     * Postconcats the matrix with the specified matrix.
-     * M' = other * M
+     * Postconcats the matrix with the specified matrix. M' = other * M
      */
     public boolean postConcat(Matrix other) {
-        native_postConcat(native_instance, other.native_instance);
+        nPostConcat(native_instance, other.native_instance);
         return true;
     }
 
-    /** Controlls how the src rect should align into the dst rect for
-        setRectToRect().
-    */
+    /**
+     * Controlls how the src rect should align into the dst rect for setRectToRect().
+     */
     public enum ScaleToFit {
         /**
-         * Scale in X and Y independently, so that src matches dst exactly.
-         * This may change the aspect ratio of the src.
+         * Scale in X and Y independently, so that src matches dst exactly. This may change the
+         * aspect ratio of the src.
          */
-        FILL    (0),
+        FILL(0),
         /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. START aligns the result to the
-         * left and top edges of dst.
+         * Compute a scale that will maintain the original src aspect ratio, but will also ensure
+         * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. START
+         * aligns the result to the left and top edges of dst.
          */
-        START   (1),
+        START(1),
         /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. The result is centered inside dst.
+         * Compute a scale that will maintain the original src aspect ratio, but will also ensure
+         * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. The
+         * result is centered inside dst.
          */
-        CENTER  (2),
+        CENTER(2),
         /**
-         * Compute a scale that will maintain the original src aspect ratio,
-         * but will also ensure that src fits entirely inside dst. At least one
-         * axis (X or Y) will fit exactly. END aligns the result to the
-         * right and bottom edges of dst.
+         * Compute a scale that will maintain the original src aspect ratio, but will also ensure
+         * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. END
+         * aligns the result to the right and bottom edges of dst.
          */
-        END     (3);
+        END(3);
 
         // the native values must match those in SkMatrix.h
         ScaleToFit(int nativeInt) {
             this.nativeInt = nativeInt;
         }
+
         final int nativeInt;
     }
 
     /**
-     * Set the matrix to the scale and translate values that map the source
-     * rectangle to the destination rectangle, returning true if the the result
-     * can be represented.
+     * Set the matrix to the scale and translate values that map the source rectangle to the
+     * destination rectangle, returning true if the the result can be represented.
      *
      * @param src the source rectangle to map from.
      * @param dst the destination rectangle to map to.
@@ -572,13 +569,13 @@
         if (dst == null || src == null) {
             throw new NullPointerException();
         }
-        return native_setRectToRect(native_instance, src, dst, stf.nativeInt);
+        return nSetRectToRect(native_instance, src, dst, stf.nativeInt);
     }
 
     // private helper to perform range checks on arrays of "points"
     private static void checkPointArrays(float[] src, int srcIndex,
-                                         float[] dst, int dstIndex,
-                                         int pointCount) {
+            float[] dst, int dstIndex,
+            int pointCount) {
         // check for too-small and too-big indices
         int srcStop = srcIndex + (pointCount << 1);
         int dstStop = dstIndex + (pointCount << 1);
@@ -589,84 +586,81 @@
     }
 
     /**
-     * Set the matrix such that the specified src points would map to the
-     * specified dst points. The "points" are represented as an array of floats,
-     * order [x0, y0, x1, y1, ...], where each "point" is 2 float values.
+     * Set the matrix such that the specified src points would map to the specified dst points. The
+     * "points" are represented as an array of floats, order [x0, y0, x1, y1, ...], where each
+     * "point" is 2 float values.
      *
-     * @param src   The array of src [x,y] pairs (points)
+     * @param src The array of src [x,y] pairs (points)
      * @param srcIndex Index of the first pair of src values
-     * @param dst   The array of dst [x,y] pairs (points)
+     * @param dst The array of dst [x,y] pairs (points)
      * @param dstIndex Index of the first pair of dst values
      * @param pointCount The number of pairs/points to be used. Must be [0..4]
      * @return true if the matrix was set to the specified transformation
      */
     public boolean setPolyToPoly(float[] src, int srcIndex,
-                                 float[] dst, int dstIndex,
-                                 int pointCount) {
+            float[] dst, int dstIndex,
+            int pointCount) {
         if (pointCount > 4) {
             throw new IllegalArgumentException();
         }
         checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
-        return native_setPolyToPoly(native_instance, src, srcIndex,
-                                    dst, dstIndex, pointCount);
+        return nSetPolyToPoly(native_instance, src, srcIndex,
+                dst, dstIndex, pointCount);
     }
 
     /**
-     * If this matrix can be inverted, return true and if inverse is not null,
-     * set inverse to be the inverse of this matrix. If this matrix cannot be
-     * inverted, ignore inverse and return false.
+     * If this matrix can be inverted, return true and if inverse is not null, set inverse to be the
+     * inverse of this matrix. If this matrix cannot be inverted, ignore inverse and return false.
      */
     public boolean invert(Matrix inverse) {
-        return native_invert(native_instance, inverse.native_instance);
+        return nInvert(native_instance, inverse.native_instance);
     }
 
     /**
-    * Apply this matrix to the array of 2D points specified by src, and write
-     * the transformed points into the array of points specified by dst. The
-     * two arrays represent their "points" as pairs of floats [x, y].
+     * Apply this matrix to the array of 2D points specified by src, and write the transformed
+     * points into the array of points specified by dst. The two arrays represent their "points" as
+     * pairs of floats [x, y].
      *
-     * @param dst   The array of dst points (x,y pairs)
+     * @param dst The array of dst points (x,y pairs)
      * @param dstIndex The index of the first [x,y] pair of dst floats
-     * @param src   The array of src points (x,y pairs)
+     * @param src The array of src points (x,y pairs)
      * @param srcIndex The index of the first [x,y] pair of src floats
      * @param pointCount The number of points (x,y pairs) to transform
      */
     public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
-                          int pointCount) {
+            int pointCount) {
         checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
-        native_mapPoints(native_instance, dst, dstIndex, src, srcIndex,
-                         pointCount, true);
+        nMapPoints(native_instance, dst, dstIndex, src, srcIndex,
+                pointCount, true);
     }
 
     /**
-    * Apply this matrix to the array of 2D vectors specified by src, and write
-     * the transformed vectors into the array of vectors specified by dst. The
-     * two arrays represent their "vectors" as pairs of floats [x, y].
+     * Apply this matrix to the array of 2D vectors specified by src, and write the transformed
+     * vectors into the array of vectors specified by dst. The two arrays represent their "vectors"
+     * as pairs of floats [x, y]. Note: this method does not apply the translation associated with
+     * the matrix. Use {@link Matrix#mapPoints(float[], int, float[], int, int)} if you want the
+     * translation to be applied.
      *
-     * Note: this method does not apply the translation associated with the matrix. Use
-     * {@link Matrix#mapPoints(float[], int, float[], int, int)} if you want the translation
-     * to be applied.
-     *
-     * @param dst   The array of dst vectors (x,y pairs)
+     * @param dst The array of dst vectors (x,y pairs)
      * @param dstIndex The index of the first [x,y] pair of dst floats
-     * @param src   The array of src vectors (x,y pairs)
+     * @param src The array of src vectors (x,y pairs)
      * @param srcIndex The index of the first [x,y] pair of src floats
      * @param vectorCount The number of vectors (x,y pairs) to transform
      */
     public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex,
-                          int vectorCount) {
+            int vectorCount) {
         checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount);
-        native_mapPoints(native_instance, dst, dstIndex, src, srcIndex,
-                         vectorCount, false);
+        nMapPoints(native_instance, dst, dstIndex, src, srcIndex,
+                vectorCount, false);
     }
 
     /**
-     * Apply this matrix to the array of 2D points specified by src, and write
-     * the transformed points into the array of points specified by dst. The
-     * two arrays represent their "points" as pairs of floats [x, y].
+     * Apply this matrix to the array of 2D points specified by src, and write the transformed
+     * points into the array of points specified by dst. The two arrays represent their "points" as
+     * pairs of floats [x, y].
      *
-     * @param dst   The array of dst points (x,y pairs)
-     * @param src   The array of src points (x,y pairs)
+     * @param dst The array of dst points (x,y pairs)
+     * @param src The array of src points (x,y pairs)
      */
     public void mapPoints(float[] dst, float[] src) {
         if (dst.length != src.length) {
@@ -676,15 +670,14 @@
     }
 
     /**
-     * Apply this matrix to the array of 2D vectors specified by src, and write
-     * the transformed vectors into the array of vectors specified by dst. The
-     * two arrays represent their "vectors" as pairs of floats [x, y].
+     * Apply this matrix to the array of 2D vectors specified by src, and write the transformed
+     * vectors into the array of vectors specified by dst. The two arrays represent their "vectors"
+     * as pairs of floats [x, y]. Note: this method does not apply the translation associated with
+     * the matrix. Use {@link Matrix#mapPoints(float[], float[])} if you want the translation to be
+     * applied.
      *
-     * Note: this method does not apply the translation associated with the matrix. Use
-     * {@link Matrix#mapPoints(float[], float[])} if you want the translation to be applied.
-     *
-     * @param dst   The array of dst vectors (x,y pairs)
-     * @param src   The array of src vectors (x,y pairs)
+     * @param dst The array of dst vectors (x,y pairs)
+     * @param src The array of src vectors (x,y pairs)
      */
     public void mapVectors(float[] dst, float[] src) {
         if (dst.length != src.length) {
@@ -694,8 +687,8 @@
     }
 
     /**
-     * Apply this matrix to the array of 2D points, and write the transformed
-     * points back into the array
+     * Apply this matrix to the array of 2D points, and write the transformed points back into the
+     * array
      *
      * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
      */
@@ -704,10 +697,8 @@
     }
 
     /**
-     * Apply this matrix to the array of 2D vectors, and write the transformed
-     * vectors back into the array.
-     *
-     * Note: this method does not apply the translation associated with the matrix. Use
+     * Apply this matrix to the array of 2D vectors, and write the transformed vectors back into the
+     * array. Note: this method does not apply the translation associated with the matrix. Use
      * {@link Matrix#mapPoints(float[])} if you want the translation to be applied.
      *
      * @param vecs The array [x0, y0, x1, y1, ...] of vectors to transform.
@@ -717,9 +708,9 @@
     }
 
     /**
-     * Apply this matrix to the src rectangle, and write the transformed
-     * rectangle into dst. This is accomplished by transforming the 4 corners of
-     * src, and then setting dst to the bounds of those points.
+     * Apply this matrix to the src rectangle, and write the transformed rectangle into dst. This is
+     * accomplished by transforming the 4 corners of src, and then setting dst to the bounds of
+     * those points.
      *
      * @param dst Where the transformed rectangle is written.
      * @param src The original rectangle to be transformed.
@@ -729,13 +720,13 @@
         if (dst == null || src == null) {
             throw new NullPointerException();
         }
-        return native_mapRect(native_instance, dst, src);
+        return nMapRect(native_instance, dst, src);
     }
 
     /**
-     * Apply this matrix to the rectangle, and write the transformed rectangle
-     * back into it. This is accomplished by transforming the 4 corners of rect,
-     * and then setting it to the bounds of those points
+     * Apply this matrix to the rectangle, and write the transformed rectangle back into it. This is
+     * accomplished by transforming the 4 corners of rect, and then setting it to the bounds of
+     * those points
      *
      * @param rect The rectangle to transform.
      * @return the result of calling rectStaysRect()
@@ -745,34 +736,33 @@
     }
 
     /**
-     * Return the mean radius of a circle after it has been mapped by
-     * this matrix. NOTE: in perspective this value assumes the circle
-     * has its center at the origin.
+     * Return the mean radius of a circle after it has been mapped by this matrix. NOTE: in
+     * perspective this value assumes the circle has its center at the origin.
      */
     public float mapRadius(float radius) {
-        return native_mapRadius(native_instance, radius);
+        return nMapRadius(native_instance, radius);
     }
 
-    /** Copy 9 values from the matrix into the array.
-    */
+    /**
+     * Copy 9 values from the matrix into the array.
+     */
     public void getValues(float[] values) {
         if (values.length < 9) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        native_getValues(native_instance, values);
+        nGetValues(native_instance, values);
     }
 
-    /** Copy 9 values from the array into the matrix.
-        Depending on the implementation of Matrix, these may be
-        transformed into 16.16 integers in the Matrix, such that
-        a subsequent call to getValues() will not yield exactly
-        the same values.
-    */
+    /**
+     * Copy 9 values from the array into the matrix. Depending on the implementation of Matrix,
+     * these may be transformed into 16.16 integers in the Matrix, such that a subsequent call to
+     * getValues() will not yield exactly the same values.
+     */
     public void setValues(float[] values) {
         if (values.length < 9) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        native_setValues(native_instance, values);
+        nSetValues(native_instance, values);
     }
 
     @Override
@@ -798,122 +788,155 @@
         float[] values = new float[9];
         getValues(values);
         sb.append('[');
-        sb.append(values[0]); sb.append(", "); sb.append(values[1]); sb.append(", ");
-        sb.append(values[2]); sb.append("][");
-        sb.append(values[3]); sb.append(", "); sb.append(values[4]); sb.append(", ");
-        sb.append(values[5]); sb.append("][");
-        sb.append(values[6]); sb.append(", "); sb.append(values[7]); sb.append(", ");
-        sb.append(values[8]); sb.append(']');
+        sb.append(values[0]);
+        sb.append(", ");
+        sb.append(values[1]);
+        sb.append(", ");
+        sb.append(values[2]);
+        sb.append("][");
+        sb.append(values[3]);
+        sb.append(", ");
+        sb.append(values[4]);
+        sb.append(", ");
+        sb.append(values[5]);
+        sb.append("][");
+        sb.append(values[6]);
+        sb.append(", ");
+        sb.append(values[7]);
+        sb.append(", ");
+        sb.append(values[8]);
+        sb.append(']');
     }
 
     /**
      * Print short string, to optimize dumping.
+     *
      * @hide
      */
     public void printShortString(PrintWriter pw) {
         float[] values = new float[9];
         getValues(values);
         pw.print('[');
-        pw.print(values[0]); pw.print(", "); pw.print(values[1]); pw.print(", ");
-                pw.print(values[2]); pw.print("][");
-        pw.print(values[3]); pw.print(", "); pw.print(values[4]); pw.print(", ");
-                pw.print(values[5]); pw.print("][");
-        pw.print(values[6]); pw.print(", "); pw.print(values[7]); pw.print(", ");
-                pw.print(values[8]); pw.print(']');
+        pw.print(values[0]);
+        pw.print(", ");
+        pw.print(values[1]);
+        pw.print(", ");
+        pw.print(values[2]);
+        pw.print("][");
+        pw.print(values[3]);
+        pw.print(", ");
+        pw.print(values[4]);
+        pw.print(", ");
+        pw.print(values[5]);
+        pw.print("][");
+        pw.print(values[6]);
+        pw.print(", ");
+        pw.print(values[7]);
+        pw.print(", ");
+        pw.print(values[8]);
+        pw.print(']');
 
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            finalizer(native_instance);
-            native_instance = 0;  // Other finalizers can still call us.
-        } finally {
-            super.finalize();
-        }
-    }
-
-    /*package*/ final long ni() {
+    /* package */ final long ni() {
         return native_instance;
     }
 
-    private static native long native_create(long native_src_or_zero);
-    private static native boolean native_isIdentity(long native_object);
-    private static native boolean native_isAffine(long native_object);
-    private static native boolean native_rectStaysRect(long native_object);
-    private static native void native_reset(long native_object);
-    private static native void native_set(long native_object,
-                                          long native_other);
-    private static native void native_setTranslate(long native_object,
-                                                   float dx, float dy);
-    private static native void native_setScale(long native_object,
-                                        float sx, float sy, float px, float py);
-    private static native void native_setScale(long native_object,
-                                               float sx, float sy);
-    private static native void native_setRotate(long native_object,
-                                            float degrees, float px, float py);
-    private static native void native_setRotate(long native_object,
-                                                float degrees);
-    private static native void native_setSinCos(long native_object,
-                            float sinValue, float cosValue, float px, float py);
-    private static native void native_setSinCos(long native_object,
-                                                float sinValue, float cosValue);
-    private static native void native_setSkew(long native_object,
-                                        float kx, float ky, float px, float py);
-    private static native void native_setSkew(long native_object,
-                                              float kx, float ky);
-    private static native void native_setConcat(long native_object,
-                                                long native_a,
-                                                long native_b);
-    private static native void native_preTranslate(long native_object,
-                                                   float dx, float dy);
-    private static native void native_preScale(long native_object,
-                                               float sx, float sy, float px, float py);
-    private static native void native_preScale(long native_object,
-                                               float sx, float sy);
-    private static native void native_preRotate(long native_object,
-                                                float degrees, float px, float py);
-    private static native void native_preRotate(long native_object,
-                                                float degrees);
-    private static native void native_preSkew(long native_object,
-                                              float kx, float ky, float px, float py);
-    private static native void native_preSkew(long native_object,
-                                              float kx, float ky);
-    private static native void native_preConcat(long native_object,
-                                                long native_other_matrix);
-    private static native void native_postTranslate(long native_object,
-                                                    float dx, float dy);
-    private static native void native_postScale(long native_object,
-                                                float sx, float sy, float px, float py);
-    private static native void native_postScale(long native_object,
-                                                float sx, float sy);
-    private static native void native_postRotate(long native_object,
-                                                 float degrees, float px, float py);
-    private static native void native_postRotate(long native_object,
-                                                 float degrees);
-    private static native void native_postSkew(long native_object,
-                                               float kx, float ky, float px, float py);
-    private static native void native_postSkew(long native_object,
-                                               float kx, float ky);
-    private static native void native_postConcat(long native_object,
-                                                 long native_other_matrix);
-    private static native boolean native_setRectToRect(long native_object,
-                                                RectF src, RectF dst, int stf);
-    private static native boolean native_setPolyToPoly(long native_object,
-        float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount);
-    private static native boolean native_invert(long native_object,
-                                                long native_inverse);
-    private static native void native_mapPoints(long native_object,
-                        float[] dst, int dstIndex, float[] src, int srcIndex,
-                        int ptCount, boolean isPts);
-    private static native boolean native_mapRect(long native_object,
-                                                 RectF dst, RectF src);
-    private static native float native_mapRadius(long native_object,
-                                                 float radius);
-    private static native void native_getValues(long native_object,
-                                                float[] values);
-    private static native void native_setValues(long native_object,
-                                                float[] values);
-    private static native boolean native_equals(long native_a, long native_b);
-    private static native void finalizer(long native_instance);
+    // ------------------ Regular JNI ------------------------
+
+    private static native long nCreate(long nSrc_or_zero);
+    private static native long nGetNativeFinalizer();
+
+
+    // ------------------ Fast JNI ------------------------
+
+    @FastNative
+    private static native boolean nSetRectToRect(long nObject,
+            RectF src, RectF dst, int stf);
+    @FastNative
+    private static native boolean nSetPolyToPoly(long nObject,
+            float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount);
+    @FastNative
+    private static native void nMapPoints(long nObject,
+            float[] dst, int dstIndex, float[] src, int srcIndex,
+            int ptCount, boolean isPts);
+    @FastNative
+    private static native boolean nMapRect(long nObject, RectF dst, RectF src);
+    @FastNative
+    private static native void nGetValues(long nObject, float[] values);
+    @FastNative
+    private static native void nSetValues(long nObject, float[] values);
+
+
+    // ------------------ Critical JNI ------------------------
+
+    @CriticalNative
+    private static native boolean nIsIdentity(long nObject);
+    @CriticalNative
+    private static native boolean nIsAffine(long nObject);
+    @CriticalNative
+    private static native boolean nRectStaysRect(long nObject);
+    @CriticalNative
+    private static native void nReset(long nObject);
+    @CriticalNative
+    private static native void nSet(long nObject, long nOther);
+    @CriticalNative
+    private static native void nSetTranslate(long nObject, float dx, float dy);
+    @CriticalNative
+    private static native void nSetScale(long nObject, float sx, float sy, float px, float py);
+    @CriticalNative
+    private static native void nSetScale(long nObject, float sx, float sy);
+    @CriticalNative
+    private static native void nSetRotate(long nObject, float degrees, float px, float py);
+    @CriticalNative
+    private static native void nSetRotate(long nObject, float degrees);
+    @CriticalNative
+    private static native void nSetSinCos(long nObject, float sinValue, float cosValue,
+            float px, float py);
+    @CriticalNative
+    private static native void nSetSinCos(long nObject, float sinValue, float cosValue);
+    @CriticalNative
+    private static native void nSetSkew(long nObject, float kx, float ky, float px, float py);
+    @CriticalNative
+    private static native void nSetSkew(long nObject, float kx, float ky);
+    @CriticalNative
+    private static native void nSetConcat(long nObject, long nA, long nB);
+    @CriticalNative
+    private static native void nPreTranslate(long nObject, float dx, float dy);
+    @CriticalNative
+    private static native void nPreScale(long nObject, float sx, float sy, float px, float py);
+    @CriticalNative
+    private static native void nPreScale(long nObject, float sx, float sy);
+    @CriticalNative
+    private static native void nPreRotate(long nObject, float degrees, float px, float py);
+    @CriticalNative
+    private static native void nPreRotate(long nObject, float degrees);
+    @CriticalNative
+    private static native void nPreSkew(long nObject, float kx, float ky, float px, float py);
+    @CriticalNative
+    private static native void nPreSkew(long nObject, float kx, float ky);
+    @CriticalNative
+    private static native void nPreConcat(long nObject, long nOther_matrix);
+    @CriticalNative
+    private static native void nPostTranslate(long nObject, float dx, float dy);
+    @CriticalNative
+    private static native void nPostScale(long nObject, float sx, float sy, float px, float py);
+    @CriticalNative
+    private static native void nPostScale(long nObject, float sx, float sy);
+    @CriticalNative
+    private static native void nPostRotate(long nObject, float degrees, float px, float py);
+    @CriticalNative
+    private static native void nPostRotate(long nObject, float degrees);
+    @CriticalNative
+    private static native void nPostSkew(long nObject, float kx, float ky, float px, float py);
+    @CriticalNative
+    private static native void nPostSkew(long nObject, float kx, float ky);
+    @CriticalNative
+    private static native void nPostConcat(long nObject, long nOther_matrix);
+    @CriticalNative
+    private static native boolean nInvert(long nObject, long nInverse);
+    @CriticalNative
+    private static native float nMapRadius(long nObject, float radius);
+    @CriticalNative
+    private static native boolean nEquals(long nA, long nB);
 }